-- -----------------------------------------------------------------------------
-- 001_verdict_ledger_initial.sql
-- Sprint: SPRINT_20260118_015_Attestor_verdict_ledger_foundation
-- Task: VL-001 - Create VerdictLedger database schema
-- Description: Append-only verdict ledger with SHA-256 hash chaining
-- -----------------------------------------------------------------------------

-- Create verdict decision enum
DO $$ BEGIN
    CREATE TYPE verdict_decision AS ENUM ('unknown', 'approve', 'reject', 'pending');
EXCEPTION
    WHEN duplicate_object THEN null;
END $$;

-- Create the verdict_ledger table
CREATE TABLE IF NOT EXISTS verdict_ledger (
    ledger_id UUID PRIMARY KEY,
    bom_ref VARCHAR(2048) NOT NULL,
    cyclonedx_serial VARCHAR(512),
    rekor_uuid VARCHAR(128),
    decision verdict_decision NOT NULL DEFAULT 'unknown',
    reason TEXT NOT NULL,
    policy_bundle_id VARCHAR(256) NOT NULL,
    policy_bundle_hash VARCHAR(64) NOT NULL,
    verifier_image_digest VARCHAR(256) NOT NULL,
    signer_keyid VARCHAR(512) NOT NULL,
    prev_hash VARCHAR(64),  -- SHA-256 hex, null for genesis entry
    verdict_hash VARCHAR(64) NOT NULL UNIQUE,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    tenant_id UUID NOT NULL,
    
    -- Constraints
    CONSTRAINT verdict_hash_format CHECK (verdict_hash ~ '^[a-f0-9]{64}$'),
    CONSTRAINT prev_hash_format CHECK (prev_hash IS NULL OR prev_hash ~ '^[a-f0-9]{64}$'),
    CONSTRAINT policy_hash_format CHECK (policy_bundle_hash ~ '^[a-f0-9]{64}$')
);

-- Indexes for common query patterns
CREATE INDEX IF NOT EXISTS idx_verdict_ledger_bom_ref 
    ON verdict_ledger (bom_ref);

CREATE INDEX IF NOT EXISTS idx_verdict_ledger_rekor_uuid 
    ON verdict_ledger (rekor_uuid) 
    WHERE rekor_uuid IS NOT NULL;

CREATE INDEX IF NOT EXISTS idx_verdict_ledger_created_at 
    ON verdict_ledger (created_at DESC);

CREATE INDEX IF NOT EXISTS idx_verdict_ledger_tenant_created 
    ON verdict_ledger (tenant_id, created_at DESC);

CREATE INDEX IF NOT EXISTS idx_verdict_ledger_prev_hash 
    ON verdict_ledger (prev_hash) 
    WHERE prev_hash IS NOT NULL;

CREATE INDEX IF NOT EXISTS idx_verdict_ledger_decision 
    ON verdict_ledger (decision);

-- Composite index for chain walking
CREATE INDEX IF NOT EXISTS idx_verdict_ledger_chain 
    ON verdict_ledger (tenant_id, verdict_hash);

-- Comments
COMMENT ON TABLE verdict_ledger IS 'Append-only ledger of release verdicts with SHA-256 hash chaining for cryptographic audit trail';
COMMENT ON COLUMN verdict_ledger.ledger_id IS 'Unique identifier for this ledger entry';
COMMENT ON COLUMN verdict_ledger.bom_ref IS 'Package URL (purl) or container digest reference';
COMMENT ON COLUMN verdict_ledger.cyclonedx_serial IS 'CycloneDX serialNumber URN linking to SBOM';
COMMENT ON COLUMN verdict_ledger.rekor_uuid IS 'Transparency log entry UUID for external verification';
COMMENT ON COLUMN verdict_ledger.decision IS 'The release decision: unknown, approve, reject, or pending';
COMMENT ON COLUMN verdict_ledger.reason IS 'Human-readable explanation for the decision';
COMMENT ON COLUMN verdict_ledger.policy_bundle_id IS 'Reference to the policy configuration used';
COMMENT ON COLUMN verdict_ledger.policy_bundle_hash IS 'SHA-256 hash of the policy bundle for reproducibility';
COMMENT ON COLUMN verdict_ledger.verifier_image_digest IS 'Container digest of the verifier service';
COMMENT ON COLUMN verdict_ledger.signer_keyid IS 'Key ID that signed this verdict';
COMMENT ON COLUMN verdict_ledger.prev_hash IS 'SHA-256 hash of previous entry (null for genesis)';
COMMENT ON COLUMN verdict_ledger.verdict_hash IS 'SHA-256 hash of this entry canonical JSON form';
COMMENT ON COLUMN verdict_ledger.created_at IS 'Timestamp when this verdict was recorded';
COMMENT ON COLUMN verdict_ledger.tenant_id IS 'Tenant identifier for multi-tenancy';

-- Revoke UPDATE and DELETE for application role (append-only enforcement)
-- This should be run after creating the appropriate role
-- REVOKE UPDATE, DELETE ON verdict_ledger FROM stellaops_app;
-- GRANT INSERT, SELECT ON verdict_ledger TO stellaops_app;
