-- Per-connection publish governance (publish-phase gate). -- -- connections.fields.publishGovernance selects what happens once a draft is -- approved: unset = manual publish (today), 'auto' = dispatch on approval, -- 'admin1' | 'admin_majority' | 'admin_consensus' = a SECOND chatgov poll -- (subject_kind 'draft_publish', kind yes_no) must pass before the publish -- is scheduled. The setting itself lives in the established fields jsonb; -- this migration only teaches `polls` about the publish-phase subject. -- -- publish_connection_id the destination the publish poll releases to -- publish_request {publishAt, requiredPermission} captured at hold -- time; the requester is polls.created_by and stays -- the scheduling principal (re-checked at claim). ALTER TABLE polls DROP CONSTRAINT polls_subject_kind_check; ALTER TABLE polls ADD CONSTRAINT polls_subject_kind_check CHECK (subject_kind IN ('draft', 'chat_post', 'none', 'draft_publish')); ALTER TABLE polls ADD COLUMN publish_connection_id uuid, ADD COLUMN publish_request jsonb CHECK (publish_request IS NULL OR jsonb_typeof(publish_request) = 'object'); ALTER TABLE polls ADD CONSTRAINT polls_publish_connection_fk FOREIGN KEY (publish_connection_id, workspace_id) REFERENCES connections (id, workspace_id) ON DELETE NO ACTION ON UPDATE RESTRICT; ALTER TABLE polls ADD CONSTRAINT polls_publish_subject_check CHECK ( (subject_kind = 'draft_publish') = (publish_connection_id IS NOT NULL) AND (subject_kind <> 'draft_publish' OR (draft_id IS NOT NULL AND publish_request IS NOT NULL)) ); -- One open REVIEW gate per draft stays index-enforced; publish gates get -- their own slot per (draft, destination) so they never collide with it. DROP INDEX polls_open_one_per_draft; CREATE UNIQUE INDEX polls_open_one_per_draft ON polls (workspace_id, draft_id) WHERE state = 'open' AND draft_id IS NOT NULL AND subject_kind <> 'draft_publish'; CREATE UNIQUE INDEX polls_open_one_per_publish ON polls (workspace_id, draft_id, publish_connection_id) WHERE state = 'open' AND subject_kind = 'draft_publish'; CREATE INDEX polls_ws_publish ON polls (workspace_id, draft_id, publish_connection_id, created_at DESC) WHERE subject_kind = 'draft_publish';