84 lines
4.0 KiB
SQL
84 lines
4.0 KiB
SQL
-- -----------------------------------------------------------------------------
|
|
-- 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;
|