KB-5CA0

Phase 3B — Rollback Package

5 min read Revision 1
dieu45phase-3brollbackpg-dump2026-05-26

Phase 3B — Rollback Package

Scope

This rollback restores the system to the pre-Phase-3B state, i.e. exactly the state at the end of Phase 3 ([[project-dieu45-phase3-mark-cut-queue-pilot-dieu37-write-channel-pass-2026-05-26]]).

It does not roll back Phase 3 itself (the 17 durable Điều 37 IUs, the staging/payload/job_queue rows, the queue_heartbeat snapshot) — those remain.

Backup files

Stage path (in postgres container) size sha256
pre-apply (Phase 3B baseline) /tmp/dieu45_phase3b_pre_apply.dump 83,241,085 28c2a683a3c3ca6b6898d57862702410cc582f4b00d40322528dd2bf7483ddf3
post-apply (Phase 3B exit) /tmp/dieu45_phase3b_post_apply.dump 83,249,241 fd3549d8f62361f0b499cd400c40e81dc6c80aec40e0999b567bcc891653068b

Both are pg_dump -Fc (custom-format, restorable by pg_restore).

Option A — Surgical rollback (preferred for small revert)

The Phase 3B mutations are deliberately small and individually reversible. Run from psql -U workflow_admin -d directus:

BEGIN;

-- 1) Drop the heartbeat ping wrapper
DROP FUNCTION IF EXISTS public.fn_queue_heartbeat_ping_external(text,text,text,jsonb);

-- 2) Drop the vocab sync check fn and its supporting view
DROP FUNCTION IF EXISTS public.fn_iu_section_type_vocab_sync_check();
DROP VIEW     IF EXISTS public.v_iu_section_type_vocab_sync;

-- 3) Remove the 5 added dot_config keys
DELETE FROM public.dot_config WHERE key IN (
  'vocab.section_type.invariant_list',
  'vocab.section_type.matrix',
  'vocab.section_type.open_decision_list',
  'vocab.section_type.rationale',
  'vocab.section_type.reference_mapping'
);

COMMIT;

After this rollback, post-fix tests will fail:

  • fn_iu_resolve_default('matrix','iu_create.default_section_type','vocab.section_type.') returns invalid again,
  • The 5 governed values become un-acceptable to fn_iu_create again,
  • The §15.5 silent-gap marker for iu_outbound_default is still protected as before (Phase 2 created the row; Phase 3B did not touch it),
  • But there is no longer any safe external heartbeat caller (operators would need to call fn_queue_heartbeat_tick directly with the corresponding risk of false-healing iu_outbound_default).

Net effect = Phase 3 baseline.

Option B — Full restore from pre-apply dump

ssh contabo
# inside the box:
docker exec postgres bash -c 'pg_restore -U workflow_admin -d directus --clean --if-exists /tmp/dieu45_phase3b_pre_apply.dump'

Caveats:

  • --clean will drop the post-apply objects before restoring; this is destructive and should only be used if Phase 3B introduced an unrecoverable problem.
  • This restore will also revert any unrelated background-rate writes that happened between the pre-apply dump and now (e.g. event_outbox background rows, hc_executor_last_run updates).
  • Prefer Option A unless something inside Phase 3B is irreparably broken.

Verification after rollback

SELECT count(*) AS dot_config_vocab_keys
  FROM dot_config WHERE left(key,length('vocab.section_type.'))='vocab.section_type.';
-- expect 13 after Option A; could differ after Option B depending on unrelated drift

SELECT count(*) FROM pg_proc WHERE proname IN ('fn_queue_heartbeat_ping_external','fn_iu_section_type_vocab_sync_check');
-- expect 0

SELECT count(*) FROM pg_class WHERE relname='v_iu_section_type_vocab_sync';
-- expect 0

What rollback does NOT touch

Item Reason
Phase 3 17 Điều 37 IUs Pre-Phase-3B durable; outside Phase 3B scope.
Phase 3 queue_heartbeat rows (dieu45_phase3_pilot, iu_outbound_default) Created in Phase 3 / Phase 2.
Phase 3 6 job_queue rows Created in Phase 3.
fn_iu_create body Unchanged through Phase 3B (md5 dcade99af1ef096892748c9f14082e11).
MARK/CUT alias bodies Unchanged through Phase 3B (md5 pinned in [[04-queue-d30-regression-pack]]).
tac_section_type_vocab table Untouched.
event_outbox, iu_vector_sync_point, production_documents, pg_extension Untouched.
All risk-bearing gates Already at safe defaults at exit.

Rollback risk assessment

Option A is low-risk:

  • Only 8 catalog objects are dropped/deleted (1 fn wrapper, 1 fn check, 1 view, 5 rows).
  • No object outside Phase 3B's add-list depends on them (verified: nothing in pg_depend references the new objects from outside Phase 3B).
  • Post-rollback, the system reverts to a known-good Phase 3 baseline (governance silent-gap surfaced but unprotected by ping-wrapper, vocab gap re-opened).

Option B carries the standard --clean blast radius (drops the whole post-apply schema before restoring). Reserved as a last resort.

Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.6-dieu45-phase-3b-queue-cutter-hardening/07-rollback-package.md