new two advisories and sprints work on them

This commit is contained in:
master
2026-01-16 18:39:36 +02:00
parent 9daf619954
commit c3a6269d55
72 changed files with 15540 additions and 18 deletions

View File

@@ -0,0 +1,153 @@
-- Migration: V20260117__vex_rekor_linkage.sql
-- Sprint: SPRINT_20260117_002_EXCITITOR_vex_rekor_linkage
-- Task: VRL-004, VRL-005 - Create Excititor and VexHub database migrations
-- Description: Add Rekor transparency log linkage columns to VEX tables
-- Author: StellaOps
-- Date: 2026-01-17
-- ============================================================================
-- EXCITITOR SCHEMA: vex_observations table
-- ============================================================================
-- Add Rekor linkage columns to vex_observations
ALTER TABLE IF EXISTS excititor.vex_observations
ADD COLUMN IF NOT EXISTS rekor_uuid TEXT,
ADD COLUMN IF NOT EXISTS rekor_log_index BIGINT,
ADD COLUMN IF NOT EXISTS rekor_integrated_time TIMESTAMPTZ,
ADD COLUMN IF NOT EXISTS rekor_log_url TEXT,
ADD COLUMN IF NOT EXISTS rekor_tree_root TEXT,
ADD COLUMN IF NOT EXISTS rekor_tree_size BIGINT,
ADD COLUMN IF NOT EXISTS rekor_inclusion_proof JSONB,
ADD COLUMN IF NOT EXISTS rekor_entry_body_hash TEXT,
ADD COLUMN IF NOT EXISTS rekor_entry_kind TEXT,
ADD COLUMN IF NOT EXISTS rekor_linked_at TIMESTAMPTZ;
-- Index for Rekor queries by UUID
CREATE INDEX IF NOT EXISTS idx_vex_observations_rekor_uuid
ON excititor.vex_observations(rekor_uuid)
WHERE rekor_uuid IS NOT NULL;
-- Index for Rekor queries by log index (for ordered traversal)
CREATE INDEX IF NOT EXISTS idx_vex_observations_rekor_log_index
ON excititor.vex_observations(rekor_log_index DESC)
WHERE rekor_log_index IS NOT NULL;
-- Index for finding unlinked observations (for retry/backfill)
CREATE INDEX IF NOT EXISTS idx_vex_observations_pending_rekor
ON excititor.vex_observations(created_at)
WHERE rekor_uuid IS NULL;
-- Comment on columns
COMMENT ON COLUMN excititor.vex_observations.rekor_uuid IS 'Rekor entry UUID (64-char hex)';
COMMENT ON COLUMN excititor.vex_observations.rekor_log_index IS 'Monotonically increasing log position';
COMMENT ON COLUMN excititor.vex_observations.rekor_integrated_time IS 'Time entry was integrated into Rekor log';
COMMENT ON COLUMN excititor.vex_observations.rekor_log_url IS 'Rekor server URL where entry was submitted';
COMMENT ON COLUMN excititor.vex_observations.rekor_tree_root IS 'Merkle tree root hash at submission time (base64)';
COMMENT ON COLUMN excititor.vex_observations.rekor_tree_size IS 'Tree size at submission time';
COMMENT ON COLUMN excititor.vex_observations.rekor_inclusion_proof IS 'RFC 6962 inclusion proof for offline verification';
COMMENT ON COLUMN excititor.vex_observations.rekor_entry_body_hash IS 'SHA-256 hash of entry body';
COMMENT ON COLUMN excititor.vex_observations.rekor_entry_kind IS 'Entry kind (dsse, intoto, hashedrekord)';
COMMENT ON COLUMN excititor.vex_observations.rekor_linked_at IS 'When linkage was recorded locally';
-- ============================================================================
-- EXCITITOR SCHEMA: vex_statement_change_events table
-- ============================================================================
-- Add Rekor linkage to change events
ALTER TABLE IF EXISTS excititor.vex_statement_change_events
ADD COLUMN IF NOT EXISTS rekor_entry_id TEXT,
ADD COLUMN IF NOT EXISTS rekor_log_index BIGINT;
-- Index for Rekor queries on change events
CREATE INDEX IF NOT EXISTS idx_vex_change_events_rekor
ON excititor.vex_statement_change_events(rekor_entry_id)
WHERE rekor_entry_id IS NOT NULL;
COMMENT ON COLUMN excititor.vex_statement_change_events.rekor_entry_id IS 'Rekor entry UUID for change attestation';
COMMENT ON COLUMN excititor.vex_statement_change_events.rekor_log_index IS 'Rekor log index for change attestation';
-- ============================================================================
-- VEXHUB SCHEMA: vex_statements table
-- ============================================================================
-- Add Rekor linkage columns to vex_statements
ALTER TABLE IF EXISTS vexhub.vex_statements
ADD COLUMN IF NOT EXISTS rekor_uuid TEXT,
ADD COLUMN IF NOT EXISTS rekor_log_index BIGINT,
ADD COLUMN IF NOT EXISTS rekor_integrated_time TIMESTAMPTZ,
ADD COLUMN IF NOT EXISTS rekor_inclusion_proof JSONB;
-- Index for Rekor queries
CREATE INDEX IF NOT EXISTS idx_vexhub_statements_rekor_uuid
ON vexhub.vex_statements(rekor_uuid)
WHERE rekor_uuid IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_vexhub_statements_rekor_log_index
ON vexhub.vex_statements(rekor_log_index DESC)
WHERE rekor_log_index IS NOT NULL;
COMMENT ON COLUMN vexhub.vex_statements.rekor_uuid IS 'Rekor entry UUID for statement attestation';
COMMENT ON COLUMN vexhub.vex_statements.rekor_log_index IS 'Rekor log index for statement attestation';
COMMENT ON COLUMN vexhub.vex_statements.rekor_integrated_time IS 'Time statement was integrated into Rekor log';
COMMENT ON COLUMN vexhub.vex_statements.rekor_inclusion_proof IS 'RFC 6962 inclusion proof for offline verification';
-- ============================================================================
-- ATTESTOR SCHEMA: rekor_entries verification tracking
-- Sprint: SPRINT_20260117_001_ATTESTOR_periodic_rekor_verification (PRV-003)
-- ============================================================================
-- Add verification tracking columns to existing rekor_entries table
ALTER TABLE IF EXISTS attestor.rekor_entries
ADD COLUMN IF NOT EXISTS last_verified_at TIMESTAMPTZ,
ADD COLUMN IF NOT EXISTS verification_count INT NOT NULL DEFAULT 0,
ADD COLUMN IF NOT EXISTS last_verification_result TEXT;
-- Index for verification queries (find entries needing verification)
CREATE INDEX IF NOT EXISTS idx_rekor_entries_verification
ON attestor.rekor_entries(created_at DESC, last_verified_at NULLS FIRST)
WHERE last_verification_result IS DISTINCT FROM 'invalid';
-- Index for finding never-verified entries
CREATE INDEX IF NOT EXISTS idx_rekor_entries_unverified
ON attestor.rekor_entries(created_at DESC)
WHERE last_verified_at IS NULL;
COMMENT ON COLUMN attestor.rekor_entries.last_verified_at IS 'Timestamp of last successful verification';
COMMENT ON COLUMN attestor.rekor_entries.verification_count IS 'Number of times entry has been verified';
COMMENT ON COLUMN attestor.rekor_entries.last_verification_result IS 'Result of last verification: valid, invalid, skipped';
-- ============================================================================
-- ATTESTOR SCHEMA: rekor_root_checkpoints table
-- Stores tree root checkpoints for consistency verification
-- ============================================================================
CREATE TABLE IF NOT EXISTS attestor.rekor_root_checkpoints (
id BIGSERIAL PRIMARY KEY,
tree_root TEXT NOT NULL,
tree_size BIGINT NOT NULL,
log_id TEXT NOT NULL,
log_url TEXT,
checkpoint_envelope TEXT,
captured_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
verified_at TIMESTAMPTZ,
is_consistent BOOLEAN,
inconsistency_reason TEXT,
CONSTRAINT uq_root_checkpoint UNIQUE (log_id, tree_root, tree_size)
);
-- Index for finding latest checkpoints per log
CREATE INDEX IF NOT EXISTS idx_rekor_root_checkpoints_latest
ON attestor.rekor_root_checkpoints(log_id, captured_at DESC);
-- Index for consistency verification
CREATE INDEX IF NOT EXISTS idx_rekor_root_checkpoints_unverified
ON attestor.rekor_root_checkpoints(captured_at DESC)
WHERE verified_at IS NULL;
COMMENT ON TABLE attestor.rekor_root_checkpoints IS 'Stores Rekor tree root checkpoints for consistency verification';
COMMENT ON COLUMN attestor.rekor_root_checkpoints.tree_root IS 'Merkle tree root hash (base64)';
COMMENT ON COLUMN attestor.rekor_root_checkpoints.tree_size IS 'Tree size at checkpoint';
COMMENT ON COLUMN attestor.rekor_root_checkpoints.log_id IS 'Rekor log identifier (hash of public key)';
COMMENT ON COLUMN attestor.rekor_root_checkpoints.checkpoint_envelope IS 'Signed checkpoint in note format';
COMMENT ON COLUMN attestor.rekor_root_checkpoints.is_consistent IS 'Whether checkpoint was consistent with previous';
COMMENT ON COLUMN attestor.rekor_root_checkpoints.inconsistency_reason IS 'Reason for inconsistency if detected';