-- Feedback categories, managed from the admin panel instead of hard-coded in -- the app and the BFF. -- -- `key` is what feedback.category stores, and never changes once created — -- so renaming a category in the admin relabels every past submission too. -- Archiving hides a category from the /feedback form while existing feedback -- keeps its label. There is deliberately no foreign key from feedback: the -- column predates this table, and the admin only hard-deletes categories -- nothing uses. CREATE TABLE IF NOT EXISTS feedback_categories ( key TEXT PRIMARY KEY, label TEXT NOT NULL, description TEXT NOT NULL DEFAULT '', sort_order INTEGER NOT NULL DEFAULT 0, archived_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); -- The four categories the app offered until now, with the exact labels and -- descriptions its form showed, in the form's order. Production feedback -- already uses these keys, so they must stay byte-for-byte the same. INSERT INTO feedback_categories (key, label, description, sort_order) VALUES ('general', 'General feedback', 'Thoughts, impressions, suggestions — anything else.', 0), ('bug', 'Bug report', 'Something is broken or behaving unexpectedly.', 1), ('feature', 'Feature request', 'An idea for something new on the site.', 2), ('other', 'Other', 'Doesn''t fit the above? Use this.', 3) ON CONFLICT (key) DO NOTHING; -- Safety net: any other key already present in feedback (from an older -- client) gets a category too — archived, so it isn't offered on the form, -- but its submissions still carry a readable label. INSERT INTO feedback_categories (key, label, sort_order, archived_at) SELECT DISTINCT f.category, initcap(replace(f.category, '_', ' ')), 100, now() FROM feedback f WHERE NOT EXISTS (SELECT 1 FROM feedback_categories c WHERE c.key = f.category) ON CONFLICT (key) DO NOTHING; -- The Admin role may manage them; Superadmin already has '*'. UPDATE admin_roles SET permissions = array_append(permissions, 'feedback:categories') WHERE key = 'admin' AND NOT ('feedback:categories' = ANY(permissions));