new two advisories and sprints work on them
This commit is contained in:
153
devops/database/migrations/V20260117__vex_rekor_linkage.sql
Normal file
153
devops/database/migrations/V20260117__vex_rekor_linkage.sql
Normal 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';
|
||||
Reference in New Issue
Block a user