-- Migration 044: Canonical Control Library
-- Provides a legally defensible, independently authored security control library.
-- Controls are formulated independently (no BSI/proprietary nomenclature).
-- Every control MUST have open-source anchors (OWASP, NIST, ENISA).
-- Source provenance is tracked internally for audit, never shipped in product.
--
-- Tables:
--   1. canonical_control_licenses     — License metadata for source materials
--   2. canonical_control_sources      — Source registry (internal, not product-facing)
--   3. canonical_control_frameworks   — Registered control frameworks
--   4. canonical_controls             — The actual controls (product-facing)
--   5. canonical_control_mappings     — Provenance trail (internal audit)

BEGIN;

-- =============================================================================
-- 1. License Metadata
-- =============================================================================

CREATE TABLE IF NOT EXISTS canonical_control_licenses (
    license_id VARCHAR(50) PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    terms_url TEXT,
    commercial_use VARCHAR(20) NOT NULL
        CHECK (commercial_use IN ('allowed', 'restricted', 'prohibited', 'unclear')),
    ai_training_restriction VARCHAR(20),
    tdm_allowed_under_44b VARCHAR(10)
        CHECK (tdm_allowed_under_44b IN ('yes', 'no', 'unclear')),
    deletion_required BOOLEAN DEFAULT false,
    notes TEXT,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- =============================================================================
-- 2. Source Registry (internal — never shipped in product)
-- =============================================================================

CREATE TABLE IF NOT EXISTS canonical_control_sources (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    source_id VARCHAR(50) UNIQUE NOT NULL,
    title VARCHAR(500) NOT NULL,
    publisher VARCHAR(100) NOT NULL,
    url TEXT,
    version_label VARCHAR(50),
    language VARCHAR(5) DEFAULT 'de',
    license_id VARCHAR(50) NOT NULL
        REFERENCES canonical_control_licenses(license_id),
    allowed_analysis BOOLEAN DEFAULT false,
    allowed_store_excerpt BOOLEAN DEFAULT false,
    allowed_ship_embeddings BOOLEAN DEFAULT false,
    allowed_ship_in_product BOOLEAN DEFAULT false,
    vault_retention_days INTEGER DEFAULT 30,
    vault_access_tier VARCHAR(20) DEFAULT 'restricted'
        CHECK (vault_access_tier IN ('restricted', 'internal', 'public')),
    retrieved_at TIMESTAMPTZ,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_ccs_license ON canonical_control_sources(license_id);

-- =============================================================================
-- 3. Control Frameworks
-- =============================================================================

CREATE TABLE IF NOT EXISTS canonical_control_frameworks (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    framework_id VARCHAR(50) UNIQUE NOT NULL,
    name VARCHAR(255) NOT NULL,
    version VARCHAR(20) NOT NULL,
    description TEXT,
    owner VARCHAR(100) DEFAULT 'security-platform',
    policy_version VARCHAR(20),
    release_state VARCHAR(20) DEFAULT 'draft'
        CHECK (release_state IN ('draft', 'review', 'approved', 'deprecated')),
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- =============================================================================
-- 4. Canonical Controls (product-facing)
-- =============================================================================

CREATE TABLE IF NOT EXISTS canonical_controls (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    framework_id UUID NOT NULL
        REFERENCES canonical_control_frameworks(id),
    control_id VARCHAR(20) NOT NULL,
    title VARCHAR(255) NOT NULL,
    objective TEXT NOT NULL,
    rationale TEXT NOT NULL,
    scope JSONB NOT NULL DEFAULT '{}',
    requirements JSONB NOT NULL DEFAULT '[]',
    test_procedure JSONB NOT NULL DEFAULT '[]',
    evidence JSONB NOT NULL DEFAULT '[]',
    severity VARCHAR(20) NOT NULL
        CHECK (severity IN ('low', 'medium', 'high', 'critical')),
    risk_score NUMERIC(3,1) CHECK (risk_score >= 0 AND risk_score <= 10),
    implementation_effort VARCHAR(2)
        CHECK (implementation_effort IN ('s', 'm', 'l', 'xl')),
    evidence_confidence NUMERIC(3,2) CHECK (evidence_confidence >= 0 AND evidence_confidence <= 1),
    open_anchors JSONB NOT NULL DEFAULT '[]',
    release_state VARCHAR(20) DEFAULT 'draft'
        CHECK (release_state IN ('draft', 'review', 'approved', 'deprecated')),
    tags JSONB DEFAULT '[]',
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW(),
    UNIQUE (framework_id, control_id)
);

CREATE INDEX IF NOT EXISTS idx_canonical_controls_domain
    ON canonical_controls ((LEFT(control_id, 4)));
CREATE INDEX IF NOT EXISTS idx_canonical_controls_severity
    ON canonical_controls (severity);
CREATE INDEX IF NOT EXISTS idx_canonical_controls_release
    ON canonical_controls (release_state);
CREATE INDEX IF NOT EXISTS idx_canonical_controls_framework
    ON canonical_controls (framework_id);

-- =============================================================================
-- 5. Control Mappings / Provenance (internal audit trail)
-- =============================================================================

CREATE TABLE IF NOT EXISTS canonical_control_mappings (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    control_id UUID NOT NULL
        REFERENCES canonical_controls(id) ON DELETE CASCADE,
    source_id UUID NOT NULL
        REFERENCES canonical_control_sources(id),
    mapping_type VARCHAR(30) NOT NULL
        CHECK (mapping_type IN ('inspired_by_internal', 'corroborated_by_open', 'derived_only_open')),
    attribution_class VARCHAR(20) NOT NULL
        CHECK (attribution_class IN ('internal_only', 'product_ok')),
    source_locator VARCHAR(100),
    paraphrase_note TEXT,
    excerpt_hashes JSONB DEFAULT '[]',
    similarity_report JSONB,
    reviewed_by VARCHAR(100),
    reviewed_at TIMESTAMPTZ,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_ccm_control ON canonical_control_mappings(control_id);
CREATE INDEX IF NOT EXISTS idx_ccm_source ON canonical_control_mappings(source_id);

-- =============================================================================
-- SEED: Licenses
-- =============================================================================

INSERT INTO canonical_control_licenses (license_id, name, terms_url, commercial_use, ai_training_restriction, tdm_allowed_under_44b, deletion_required, notes)
VALUES
    ('BSI_TOS_2025', 'BSI Nutzungsbedingungen', 'https://www.bsi.bund.de/impressum', 'restricted', 'unclear', 'yes', true,
     'Kommerziell nur mit Zustimmung. TDM unter UrhG 44b erlaubt, Kopien danach loeschen.'),
    ('OWASP_CC_BY_SA', 'Creative Commons BY-SA 4.0', 'https://creativecommons.org/licenses/by-sa/4.0/', 'allowed', null, 'yes', false,
     'Offen, Attribution + ShareAlike. Kommerziell erlaubt.'),
    ('NIST_PUBLIC_DOMAIN', 'US Government Public Domain', 'https://www.nist.gov/open/copyright-fair-use-and-licensing-statements-srd-data-software-and-technical-series-publications', 'allowed', null, 'yes', false,
     'US-Regierungswerke sind gemeinfrei. Keine Einschraenkungen.'),
    ('ENISA_CC_BY', 'Creative Commons BY 4.0', 'https://creativecommons.org/licenses/by/4.0/', 'allowed', null, 'yes', false,
     'Offen, nur Attribution. Kommerziell erlaubt.'),
    ('ETSI_RESTRICTIVE', 'ETSI Terms of Use', 'https://www.etsi.org/intellectual-property-rights', 'prohibited', 'prohibited', 'no', true,
     'Kommerzielle Nutzung und AI-Training ausdruecklich verboten.'),
    ('ISO_PAYWALLED', 'ISO Copyright', 'https://www.iso.org/privacy-and-copyright.html', 'prohibited', 'prohibited', 'unclear', true,
     'Kostenpflichtig. Kein Recht auf Reproduktion, Paraphrase muss hinreichend abstrahiert sein.'),
    ('IEC_AI_PROHIBITED', 'IEC Terms of Use', 'https://www.iec.ch/terms-conditions', 'prohibited', 'prohibited', 'no', true,
     'AI-Training explizit verboten.'),
    ('CSA_NC', 'CSA Noncommercial', 'https://cloudsecurityalliance.org/license/', 'restricted', null, 'unclear', false,
     'Noncommercial license. Kommerziell nur mit separater Vereinbarung.'),
    ('CIS_CC_BY_NC_ND', 'Creative Commons BY-NC-ND 4.0', 'https://creativecommons.org/licenses/by-nc-nd/4.0/', 'prohibited', null, 'yes', false,
     'Kein kommerzieller Gebrauch, keine Ableitungen.')
ON CONFLICT (license_id) DO NOTHING;

-- =============================================================================
-- SEED: Sources
-- =============================================================================

INSERT INTO canonical_control_sources (source_id, title, publisher, url, version_label, language, license_id, allowed_analysis, allowed_store_excerpt, allowed_ship_embeddings, allowed_ship_in_product)
VALUES
    ('BSI_TR03161_1', 'BSI TR-03161 Teil 1 — Mobile Anwendungen', 'BSI', 'https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Publikationen/TechnischeRichtlinien/TR03161/BSI-TR-03161-1.html', '1.0', 'de', 'BSI_TOS_2025', true, false, false, false),
    ('BSI_TR03161_2', 'BSI TR-03161 Teil 2 — Web-Anwendungen', 'BSI', 'https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Publikationen/TechnischeRichtlinien/TR03161/BSI-TR-03161-2.html', '1.0', 'de', 'BSI_TOS_2025', true, false, false, false),
    ('BSI_TR03161_3', 'BSI TR-03161 Teil 3 — Hintergrunddienste', 'BSI', 'https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Publikationen/TechnischeRichtlinien/TR03161/BSI-TR-03161-3.html', '1.0', 'de', 'BSI_TOS_2025', true, false, false, false),
    ('OWASP_ASVS', 'OWASP Application Security Verification Standard', 'OWASP Foundation', 'https://owasp.org/www-project-application-security-verification-standard/', '4.0.3', 'en', 'OWASP_CC_BY_SA', true, true, true, true),
    ('OWASP_MASVS', 'OWASP Mobile Application Security Verification Standard', 'OWASP Foundation', 'https://mas.owasp.org/', '2.1.0', 'en', 'OWASP_CC_BY_SA', true, true, true, true),
    ('OWASP_TOP10', 'OWASP Top 10', 'OWASP Foundation', 'https://owasp.org/www-project-top-ten/', '2021', 'en', 'OWASP_CC_BY_SA', true, true, true, true),
    ('NIST_SP800_53', 'NIST SP 800-53 Rev. 5 — Security and Privacy Controls', 'NIST', 'https://csrc.nist.gov/publications/detail/sp/800-53/rev-5/final', 'Rev.5', 'en', 'NIST_PUBLIC_DOMAIN', true, true, true, true),
    ('NIST_SP800_63B', 'NIST SP 800-63B — Digital Identity Guidelines (Authentication)', 'NIST', 'https://pages.nist.gov/800-63-3/sp800-63b.html', 'Rev.3', 'en', 'NIST_PUBLIC_DOMAIN', true, true, true, true),
    ('ENISA_GOOD_PRACTICES', 'ENISA Good Practices for Security of IoT/Mobile', 'ENISA', 'https://www.enisa.europa.eu/publications', null, 'en', 'ENISA_CC_BY', true, true, true, true),
    ('CIS_CONTROLS', 'CIS Critical Security Controls', 'Center for Internet Security', 'https://www.cisecurity.org/controls', 'v8', 'en', 'CIS_CC_BY_NC_ND', true, false, false, false)
ON CONFLICT (source_id) DO NOTHING;

-- =============================================================================
-- SEED: Default Framework
-- =============================================================================

INSERT INTO canonical_control_frameworks (framework_id, name, version, description, owner, release_state)
VALUES (
    'bp_security_v1',
    'BreakPilot Security Controls',
    '1.0',
    'Eigenstaendig formulierte Security Controls basierend auf offenem Wissen (OWASP, NIST, ENISA). Unabhaengige Taxonomie und Nomenklatur.',
    'security-platform',
    'draft'
)
ON CONFLICT (framework_id) DO NOTHING;

COMMIT;
