-- Migration 006: Decision Traces (G1) -- Schema: compliance -- Run: ssh macmini "docker exec -i bp-core-postgres psql -U breakpilot -d breakpilot_db" < control-pipeline/migrations/006_decision_traces.sql SET search_path TO compliance, public; CREATE TABLE IF NOT EXISTS decision_traces ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), control_uuid UUID NOT NULL, regulation_id VARCHAR(100), obligation_id VARCHAR(100), -- Decision status VARCHAR(30) NOT NULL DEFAULT 'not_assessed' CHECK (status IN ('not_assessed', 'compliant', 'partially_compliant', 'not_compliant', 'not_applicable', 'under_remediation')), decision_reason TEXT, decided_by VARCHAR(100), decided_at TIMESTAMPTZ, -- Fix/Remediation fix_strategy TEXT, fix_owner VARCHAR(100), fix_target_date DATE, fix_completed_date DATE, -- Evidence evidence_ids JSONB DEFAULT '[]', confidence NUMERIC(3,2) DEFAULT 0.0, -- Multi-tenant tenant_id UUID, project_id UUID, metadata JSONB DEFAULT '{}', created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_dt_control ON decision_traces(control_uuid); CREATE INDEX IF NOT EXISTS idx_dt_status ON decision_traces(status); CREATE INDEX IF NOT EXISTS idx_dt_tenant ON decision_traces(tenant_id); CREATE INDEX IF NOT EXISTS idx_dt_decided_at ON decision_traces(decided_at); -- Updated-at trigger CREATE OR REPLACE FUNCTION update_decision_traces_updated_at() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $$ LANGUAGE plpgsql; DROP TRIGGER IF EXISTS trg_decision_traces_updated_at ON decision_traces; CREATE TRIGGER trg_decision_traces_updated_at BEFORE UPDATE ON decision_traces FOR EACH ROW EXECUTE FUNCTION update_decision_traces_updated_at();