teleo-infrastructure/ops/rollback_teleo_v3_epistemic_contract.sql

357 lines
14 KiB
PL/PgSQL

-- Schema-only rollback for ops/teleo_v3_epistemic_contract.sql.
--
-- The rollback refuses to discard proposal-linked V3 data. A disposable
-- verifier may delete its own canary rows first; a real migration needs an
-- explicit export/port decision before this file can run.
\set ON_ERROR_STOP on
set timezone = 'UTC';
begin;
do $ownership_guard$
declare
v_artifacts_present boolean;
v_ledger_owner_valid boolean;
v_ledger_row_valid boolean;
v_missing_objects text;
begin
select
pg_catalog.to_regclass('kb_stage.teleo_v3_installation_ownership') is not null
or pg_catalog.to_regclass('public.claim_evidence_assessments') is not null
or exists (
select 1
from information_schema.columns columns
where columns.table_schema = 'public'
and (columns.table_name, columns.column_name) in (
('claims', 'owner_agent_id'),
('claims', 'proposition'),
('claims', 'body_markdown'),
('claims', 'scope'),
('claims', 'access_scope'),
('claims', 'admission_state'),
('claims', 'revision_criteria'),
('claims', 'revision_kind'),
('claims', 'supersedes_id'),
('claims', 'accepted_by_proposal_id'),
('sources', 'canonical_url'),
('sources', 'storage_uri'),
('sources', 'content_hash'),
('sources', 'access_scope'),
('sources', 'ingestion_origin'),
('sources', 'provenance_status'),
('sources', 'source_class'),
('sources', 'auto_promotion_policy'),
('sources', 'accepted_by_proposal_id'),
('claim_evidence', 'excerpt'),
('claim_evidence', 'locator_json'),
('claim_evidence', 'source_content_hash'),
('claim_evidence', 'rationale'),
('claim_evidence', 'polarity'),
('claim_evidence', 'accepted_from_proposal_id'),
('claim_edges', 'relation_type'),
('claim_edges', 'rationale'),
('claim_edges', 'scope_or_conditions'),
('claim_edges', 'accepted_by_proposal_id')
)
)
or exists (
select 1
from pg_catalog.pg_proc procedure
join pg_catalog.pg_namespace namespace on namespace.oid = procedure.pronamespace
where namespace.nspname = 'kb_stage'
and procedure.proname like 'teleo\_v3\_%' escape '\'
)
or exists (
select 1
from pg_catalog.pg_trigger trigger_row
where not trigger_row.tgisinternal
and trigger_row.tgname like 'teleo\_v3\_%' escape '\'
)
or exists (
select 1
from pg_catalog.pg_constraint constraint_row
where constraint_row.conname like 'teleo\_v3\_%' escape '\'
)
or exists (
select 1
from pg_catalog.pg_class index_row
where index_row.relkind = 'i'
and index_row.relname like 'teleo\_v3\_%' escape '\'
)
into v_artifacts_present;
if pg_catalog.to_regclass('kb_stage.teleo_v3_installation_ownership') is null then
if v_artifacts_present then
raise exception using
errcode = '55000',
message = 'teleo_v3 rollback refused: V3-named objects lack exact installation ownership';
end if;
return;
end if;
select owner_role.rolname = 'kb_gate_owner'
into v_ledger_owner_valid
from pg_catalog.pg_class relation
join pg_catalog.pg_namespace namespace on namespace.oid = relation.relnamespace
join pg_catalog.pg_roles owner_role on owner_role.oid = relation.relowner
where namespace.nspname = 'kb_stage'
and relation.relname = 'teleo_v3_installation_ownership'
and relation.relkind in ('r', 'p');
if not coalesce(v_ledger_owner_valid, false) then
raise exception using
errcode = '55000',
message = 'teleo_v3 rollback refused: installation ownership ledger owner is invalid';
end if;
execute $ownership_query$
select count(*) = 1
and bool_and(
contract_name = 'livingip.teleo-v3-epistemic-contract'
and contract_version = 1
and installation_token = 'collision-free-install-v1'
)
from kb_stage.teleo_v3_installation_ownership
$ownership_query$ into v_ledger_row_valid;
if not coalesce(v_ledger_row_valid, false) then
raise exception using
errcode = '55000',
message = 'teleo_v3 rollback refused: installation ownership ledger is not exact';
end if;
with expected_columns(table_name, column_name) as (
values
('claims', 'owner_agent_id'),
('claims', 'proposition'),
('claims', 'body_markdown'),
('claims', 'scope'),
('claims', 'access_scope'),
('claims', 'admission_state'),
('claims', 'revision_criteria'),
('claims', 'revision_kind'),
('claims', 'supersedes_id'),
('claims', 'accepted_by_proposal_id'),
('sources', 'canonical_url'),
('sources', 'storage_uri'),
('sources', 'content_hash'),
('sources', 'access_scope'),
('sources', 'ingestion_origin'),
('sources', 'provenance_status'),
('sources', 'source_class'),
('sources', 'auto_promotion_policy'),
('sources', 'accepted_by_proposal_id'),
('claim_evidence', 'excerpt'),
('claim_evidence', 'locator_json'),
('claim_evidence', 'source_content_hash'),
('claim_evidence', 'rationale'),
('claim_evidence', 'polarity'),
('claim_evidence', 'accepted_from_proposal_id'),
('claim_edges', 'relation_type'),
('claim_edges', 'rationale'),
('claim_edges', 'scope_or_conditions'),
('claim_edges', 'accepted_by_proposal_id')
), missing(object_name) as (
select pg_catalog.format('%I.%I', expected.table_name, expected.column_name)
from expected_columns expected
where not exists (
select 1
from information_schema.columns columns
where columns.table_schema = 'public'
and columns.table_name = expected.table_name
and columns.column_name = expected.column_name
)
union all
select 'public.claim_evidence_assessments'
where pg_catalog.to_regclass('public.claim_evidence_assessments') is null
)
select pg_catalog.string_agg(object_name, ', ' order by object_name)
into v_missing_objects
from missing;
if v_missing_objects is not null then
raise exception using
errcode = '55000',
message = pg_catalog.format(
'teleo_v3 rollback refused: installation-owned object set is incomplete: %s',
v_missing_objects
);
end if;
end
$ownership_guard$;
do $data_guard$
declare
contract_rows_exist boolean := false;
begin
if to_regclass('public.claim_evidence_assessments') is not null then
execute 'select exists (select 1 from public.claim_evidence_assessments)'
into contract_rows_exist;
if contract_rows_exist then
raise exception using
errcode = '55000',
message = 'teleo_v3 rollback refused: claim_evidence_assessments contains V3 data';
end if;
end if;
if exists (
select 1 from information_schema.columns
where table_schema = 'public' and table_name = 'claim_edges'
and column_name = 'accepted_by_proposal_id'
) then
execute 'select exists (select 1 from public.claim_edges where accepted_by_proposal_id is not null)'
into contract_rows_exist;
if contract_rows_exist then
raise exception using
errcode = '55000',
message = 'teleo_v3 rollback refused: claim_edges contains proposal-linked V3 data';
end if;
end if;
if exists (
select 1 from information_schema.columns
where table_schema = 'public' and table_name = 'claim_evidence'
and column_name = 'accepted_from_proposal_id'
) then
execute 'select exists (select 1 from public.claim_evidence where accepted_from_proposal_id is not null)'
into contract_rows_exist;
if contract_rows_exist then
raise exception using
errcode = '55000',
message = 'teleo_v3 rollback refused: claim_evidence contains proposal-linked V3 data';
end if;
end if;
if exists (
select 1 from information_schema.columns
where table_schema = 'public' and table_name = 'sources'
and column_name = 'accepted_by_proposal_id'
) then
execute 'select exists (select 1 from public.sources where accepted_by_proposal_id is not null)'
into contract_rows_exist;
if contract_rows_exist then
raise exception using
errcode = '55000',
message = 'teleo_v3 rollback refused: sources contains proposal-linked V3 data';
end if;
end if;
if exists (
select 1 from information_schema.columns
where table_schema = 'public' and table_name = 'claims'
and column_name = 'admission_state'
) then
execute $query$
select exists (
select 1 from public.claims
where admission_state = 'admitted' or accepted_by_proposal_id is not null
)
$query$ into contract_rows_exist;
if contract_rows_exist then
raise exception using
errcode = '55000',
message = 'teleo_v3 rollback refused: claims contains admitted or proposal-linked V3 data';
end if;
end if;
end
$data_guard$;
drop trigger if exists teleo_v3_guard_linked_proposal_decision on kb_stage.kb_proposals;
drop trigger if exists teleo_v3_00_enforce_apply_contract_cutover on kb_stage.kb_proposals;
alter table kb_stage.kb_proposals
drop constraint if exists teleo_v3_proposal_apply_receipt_check;
drop trigger if exists teleo_v3_edge_immutable on public.claim_edges;
drop trigger if exists teleo_v3_edge_reject_delete on public.claim_edges;
drop trigger if exists teleo_v3_edge_validate_endpoints on public.claim_edges;
drop trigger if exists teleo_v3_edge_require_accepted_proposal on public.claim_edges;
drop trigger if exists teleo_v3_00_edge_require_linked_insert on public.claim_edges;
drop trigger if exists teleo_v3_evidence_immutable on public.claim_evidence;
drop trigger if exists teleo_v3_evidence_reject_delete on public.claim_evidence;
drop trigger if exists teleo_v3_evidence_validate_provenance on public.claim_evidence;
drop trigger if exists teleo_v3_evidence_require_accepted_proposal on public.claim_evidence;
drop trigger if exists teleo_v3_00_evidence_require_linked_insert on public.claim_evidence;
drop trigger if exists teleo_v3_source_immutable on public.sources;
drop trigger if exists teleo_v3_source_reject_delete on public.sources;
drop trigger if exists teleo_v3_source_require_accepted_proposal on public.sources;
drop trigger if exists teleo_v3_00_source_require_linked_insert on public.sources;
drop trigger if exists teleo_v3_claim_immutable on public.claims;
drop trigger if exists teleo_v3_claim_reject_delete on public.claims;
drop trigger if exists teleo_v3_claim_require_accepted_proposal on public.claims;
drop trigger if exists teleo_v3_00_claim_require_linked_insert on public.claims;
drop index if exists public.teleo_v3_edge_typed_adjacency_idx;
drop index if exists public.teleo_v3_evidence_claim_polarity_idx;
drop index if exists public.teleo_v3_assessment_one_successor_idx;
drop index if exists public.teleo_v3_claim_one_admitted_successor_idx;
drop table if exists public.claim_evidence_assessments;
alter table public.claim_edges
drop constraint if exists teleo_v3_edge_contract_check,
drop constraint if exists teleo_v3_edge_accepted_proposal_fkey,
drop column if exists relation_type,
drop column if exists rationale,
drop column if exists scope_or_conditions,
drop column if exists accepted_by_proposal_id;
alter table public.claim_evidence
drop constraint if exists teleo_v3_evidence_contract_check,
drop constraint if exists teleo_v3_evidence_accepted_proposal_fkey,
drop column if exists excerpt,
drop column if exists locator_json,
drop column if exists source_content_hash,
drop column if exists rationale,
drop column if exists polarity,
drop column if exists accepted_from_proposal_id;
alter table public.sources
drop constraint if exists teleo_v3_source_contract_check,
drop constraint if exists teleo_v3_source_accepted_proposal_fkey,
drop column if exists canonical_url,
drop column if exists storage_uri,
drop column if exists content_hash,
drop column if exists access_scope,
drop column if exists ingestion_origin,
drop column if exists provenance_status,
drop column if exists source_class,
drop column if exists auto_promotion_policy,
drop column if exists accepted_by_proposal_id;
alter table public.claims
drop constraint if exists teleo_v3_claim_admission_check,
drop constraint if exists teleo_v3_claim_accepted_proposal_fkey,
drop constraint if exists teleo_v3_claim_supersedes_fkey,
drop constraint if exists teleo_v3_claim_owner_agent_fkey,
drop column if exists owner_agent_id,
drop column if exists proposition,
drop column if exists body_markdown,
drop column if exists scope,
drop column if exists access_scope,
drop column if exists admission_state,
drop column if exists revision_criteria,
drop column if exists revision_kind,
drop column if exists supersedes_id,
drop column if exists accepted_by_proposal_id;
drop function if exists kb_stage.teleo_v3_guard_linked_proposal_decision();
drop function if exists kb_stage.teleo_v3_acquire_protected_relation_locks();
drop function if exists kb_stage.teleo_v3_enforce_apply_contract_cutover();
drop function if exists kb_stage.teleo_v3_validate_evidence_assessment();
drop function if exists kb_stage.teleo_v3_validate_claim_edge();
drop function if exists kb_stage.teleo_v3_validate_claim_evidence();
drop function if exists kb_stage.teleo_v3_guard_immutable_fields();
drop function if exists kb_stage.teleo_v3_reject_delete();
drop function if exists kb_stage.teleo_v3_require_linked_insert();
drop function if exists kb_stage.teleo_v3_require_accepted_proposal();
drop table if exists kb_stage.teleo_v3_installation_ownership;
commit;
select jsonb_build_object(
'contract', 'livingip.teleo-v3-epistemic-contract',
'version', 1,
'migration', 'rolled_back'
)::text;