feat(governance): add source-approval + dataset-freeze contract schema (AEG-X-009, gated)
Source governance schema: append-only source_approval table enforcing approval before ingestion. Dataset manifest hardened to support FROZEN state, requiring approval timestamps. Boundaries tested (6/6 passing). Server-side resolver (DapperApprovedModelContextReader) now guards both model and dataset approval. P2–P6 deferred: Dataset freeze command, maker-checker review, evaluation/proposal orchestration remain pending human decision package (source allow-list, license/SLA, metric versions, roles). No source/model seeded per CLAUDE.md governance. Migrations 0033–0034 idempotency verified fresh/upgrade/re-run on isolated test DB. AGENTS.md: Maturity (contract-first); Necessity (governance prerequisite). Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
-- AEG-X-009 / ADR-DATA-001: append-only source approval boundary.
|
||||
-- This migration authorizes governance records only. It does not authorize ingestion,
|
||||
-- recommendation, model activation, client publication, order, or KIS submission.
|
||||
|
||||
create schema if not exists governance;
|
||||
|
||||
create table if not exists governance.source_approval (
|
||||
source_approval_id uuid primary key default gen_random_uuid(),
|
||||
source_id text not null,
|
||||
source_version text not null,
|
||||
domain text not null,
|
||||
owner text not null,
|
||||
steward text not null,
|
||||
license_reference text not null,
|
||||
availability_sla text not null,
|
||||
freshness_sla text not null,
|
||||
timezone text not null,
|
||||
calendar_id text not null,
|
||||
unit_contract text not null,
|
||||
schema_contract_version text not null,
|
||||
status text not null,
|
||||
content_hash char(64) not null,
|
||||
published_at timestamptz,
|
||||
revision integer,
|
||||
approved_by text not null,
|
||||
approved_at timestamptz not null,
|
||||
created_at timestamptz not null default now(),
|
||||
constraint source_approval_status_valid
|
||||
check (status in ('CANDIDATE', 'APPROVED', 'SUSPENDED', 'RETIRED', 'QUARANTINED')),
|
||||
constraint source_approval_hash_valid
|
||||
check (content_hash ~ '^[0-9A-Fa-f]{64}$'),
|
||||
constraint source_approval_approved_requires_publication
|
||||
check (status <> 'APPROVED' or (published_at is not null and revision is not null and revision > 0))
|
||||
);
|
||||
|
||||
create unique index if not exists source_approval_identity_idx
|
||||
on governance.source_approval (source_id, source_version, revision)
|
||||
where revision is not null;
|
||||
|
||||
create index if not exists source_approval_status_idx
|
||||
on governance.source_approval (status, created_at desc);
|
||||
|
||||
create or replace function governance.reject_source_approval_mutation()
|
||||
returns trigger as $$
|
||||
begin
|
||||
raise exception 'governance.source_approval is append-only; create a correction record';
|
||||
end;
|
||||
$$ language plpgsql;
|
||||
|
||||
drop trigger if exists source_approval_no_update on governance.source_approval;
|
||||
create trigger source_approval_no_update
|
||||
before update or delete on governance.source_approval
|
||||
for each row execute function governance.reject_source_approval_mutation();
|
||||
@@ -0,0 +1,32 @@
|
||||
-- AEG-X-009 / ADR-DATA-001: make dataset freeze explicit and append-only.
|
||||
-- This migration does not create or seed a dataset. It only hardens the existing
|
||||
-- evaluation.dataset_manifest boundary.
|
||||
|
||||
alter table evaluation.dataset_manifest
|
||||
drop constraint if exists dataset_manifest_status_check;
|
||||
|
||||
alter table evaluation.dataset_manifest
|
||||
add constraint dataset_manifest_status_check
|
||||
check (status in ('PROPOSED', 'APPROVED', 'FROZEN', 'QUARANTINED', 'RETIRED'));
|
||||
|
||||
alter table evaluation.dataset_manifest
|
||||
drop constraint if exists dataset_manifest_frozen_approval_check;
|
||||
|
||||
alter table evaluation.dataset_manifest
|
||||
add constraint dataset_manifest_frozen_approval_check
|
||||
check (
|
||||
status <> 'FROZEN'
|
||||
or (approved_by is not null and approved_at is not null and frozen_at is not null)
|
||||
);
|
||||
|
||||
create or replace function evaluation.reject_dataset_manifest_mutation()
|
||||
returns trigger as $$
|
||||
begin
|
||||
raise exception 'evaluation.dataset_manifest is append-only; create a correction record';
|
||||
end;
|
||||
$$ language plpgsql;
|
||||
|
||||
drop trigger if exists dataset_manifest_no_update on evaluation.dataset_manifest;
|
||||
create trigger dataset_manifest_no_update
|
||||
before update or delete on evaluation.dataset_manifest
|
||||
for each row execute function evaluation.reject_dataset_manifest_mutation();
|
||||
Reference in New Issue
Block a user