-- v12.5 execution assurance delta. -- This migration adds evidence and scheduling metadata only. It does not enable automatic model mutation, -- client publication, broker submission or model promotion. -- Fail closed after upgrade. Each schedule must be enabled by an approved operational change. update evaluation.model_operation_schedule set enabled = false, updated_at = now(), last_error_code = 'V12_5_REAPPROVAL_REQUIRED' where schedule_version = 1 and operation_code in ('J10','J11','J17','J18','J19','J20','J21','J22','J23','J24'); alter table evaluation.model_operation_schedule add column if not exists calendar_id text not null default 'GLOBAL_UTC', add column if not exists due_policy text not null default 'FIXED_CADENCE', add column if not exists dependency_json jsonb not null default '[]'::jsonb, add column if not exists catch_up_policy text not null default 'LATEST_ONLY', add column if not exists max_catch_up integer not null default 1 check (max_catch_up between 0 and 31), add column if not exists business_hold_code text null; create table if not exists evaluation.model_operation_artifact ( artifact_id uuid primary key, request_id uuid not null references evaluation.model_operation_request(request_id), artifact_type text not null, artifact_uri text not null, content_hash text not null, media_type text not null, evidence_class text not null check (evidence_class in ('SOURCE', 'RUNTIME', 'RESEARCH', 'RELEASE', 'AUDIT')), produced_by text not null, produced_at timestamptz not null, retention_until timestamptz null, created_at timestamptz not null default now(), unique (request_id, artifact_type, content_hash) ); create table if not exists evaluation.model_operation_dependency_result ( dependency_result_id uuid primary key, request_id uuid not null references evaluation.model_operation_request(request_id), dependency_code text not null, result text not null check (result in ('PASS', 'WARN', 'HOLD', 'FAIL')), evidence_hash text not null, checked_at timestamptz not null, unique (request_id, dependency_code, evidence_hash) ); create table if not exists governance.release_evidence_bundle ( bundle_id uuid primary key, release_version text not null, source_manifest_hash text not null, build_artifact_hash text null, test_artifact_hash text null, migration_artifact_hash text null, security_artifact_hash text null, rollback_artifact_hash text null, decision_log_hash text not null, status text not null check (status in ('DRAFT', 'REVIEW_REQUIRED', 'APPROVED', 'REJECTED', 'EXPIRED')), maker_id text not null, checker_id text null, created_at timestamptz not null, decided_at timestamptz null, content_hash text not null unique, check (status not in ('APPROVED', 'REJECTED') or (checker_id is not null and checker_id <> maker_id and decided_at is not null)) ); create table if not exists governance.source_contract_snapshot ( snapshot_id uuid primary key, source_code text not null, schema_version text not null, license_version text not null, sla_version text not null, timezone_contract text not null, unit_contract text not null, content_hash text not null unique, status text not null check (status in ('PROPOSED', 'APPROVED', 'RETIRED', 'QUARANTINED')), effective_from timestamptz null, approved_by text null, approved_at timestamptz null, created_at timestamptz not null default now() ); create table if not exists governance.execution_assurance_decision ( decision_id uuid primary key, decision_code text not null, scope_key text not null, decision_version integer not null check (decision_version > 0), status text not null check (status in ('DECISION_REQUIRED', 'APPROVED', 'REJECTED', 'SUPERSEDED', 'EXPIRED')), statement text not null, basis_json jsonb not null, owner text not null, approved_by text null, approved_at timestamptz null, expires_at timestamptz null, content_hash text not null, created_at timestamptz not null default now(), unique (decision_code, scope_key, decision_version), unique (content_hash) ); -- Append-only operational evidence. drop trigger if exists model_operation_artifact_append_only on evaluation.model_operation_artifact; create trigger model_operation_artifact_append_only before update or delete on evaluation.model_operation_artifact for each row execute function building_blocks.prevent_append_only_change(); drop trigger if exists model_operation_dependency_result_append_only on evaluation.model_operation_dependency_result; create trigger model_operation_dependency_result_append_only before update or delete on evaluation.model_operation_dependency_result for each row execute function building_blocks.prevent_append_only_change(); drop trigger if exists release_evidence_bundle_append_only on governance.release_evidence_bundle; create trigger release_evidence_bundle_append_only before update or delete on governance.release_evidence_bundle for each row execute function building_blocks.prevent_append_only_change(); drop trigger if exists source_contract_snapshot_append_only on governance.source_contract_snapshot; create trigger source_contract_snapshot_append_only before update or delete on governance.source_contract_snapshot for each row execute function building_blocks.prevent_append_only_change(); drop trigger if exists execution_assurance_decision_append_only on governance.execution_assurance_decision; create trigger execution_assurance_decision_append_only before update or delete on governance.execution_assurance_decision for each row execute function building_blocks.prevent_append_only_change(); -- Additional checks are seeded disabled. They may be enabled only after their source/calendar/SLO contracts are approved. insert into evaluation.model_operation_schedule (schedule_id, operation_code, operation_name, scope_key, cadence, automation_mode, queue_name, schedule_version, enabled, next_due_at, max_lag, primary_owner, secondary_owner, calendar_id, due_policy, dependency_json, catch_up_policy, max_catch_up) values ('e4100000-0000-4000-8000-000000000025', 'J25', 'SourceContractDriftCheck', 'GLOBAL', 'DAILY', 'EVALUATION_ONLY', 'q-evaluation', 1, false, now() + interval '1 day', interval '1 day', 'Data Governance', 'Adapter Owner/QA', 'GLOBAL_UTC', 'FIXED_CADENCE', '["SOURCE_CONTRACT_APPROVED"]', 'LATEST_ONLY', 1), ('e4100000-0000-4000-8000-000000000026', 'J26', 'MarketCalendarCompletenessCheck', 'GLOBAL', 'DAILY', 'EVALUATION_ONLY', 'q-market-data', 1, false, now() + interval '1 day', interval '1 day', 'Data/Ops', 'Quant/QA', 'APPROVED_MARKET_CALENDAR', 'TRADING_SESSION', '["MARKET_CALENDAR_APPROVED","SOURCE_COMPLETE"]', 'LATEST_ONLY', 1), ('e4100000-0000-4000-8000-000000000027', 'J27', 'EvidenceChainAudit', 'GLOBAL', 'DAILY', 'EVALUATION_ONLY', 'q-control', 1, false, now() + interval '1 day', interval '1 day', 'Compliance/QA', 'Data/BE', 'GLOBAL_UTC', 'FIXED_CADENCE', '["AUDIT_LEDGER_READY"]', 'LATEST_ONLY', 1), ('e4100000-0000-4000-8000-000000000028', 'J28', 'ProjectionFreshnessCheck', 'GLOBAL', 'DAILY', 'EVALUATION_ONLY', 'q-evaluation', 1, false, now() + interval '1 day', interval '1 day', 'BE/Data', 'SRE/QA', 'GLOBAL_UTC', 'FIXED_CADENCE', '["PROJECTION_CONTRACT_APPROVED"]', 'LATEST_ONLY', 1), ('e4100000-0000-4000-8000-000000000029', 'J29', 'CapacitySlaTrend', 'GLOBAL', 'WEEKLY', 'EVALUATION_ONLY', 'q-control', 1, false, now() + interval '7 days', interval '7 days', 'SRE/PM', 'DBA/Module Owner', 'GLOBAL_UTC', 'FIXED_CADENCE', '["SLO_APPROVED","VOLUME_ASSUMPTION_APPROVED"]', 'LATEST_ONLY', 1), ('e4100000-0000-4000-8000-000000000030', 'J30', 'ReleaseEvidenceAssemble', 'GLOBAL', 'EVENT_DRIVEN', 'PROPOSAL_ONLY', 'q-control', 1, false, now() + interval '365 days', interval '365 days', 'QA/Release Manager', 'Compliance/SRE', 'GLOBAL_UTC', 'EVENT', '["BUILD_GREEN","TEST_GREEN","MIGRATION_GREEN","SECURITY_GREEN","ROLLBACK_READY"]', 'NONE', 0) on conflict (operation_code, scope_key, schedule_version) do nothing;