Implement full evidence integrity pipeline to prevent compliance theater: - Confidence levels (E0-E4), truth status tracking, assertion engine - Four-Eyes approval workflow, audit trail, reject endpoint - Evidence distribution dashboard, LLM audit routes - Traceability matrix (backend endpoint + Compliance Hub UI tab) - Anti-fake badges, control status machine, normative patterns - 2 migrations, 4 test suites, MkDocs documentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
126 lines
5.8 KiB
SQL
126 lines
5.8 KiB
SQL
-- Migration 076: Anti-Fake-Evidence Guardrails (Phase 1)
|
|
--
|
|
-- Prevents "Compliance-Theater": generated content passed off as real evidence,
|
|
-- controls without evidence marked as "pass", unvalidated 100% compliance claims.
|
|
--
|
|
-- Changes:
|
|
-- 1. New ENUM types for evidence confidence + truth status
|
|
-- 2. New columns on compliance_evidence (confidence, truth, review tracking)
|
|
-- 3. New value 'in_progress' for controlstatusenum
|
|
-- 4. status_justification column on compliance_controls
|
|
-- 5. New table compliance_llm_generation_audit
|
|
-- 6. Backfill existing evidence based on source
|
|
-- 7. Indexes on new columns
|
|
|
|
-- ============================================================================
|
|
-- 1. New ENUM types
|
|
-- ============================================================================
|
|
|
|
-- NOTE: CREATE TYPE cannot run inside a transaction block when combined with
|
|
-- ALTER TYPE ... ADD VALUE. Each statement here is auto-committed separately
|
|
-- when executed outside a transaction (which is the default for psql scripts).
|
|
|
|
CREATE TYPE evidence_confidence_level AS ENUM (
|
|
'E0', -- Generated / no real evidence (LLM output, placeholder)
|
|
'E1', -- Uploaded but unreviewed (manual upload, no hash, no reviewer)
|
|
'E2', -- Reviewed internally (human reviewed, hash verified)
|
|
'E3', -- Observed by system (CI/CD pipeline, API with hash)
|
|
'E4' -- Validated by external auditor
|
|
);
|
|
|
|
CREATE TYPE evidence_truth_status AS ENUM (
|
|
'generated', -- Created by LLM / system generation
|
|
'uploaded', -- Manually uploaded by user
|
|
'observed', -- Automatically observed (CI/CD, monitoring)
|
|
'validated_internal', -- Reviewed + approved by internal reviewer
|
|
'rejected', -- Reviewed and rejected
|
|
'provided_to_auditor', -- Shared with external auditor
|
|
'accepted_by_auditor' -- Accepted by external auditor
|
|
);
|
|
|
|
-- ============================================================================
|
|
-- 2. Add 'in_progress' to controlstatusenum
|
|
-- ============================================================================
|
|
-- ALTER TYPE ... ADD VALUE cannot run inside a transaction.
|
|
|
|
ALTER TYPE controlstatusenum ADD VALUE IF NOT EXISTS 'in_progress';
|
|
|
|
-- ============================================================================
|
|
-- 3. New columns on compliance_evidence
|
|
-- ============================================================================
|
|
|
|
ALTER TABLE compliance_evidence
|
|
ADD COLUMN IF NOT EXISTS confidence_level evidence_confidence_level DEFAULT 'E1',
|
|
ADD COLUMN IF NOT EXISTS truth_status evidence_truth_status DEFAULT 'uploaded',
|
|
ADD COLUMN IF NOT EXISTS generation_mode VARCHAR(100),
|
|
ADD COLUMN IF NOT EXISTS may_be_used_as_evidence BOOLEAN DEFAULT TRUE,
|
|
ADD COLUMN IF NOT EXISTS reviewed_by VARCHAR(200),
|
|
ADD COLUMN IF NOT EXISTS reviewed_at TIMESTAMPTZ;
|
|
|
|
-- ============================================================================
|
|
-- 4. status_justification on compliance_controls
|
|
-- ============================================================================
|
|
|
|
ALTER TABLE compliance_controls
|
|
ADD COLUMN IF NOT EXISTS status_justification TEXT;
|
|
|
|
-- ============================================================================
|
|
-- 5. LLM Generation Audit table
|
|
-- ============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS compliance_llm_generation_audit (
|
|
id VARCHAR(36) PRIMARY KEY DEFAULT gen_random_uuid()::text,
|
|
tenant_id VARCHAR(36),
|
|
entity_type VARCHAR(50) NOT NULL, -- 'evidence', 'control', 'document', ...
|
|
entity_id VARCHAR(36), -- FK to the generated entity
|
|
generation_mode VARCHAR(100) NOT NULL, -- 'draft_assistance', 'auto_generation', ...
|
|
truth_status evidence_truth_status NOT NULL DEFAULT 'generated',
|
|
may_be_used_as_evidence BOOLEAN NOT NULL DEFAULT FALSE,
|
|
llm_model VARCHAR(100),
|
|
llm_provider VARCHAR(50), -- 'ollama', 'anthropic', ...
|
|
prompt_hash VARCHAR(64), -- SHA-256 of the prompt
|
|
input_summary TEXT, -- Truncated input for auditability
|
|
output_summary TEXT, -- Truncated output for auditability
|
|
metadata JSONB DEFAULT '{}'::jsonb,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
-- ============================================================================
|
|
-- 6. Backfill existing evidence based on source
|
|
-- ============================================================================
|
|
|
|
-- CI pipeline evidence → E3 + observed
|
|
UPDATE compliance_evidence
|
|
SET confidence_level = 'E3',
|
|
truth_status = 'observed'
|
|
WHERE source = 'ci_pipeline'
|
|
AND confidence_level = 'E1';
|
|
|
|
-- API evidence → E3 + observed
|
|
UPDATE compliance_evidence
|
|
SET confidence_level = 'E3',
|
|
truth_status = 'observed'
|
|
WHERE source = 'api'
|
|
AND confidence_level = 'E1';
|
|
|
|
-- Manual/upload evidence stays at E1 + uploaded (default)
|
|
|
|
-- Generated evidence → E0 + generated
|
|
UPDATE compliance_evidence
|
|
SET confidence_level = 'E0',
|
|
truth_status = 'generated',
|
|
may_be_used_as_evidence = FALSE
|
|
WHERE source = 'generated'
|
|
AND confidence_level = 'E1';
|
|
|
|
-- ============================================================================
|
|
-- 7. Indexes
|
|
-- ============================================================================
|
|
|
|
CREATE INDEX IF NOT EXISTS ix_evidence_confidence ON compliance_evidence (confidence_level);
|
|
CREATE INDEX IF NOT EXISTS ix_evidence_truth_status ON compliance_evidence (truth_status);
|
|
CREATE INDEX IF NOT EXISTS ix_evidence_may_be_used ON compliance_evidence (may_be_used_as_evidence);
|
|
CREATE INDEX IF NOT EXISTS ix_llm_audit_entity ON compliance_llm_generation_audit (entity_type, entity_id);
|
|
CREATE INDEX IF NOT EXISTS ix_llm_audit_tenant ON compliance_llm_generation_audit (tenant_id);
|