-- Migration 0036: Approval workflow schema (VS-03) -- Creates tables for model activation approval gates with maker-checker separation CREATE TABLE IF NOT EXISTS model_operations.approval_proposals ( id UUID PRIMARY KEY, model_id UUID NOT NULL REFERENCES model_operations.models(id), status VARCHAR(50) NOT NULL, created_by VARCHAR(255) NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), justification TEXT NOT NULL, effective_at DATE NOT NULL, proposed_at TIMESTAMPTZ, approved_by VARCHAR(255), approved_at TIMESTAMPTZ, approval_notes TEXT, activated_by VARCHAR(255), activated_at TIMESTAMPTZ, published_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), revision INT NOT NULL DEFAULT 1, correlation_id UUID NOT NULL ); CREATE INDEX IF NOT EXISTS ix_approval_proposals_model_id ON model_operations.approval_proposals(model_id); CREATE INDEX IF NOT EXISTS ix_approval_proposals_status ON model_operations.approval_proposals(status); CREATE INDEX IF NOT EXISTS ix_approval_proposals_created_by ON model_operations.approval_proposals(created_by); CREATE INDEX IF NOT EXISTS ix_approval_proposals_approved_by ON model_operations.approval_proposals(approved_by); CREATE INDEX IF NOT EXISTS ix_approval_proposals_correlation_id ON model_operations.approval_proposals(correlation_id); CREATE TABLE IF NOT EXISTS model_operations.approval_evidence ( id UUID PRIMARY KEY, approval_proposal_id UUID NOT NULL REFERENCES model_operations.approval_proposals(id), evidence_type VARCHAR(50) NOT NULL, evidence_url TEXT NOT NULL, reviewer_comment TEXT, published_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), correlation_id UUID NOT NULL ); CREATE INDEX IF NOT EXISTS ix_approval_evidence_proposal_id ON model_operations.approval_evidence(approval_proposal_id); CREATE INDEX IF NOT EXISTS ix_approval_evidence_type ON model_operations.approval_evidence(evidence_type); CREATE INDEX IF NOT EXISTS ix_approval_evidence_correlation_id ON model_operations.approval_evidence(correlation_id); CREATE TABLE IF NOT EXISTS model_operations.approval_events ( id UUID PRIMARY KEY, approval_proposal_id UUID NOT NULL REFERENCES model_operations.approval_proposals(id), event_type VARCHAR(50) NOT NULL, actor_email VARCHAR(255) NOT NULL, event_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), details JSONB, published_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), correlation_id UUID NOT NULL ); CREATE INDEX IF NOT EXISTS ix_approval_events_proposal_id ON model_operations.approval_events(approval_proposal_id); CREATE INDEX IF NOT EXISTS ix_approval_events_type ON model_operations.approval_events(event_type); CREATE INDEX IF NOT EXISTS ix_approval_events_correlation_id ON model_operations.approval_events(correlation_id);