-- Migration: 001_CreateVerdictAttestations
-- Description: Create verdict_attestations table for storing signed policy verdict attestations
-- Author: Evidence Locker Guild
-- Date: 2025-12-23

-- Create schema if not exists
CREATE SCHEMA IF NOT EXISTS evidence_locker;

-- Create verdict_attestations table
CREATE TABLE IF NOT EXISTS evidence_locker.verdict_attestations (
    verdict_id TEXT PRIMARY KEY,
    tenant_id TEXT NOT NULL,
    run_id TEXT NOT NULL,
    policy_id TEXT NOT NULL,
    policy_version INTEGER NOT NULL,
    finding_id TEXT NOT NULL,
    verdict_status TEXT NOT NULL CHECK (verdict_status IN ('passed', 'warned', 'blocked', 'quieted', 'ignored')),
    verdict_severity TEXT NOT NULL CHECK (verdict_severity IN ('critical', 'high', 'medium', 'low', 'info', 'none')),
    verdict_score NUMERIC(5, 2) NOT NULL CHECK (verdict_score >= 0 AND verdict_score <= 100),
    evaluated_at TIMESTAMPTZ NOT NULL,
    envelope JSONB NOT NULL,
    predicate_digest TEXT NOT NULL,
    determinism_hash TEXT,
    rekor_log_index BIGINT,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Create indexes for common query patterns
CREATE INDEX IF NOT EXISTS idx_verdict_attestations_run
    ON evidence_locker.verdict_attestations(run_id);

CREATE INDEX IF NOT EXISTS idx_verdict_attestations_finding
    ON evidence_locker.verdict_attestations(finding_id);

CREATE INDEX IF NOT EXISTS idx_verdict_attestations_tenant_evaluated
    ON evidence_locker.verdict_attestations(tenant_id, evaluated_at DESC);

CREATE INDEX IF NOT EXISTS idx_verdict_attestations_tenant_status
    ON evidence_locker.verdict_attestations(tenant_id, verdict_status);

CREATE INDEX IF NOT EXISTS idx_verdict_attestations_tenant_severity
    ON evidence_locker.verdict_attestations(tenant_id, verdict_severity);

CREATE INDEX IF NOT EXISTS idx_verdict_attestations_policy
    ON evidence_locker.verdict_attestations(policy_id, policy_version);

-- Create GIN index for JSONB envelope queries
CREATE INDEX IF NOT EXISTS idx_verdict_attestations_envelope
    ON evidence_locker.verdict_attestations USING gin(envelope);

-- Create function for updating updated_at timestamp
CREATE OR REPLACE FUNCTION evidence_locker.update_verdict_attestations_updated_at()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Create trigger to auto-update updated_at
CREATE TRIGGER trigger_verdict_attestations_updated_at
    BEFORE UPDATE ON evidence_locker.verdict_attestations
    FOR EACH ROW
    EXECUTE FUNCTION evidence_locker.update_verdict_attestations_updated_at();

-- Create view for verdict summary (without full envelope)
CREATE OR REPLACE VIEW evidence_locker.verdict_attestations_summary AS
SELECT
    verdict_id,
    tenant_id,
    run_id,
    policy_id,
    policy_version,
    finding_id,
    verdict_status,
    verdict_severity,
    verdict_score,
    evaluated_at,
    predicate_digest,
    determinism_hash,
    rekor_log_index,
    created_at
FROM evidence_locker.verdict_attestations;

-- Grant permissions (adjust as needed)
-- GRANT SELECT, INSERT ON evidence_locker.verdict_attestations TO evidence_locker_app;
-- GRANT SELECT ON evidence_locker.verdict_attestations_summary TO evidence_locker_app;

-- Add comments for documentation
COMMENT ON TABLE evidence_locker.verdict_attestations IS
    'Stores DSSE-signed policy verdict attestations for audit and verification';

COMMENT ON COLUMN evidence_locker.verdict_attestations.verdict_id IS
    'Unique verdict identifier (format: verdict:run:{runId}:finding:{findingId})';

COMMENT ON COLUMN evidence_locker.verdict_attestations.envelope IS
    'DSSE envelope containing signed verdict predicate';

COMMENT ON COLUMN evidence_locker.verdict_attestations.predicate_digest IS
    'SHA256 digest of the canonical JSON predicate payload';

COMMENT ON COLUMN evidence_locker.verdict_attestations.determinism_hash IS
    'Determinism hash computed from sorted evidence digests and verdict components';

COMMENT ON COLUMN evidence_locker.verdict_attestations.rekor_log_index IS
    'Rekor transparency log index (if anchored), null for offline/air-gap deployments';
