-- Kanban Labels System -- Adds label/tag support to kanban cards for categorization and filtering -- Labels table (org-scoped) CREATE TABLE IF NOT EXISTS kanban_labels ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), org_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE, name TEXT NOT NULL, color TEXT NOT NULL DEFAULT '#6366f1', created_at TIMESTAMPTZ DEFAULT now(), UNIQUE(org_id, name) ); -- Card-Label junction table (many-to-many) CREATE TABLE IF NOT EXISTS card_labels ( card_id UUID NOT NULL REFERENCES kanban_cards(id) ON DELETE CASCADE, label_id UUID NOT NULL REFERENCES kanban_labels(id) ON DELETE CASCADE, created_at TIMESTAMPTZ DEFAULT now(), PRIMARY KEY (card_id, label_id) ); -- Enable RLS ALTER TABLE kanban_labels ENABLE ROW LEVEL SECURITY; ALTER TABLE card_labels ENABLE ROW LEVEL SECURITY; -- Labels accessible to org members CREATE POLICY "Labels accessible to org members" ON kanban_labels FOR ALL USING ( EXISTS ( SELECT 1 FROM org_members m WHERE m.org_id = kanban_labels.org_id AND m.user_id = auth.uid() ) ); -- Card labels inherit card access CREATE POLICY "Card labels inherit card access" ON card_labels FOR ALL USING ( EXISTS ( SELECT 1 FROM kanban_cards c JOIN kanban_columns col ON c.column_id = col.id JOIN kanban_boards b ON col.board_id = b.id JOIN org_members m ON b.org_id = m.org_id WHERE c.id = card_labels.card_id AND m.user_id = auth.uid() ) ); -- Indexes for performance CREATE INDEX IF NOT EXISTS idx_kanban_labels_org ON kanban_labels(org_id); CREATE INDEX IF NOT EXISTS idx_card_labels_card ON card_labels(card_id); CREATE INDEX IF NOT EXISTS idx_card_labels_label ON card_labels(label_id); -- Seed default labels for existing organizations INSERT INTO kanban_labels (org_id, name, color) SELECT DISTINCT o.id, label.name, label.color FROM organizations o CROSS JOIN ( VALUES ('Bug', '#ef4444'), ('Feature', '#22c55e'), ('Enhancement', '#3b82f6'), ('Documentation', '#a855f7'), ('Urgent', '#f97316') ) AS label(name, color) ON CONFLICT (org_id, name) DO NOTHING;