-- Migration 060: Multi-Layer Control Architecture — DB Schema -- Adds obligation_extractions, control_patterns, and crosswalk_matrix tables. -- Extends canonical_controls with pattern_id and obligation_ids columns. -- -- Part of the Multi-Layer Control Architecture (Phase 1 of 8). -- See: Legal Source → Obligation → Control Pattern → Master Control → Customer Instance -- ============================================================================= -- 1. Obligation Extractions -- Tracks how each RAG chunk was linked to an obligation (exact, embedding, LLM). -- ============================================================================= CREATE TABLE IF NOT EXISTS obligation_extractions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), chunk_hash VARCHAR(64) NOT NULL, collection VARCHAR(100) NOT NULL, regulation_code VARCHAR(100) NOT NULL, article VARCHAR(100), paragraph VARCHAR(100), obligation_id VARCHAR(50), obligation_text TEXT, confidence NUMERIC(3,2) CHECK (confidence >= 0 AND confidence <= 1), extraction_method VARCHAR(30) NOT NULL CHECK (extraction_method IN ('exact_match', 'embedding_match', 'llm_extracted', 'inferred')), pattern_id VARCHAR(50), pattern_match_score NUMERIC(3,2) CHECK (pattern_match_score >= 0 AND pattern_match_score <= 1), control_uuid UUID REFERENCES canonical_controls(id), job_id UUID REFERENCES canonical_generation_jobs(id), created_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_oe_obligation ON obligation_extractions(obligation_id); CREATE INDEX IF NOT EXISTS idx_oe_pattern ON obligation_extractions(pattern_id); CREATE INDEX IF NOT EXISTS idx_oe_control ON obligation_extractions(control_uuid); CREATE INDEX IF NOT EXISTS idx_oe_regulation ON obligation_extractions(regulation_code); CREATE INDEX IF NOT EXISTS idx_oe_chunk ON obligation_extractions(chunk_hash); CREATE INDEX IF NOT EXISTS idx_oe_method ON obligation_extractions(extraction_method); COMMENT ON TABLE obligation_extractions IS 'Tracks chunk-to-obligation linkage from the 3-tier extraction pipeline (exact/embedding/LLM)'; -- ============================================================================= -- 2. Control Patterns Registry -- DB mirror of the YAML pattern library for SQL queries and joins. -- ============================================================================= CREATE TABLE IF NOT EXISTS control_patterns ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), pattern_id VARCHAR(50) UNIQUE NOT NULL, name VARCHAR(255) NOT NULL, name_de VARCHAR(255), domain VARCHAR(10) NOT NULL, category VARCHAR(50), description TEXT, template_objective TEXT, template_rationale TEXT, template_requirements JSONB DEFAULT '[]', template_test_procedure JSONB DEFAULT '[]', template_evidence JSONB DEFAULT '[]', severity_default VARCHAR(20) CHECK (severity_default IN ('low', 'medium', 'high', 'critical')), implementation_effort_default VARCHAR(2) CHECK (implementation_effort_default IN ('s', 'm', 'l', 'xl')), obligation_match_keywords JSONB DEFAULT '[]', tags JSONB DEFAULT '[]', open_anchor_refs JSONB DEFAULT '[]', composable_with JSONB DEFAULT '[]', version VARCHAR(10) DEFAULT '1.0', created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_cp_domain ON control_patterns(domain); CREATE INDEX IF NOT EXISTS idx_cp_category ON control_patterns(category); CREATE INDEX IF NOT EXISTS idx_cp_pattern_id ON control_patterns(pattern_id); COMMENT ON TABLE control_patterns IS 'Registry of control patterns (DB mirror of YAML library). Pattern ID format: CP-{DOMAIN}-{NNN}'; -- ============================================================================= -- 3. Crosswalk Matrix -- The "golden thread" from legal source through to implementation. -- ============================================================================= CREATE TABLE IF NOT EXISTS crosswalk_matrix ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), regulation_code VARCHAR(100) NOT NULL, article VARCHAR(100), paragraph VARCHAR(100), obligation_id VARCHAR(50), pattern_id VARCHAR(50), master_control_id VARCHAR(20), master_control_uuid UUID REFERENCES canonical_controls(id), tom_control_id VARCHAR(30), confidence NUMERIC(3,2) CHECK (confidence >= 0 AND confidence <= 1), source VARCHAR(30) DEFAULT 'auto' CHECK (source IN ('manual', 'auto', 'migrated')), created_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_cw_regulation ON crosswalk_matrix(regulation_code, article); CREATE INDEX IF NOT EXISTS idx_cw_obligation ON crosswalk_matrix(obligation_id); CREATE INDEX IF NOT EXISTS idx_cw_pattern ON crosswalk_matrix(pattern_id); CREATE INDEX IF NOT EXISTS idx_cw_control ON crosswalk_matrix(master_control_id); CREATE INDEX IF NOT EXISTS idx_cw_tom ON crosswalk_matrix(tom_control_id); COMMENT ON TABLE crosswalk_matrix IS 'Golden thread: regulation → article → obligation → pattern → master control → TOM'; -- ============================================================================= -- 4. Extend canonical_controls with pattern + obligation linkage -- ============================================================================= ALTER TABLE canonical_controls ADD COLUMN IF NOT EXISTS pattern_id VARCHAR(50); ALTER TABLE canonical_controls ADD COLUMN IF NOT EXISTS obligation_ids JSONB DEFAULT '[]'; CREATE INDEX IF NOT EXISTS idx_cc_pattern ON canonical_controls(pattern_id);