FIX7 Refactor Blueprint - Dependency-Safe Construction Order
04 - Dependency-Safe Construction Order
<!-- DOC_STATUS: ACTIVE_AUTHORITY --> <!-- AUTHORITY_BOUNDARY: registry in 00-readme-first.md §Active-authority boundary -->CODEX RECHECK-3 PATCH (2026-06-09) — typed set separation. The operational target for S15/S16/S17 is the PG-object-only set
U_legacy_object(doc 02 §H.4.A); privilege reconciliation at S15.2 runs over the separateU_legacy_object × U_effective_privilege_principaljoin to sealed #21 (§H.4.B); entry-vector bypass (triggers/scheduler/DOT) is the separateU_entry_vectorcoverage relation (§H.4.C), never object membership. GuardsG-U-LEGACY-OBJECT-ONLY,G-PRINCIPAL-SET-SEPARATE,G-ENTRY-VECTOR-SEPARATE(doc 06).OPTION-BETA PATCH (2026-06-08). Codex (design owner) approved Option Beta for the legacy-disposition blocker. This doc is patched to that ruling: the five-value disposition enum,
LEGACY_*#20 rows, the computed classifier,STUB_FAIL_CLOSED/legacy body mutation/body-restore, theDO_NOT_TOUCHsubtraction fromU_legacy, and all policy branching by relkind/prokind/name/ owner/pattern/label are removed. EveryU_legacymember converges to the single uniform end-state: owner-isolated toqt001_cp_owner, body unchanged, effective privileges exactly equal the closed-world sealed #21 rows.relkind/prokindchoose only PostgreSQL syntax (theALTER ... OWNER/REVOKE/ privilege-verification form), never policy. The recheck-2 in-blueprint fixes remain valid and unchanged:
- A owner-unreachable:
qt001_cp_owneris NOLOGIN (CP-01 §2.1) and has no inboundpg_auth_membersmembership fromdirectus/runtime/login roles; the only SET-ROLE path is the sealed Level-B migrator/owner principal (CP-09principal_registry).G-OWNER-UNREACHABLE(doc 06).- F superuser break-glass:
workflow_admin(liverolsuper=true/rolbypassrls=true/login) is outside the ACL-zero model; the FIX7 operator session is the Level-B migrator principal, neverworkflow_admin; readiness requires "no unauthorized superuser use path," not effective-priv=0;G-SUPERUSER-BREAKGLASS.- G/E forward-only: rollback NEVER clears/edits
activated_at; it supersedes forward (new candidate + newmanifest_activation, predecessorsuperseded_by_manifest_idset). Current active =activated_at IS NOT NULL AND superseded_by_manifest_id IS NULL. Legacy owner/ACL rollback source = the S14 snapshot bound bymanifest_activation.rollback_evidence_id. No legacy body restore exists under Option Beta (no body was changed).- H seal order: #11/#20/#26/#27 and all root/closure bindings are authored (S13) and rehearsed BEFORE the COMPLETE rehearsal seal; production seal/stage and live cutover are separate later phases.
G-SEAL-AFTER-AUTHOR-REHEARSE.- D operator authorization: bound to the existing typed PG authority model (CP-09 Level-B + #07
authority_action+ #20/#21 scope + #16 signoff + #19 quorum + #08 separation +manifest_activationcandidate-payload/epoch), not an external artifact (doc 07).- C resolved by Option Beta: no
LEGACY_*#20 row, no disposition, no STUB body. Membership =closure(#11, roots=#20 protected_target rows)with no subtraction; boundary collisions fail closed. End-state is uniform (above). New guardsG-U-LEGACY-OPTION-BETA-UNIFORM-ENDSTATEandG-LEGACY-NO-DISPOSITION-AUTHORITY(doc 06).
This is the future construction order, not SQL to apply now. It extends the approved RP-03 "Normative Creation Order" (10 steps) and the doc 02 §2.6 reversal with the refactor-specific steps (legacy neutralization/retention, authoritative repoint, owner/ACL cutover). Every destructive or live step is explicitly OPERATOR_GATED; T1-authorable steps produce reviewable artifacts only.
Legend - who: T1 = T1 may author the artifact (no apply); OP = operator must run the live
step under explicit authority. proof references guards in doc 06. no-go = stop condition.
| step | name | object / action | preconditions | type | who | proof after | rollback (doc 05) | no-go |
|---|---|---|---|---|---|---|---|---|
| S00 | re-baseline inventory (candidate discovery = diagnostic only) | re-dump live qt001/birth/DOT defs + ACL + ownership; enumerate and capture the current Directus SELECT grant set on business base tables (MX-1, consumed by S09 #21); produce a CANDIDATE legacy set by name + owner (live 2026-06-08: 45 functions + 1 procedure + 20 tables + 196 views, all owner directus, all proacl=NULL/PUBLIC EXECUTE, none SECURITY DEFINER; 0 qt001 routines outside public; 0 trigger bypass vector) - this candidate set is evidence ONLY and is explicitly non-binding (name-pattern fragility is live-proven: views = 0/183/196 by literal - doc 01, doc 02 §H.1); classify all UNKNOWN_REQUIRES_REVIEW. The operational target for S15/S16/S17 is NOT this scan - it is the closed sealed U_legacy set (doc 02 §H): closure(#11, roots = sealed #20 protected_targetrows + #26protected_target_set_sha256), both-EXCEPT proven vs the closed PG-native denominator (§H.4), no DO_NOT_TOUCH subtraction, boundary collisions fail closed. Every member receives the single uniform end-state (no disposition) |
design approved | read-only | T1 | candidate captured == doc 01; 0 unknown; Directus SELECT set captured; G-DOT-FROZEN/G-DOT-NOOVERWRITE baseline; no step may treat the S00 scan as authority (G-LEGACY-TARGET-SEALED) | n/a | any unknown object role; Directus SELECT set not captured; any operational target derived from name pattern alone |
| S01 | roles + schema + domains | create 3 roles, qt001_cp, 4 domains |
S00 | ADD | OP | roles/schema/domains exist, owner-isolated | drop empty schema/roles | schema name collision |
| S02 | catalog root | code_catalog_set/_family/_item + sealed bootstrap + owner-only immutable trigger + 3 exact-set families |
S01 | ADD | OP | G-CATALOG-SEAL; families both-EXCEPT | drop empty catalog (no refs) | bootstrap seal mismatch |
| S03 | manifest anchors | manifest_set, manifest_item_envelope (global-unique item_id), immutable trigger |
S02 | ADD | OP | conservation rule; immutable trigger fires | drop empty anchors | DELETE/TRUNCATE not denied |
| S04 | 27 child contracts | create #01..#27 in dependency order; 4 forward child FKs DEFERRED | S03 | ADD | OP | 27 tables exist; headers exact | reverse-order drop empty (doc 02 §2.6) | any contract DDL conflict -> T1 stop |
| S05 | operator/operand compat | operator_operand_compatibility |
S04 | ADD | OP | G-OPERAND-TYPED (operand type matches compat for every rule/measurement operand); typed-operand CHECK coverage | drop empty | type mismatch |
| S06 | registries + activation | evidence_registry,human_identity_registry,principal_registry,analyzer_run,manifest_activation |
S04 | ADD | OP | FK targets resolvable | drop empty | cycle not breakable |
| S07 | 11 runtime-evidence tables | create non-authority tables; 7 RANGE-partitioned; FK to registries/anchors inline | S06 | ADD | OP | G-RUNTIME-NONAUTH (count=11, not in 27); inbound FK stable | reverse-order drop empty | any classed as authority |
| S08 | deferred constraints | apply all deferred FK groups 1..5 (doc 06 RP-03) incl cycle-break ALTERs | S04,S06,S07 | ADD | OP | both-EXCEPT constraint set; dropped-FK rehearsal -> OBJECT_AUTHORITY_IMMUTABLE | drop added constraints | any deferred FK missing |
| S09 | sealed DATA: catalog + 27 manifest rows + U_legacy roots/closure + closed-world #21 |
seed code_catalog rows; 27-manifest item rows; #20 authority-scope rows (TABLE/CONSTRAINT/INDEX/runtime-evidence + expected_constraint_set_sha256) including the sealed protected_target=true TABLE roots; dependency_manifest #11 reverse-closure rows from those roots (#24 analyzer); #26 protected_target_set_sha256; #27 repoint old/new source bindings; the closed-world privilege_set_manifest #21 desired-privilege set (== existing Directus SELECT set for preserved reads; NO EXECUTE/DML row for any U_legacy legacy object). No LEGACY_* #20 row, no disposition column, no STUB body artifact, no expected_legacy_set_sha256 - Option Beta. Set integrity is the manifest seal (not a new hash) |
S08 | ADD(DATA) | OP | G-EXACTSET-20; G-LEGACY-TARGET-SEALED (sealed U_legacy = #20 roots + #11 closure; 0 unknown); G-LEGACY-TARGET-CLOSED-DENOMINATOR (both-EXCEPT-equal to the closed universe §H.4; no subtraction); G-U-LEGACY-OPTION-BETA-UNIFORM-ENDSTATE (the #21 desired set is closed-world and assigns the uniform end-state to every member); G-DIRECTUS-READ preflight |
new candidate version | seed count != expected_item_count; U_legacy both-EXCEPT vs closed denominator non-empty; any member unclassified; any boundary collision unresolved; #21 not closed-world over U_legacy |
| S10 | sealed DATA: 14 gates + 7 hashes + thresholds | readiness_gate_manifest 14 rows; hash_component_manifest H01..H07 incl H04_SCOPE_V1 + H02/H05 total orders; #05 retention/#06 sealed thresholds; #23 workload profiles |
S09 | ADD(DATA) | OP | G-GATES-14; G-HASH-7; G-HASHDET (H01/H02/H04/H05 recompute) | new candidate version | gate/hash count off; hash non-deterministic |
| S11 | exact-set verification | both-EXCEPT child vs envelope; family coverage; adapter-input edge (#24 vs #11); PG constraint/index both-EXCEPT; CP-06 fixtures | S09,S10 | verify | T1+OP | all both-EXCEPT empty; fixtures pass | n/a (read) | any EXCEPT non-empty |
| S12 | seal candidate | seal manifests: child==envelope, count==expected, ordinals contiguous, hashes recompute | S11 | SEAL | OP (quorum) | seal accepts only if every check passes | unseal not allowed; new version | any seal check fails |
| S13 | authoritative repoint authoring | author gateway_manifest #26 (pin the QT001 writer gateway identity + protected_target_set_sha256 - §Writer-gateway-identity below) + writer_repoint_manifest #27: bind old/new source_sha256 and rollback_stub_source_sha256 (re-point bindings only - no legacy body artifact, no STUB body; Option Beta); dependency_manifest #11 closure proves new entrypoints reach NO legacy object |
S00,S12 | ADD(DATA) | T1 author | G-REPOINT-SRC; G-WRITER-GATEWAY-IDENTITY (gateway pinned by regprocedure+source_sha256+owner); G-NOLEGACY-PRE (#11 closure legacy_reached=0, non-vacuous; sealed U_legacy complete, 0 unknown, uniform end-state assigned to every member - does NOT require EXECUTE yet revoked); G-LEGACY-TARGET-CLOSED-DENOMINATOR (sealed set both-EXCEPT-equal to the closed universe §H.4) |
rollback stub repoints back (no body change) | any legacy object reachable; gateway identity not pinned; any unknown; denominator not closed; boundary collision |
| S14 | stage cutover + pre-cutover owner/ACL snapshot (NO activation yet - Codex recheck BLOCKER D/H) | the sealed manifest stays STAGED (manifest_set.sealed_at set, activated_at NULL; the #26 gateway routes fail-closed; readiness BLOCKED; the live writer is still on legacy). Capture the COMPLETE effective-privilege snapshot - owner + relacl/proacl + pg_attribute.attacl column ACL + sequence ACL + nspacl + pg_default_acl + role-membership effective privilege (pg_auth_members) over the sealed set + control objects - hash-bound (snapshot_sha256), read-back-verified, restore-rehearsed BEFORE any owner transfer or REVOKE (the snapshot must precede S15.1 ownership transfer, not S16). The snapshot is the sole legacy rollback source under Option Beta (no body to restore) |
S12,S13 | SNAPSHOT (read + stage) | OP | snapshot present + hash-bound + read-back-verified + restore-rehearsed; manifest STAGED (activated_at NULL) not ACTIVE; G-NOMIXED-AUTHORITY holds (legacy is the sole authoritative path; the new path is staged-inactive, so no mixed authority) |
discard staged state; delete snapshot artifact | snapshot absent/unverified; manifest ACTIVATED before legacy neutralization |
| S15 | atomic legacy neutralization to the uniform Option-Beta end-state + activation + repoint (ONE operator transaction, strictly ordered) | because directus (live: non-superuser, rolsuper=false) OWNS every legacy routine, an owner retains implicit EXECUTE, so REVOKE alone cannot make directus effective-EXECUTE = 0; the step runs ordered (Codex recheck BLOCKER A/D): S15.1 ALTER ... OWNER TO qt001_cp_owner for every supported sealed U_legacy member (uniform; relkind/prokind choose only the ALTER FUNCTION/ALTER TABLE/ALTER VIEW syntax) - moves the implicit owner privilege off directus to the NOLOGIN, non-superuser, unreachable qt001_cp_owner; S15.2 reconcile effective privileges to exactly the sealed #21 rows over the COMPLETE sealed set (both-EXCEPT) - for every legacy member #21 grants no EXECUTE/DML, so REVOKE EXECUTE/relevant privileges from PUBLIC/directus/every role except qt001_cp_owner; no body is replaced or stubbed for any member (Option Beta); S15.3 verify G-NOLEGACY-POST + G-U-LEGACY-OPTION-BETA-UNIFORM-ENDSTATE (over the whole set: owner=qt001_cp_owner, definition hash unchanged, effective privileges == exact #21; non-superuser non-owner effective EXECUTE/DML = 0; the cluster superuser workflow_admin explicitly dispositioned; qt001_cp_owner owner-implicit privilege held by an unreachable NOLOGIN principal); S15.4 ACTIVATE the sealed manifest (exact quorum + epoch binding via manifest_activation, one ACTIVE per type) AND repoint the live writer to the #26-pinned gateway; S15.5 verify G-NOMIXED-AUTHORITY + G-WRITER-GATEWAY-IDENTITY + gateway fail-closed. Activation (S15.4) happens only AFTER legacy is neutralized (S15.1-S15.3), so no committed state has an ACTIVE new path beside an executable legacy path |
S14 | ATOMIC LIVE (owner→reconcile→verify→activate→repoint) | OP (quorum) | precondition G-NOLEGACY-PRE + G-LEGACY-TARGET-CLOSED-DENOMINATOR + the S14 snapshot verified + valid operator_authorization (doc 07); proof G-NOLEGACY-POST, G-U-LEGACY-OPTION-BETA-UNIFORM-ENDSTATE, G-LEGACY-NO-DISPOSITION-AUTHORITY, G-NOMIXED-AUTHORITY, G-WRITER-GATEWAY-IDENTITY, G-EPOCH-TOCTOU, G-DOT-NOOVERWRITE, G-BIRTH-NEUTRAL | atomic deactivation-first rollback (doc 05 §note 5): deactivate new path → verify readiness BLOCKED → verify gateway cannot route → restore legacy by replaying the S14 owner+ACL snapshot (restore prior owner directus + captured ACL; no body change) → G-NOMIXED-AUTHORITY |
any legacy effective-executable by non-superuser non-owner OR reachable; mixed old+new authority; directus still owns an executable legacy routine; any member's effective privileges != exact #21; birth row delta; gateway identity/route drift; any boundary collision |
| S16 | owner/ACL cutover (control-plane scoped; U_legacy member ownership already moved at S15.1) |
transfer ownership of the remaining scoped objects - the qt001_cp control objects (if any reside under another owner) + any legacy relation not already moved as a U_legacy member - to qt001_cp_owner; reconcile residual directus/PUBLIC authority on those control objects to exact #21; re-grant exact #21 SELECT to Directus. The #26 QT001 writer gateway is born qt001_cp_owner at PKG-E (no transition). Directus retains full authority over its own directus_* app tables and the business base tables it legitimately owns (XH-4). Uses the S14-captured snapshot for rollback - it does NOT capture a new snapshot, because the snapshot must precede the S15.1 owner transfer (Codex recheck BLOCKER H) |
S15 | LIVE ACL | OP | precondition: the S14 effective-privilege snapshot present + hash-bound + read-back-verified (doc 05 invariant 3) + valid operator_authorization; proof G-OWNER-CUTOVER (effective-privilege, role-membership-aware, superuser workflow_admin dispositioned), G-DIRECTUS-APP-INTACT, G-DIRECTUS-READ (SELECT preserved), PUBLIC EXECUTE on control objects gone |
restore prior ownership + full effective-privilege ACL from the S14 snapshot (both-direction effective-privilege match) | Directus loses required SELECT or app-table authority; readiness un-blocks falsely; S14 snapshot absent/unverified |
| S17 | legacy retention (uniform end-state on superseded relations) | apply the same uniform end-state to the superseded legacy relations that are U_legacy members (20 tables + reached views): owner-isolated, effective privileges == exact sealed #21 (writes absent; any retained SELECT exists only because a #21 SELECT row grants it), definition/body unchanged (no stub), plan_v2 stays unreachable. This is not a FREEZE_NO_CHANGE/DEPRECATE_READONLY disposition - it is the uniform #21 end-state, retained forward-only |
S15 (#11 proven non-dependence) | RETAIN | OP | G-U-LEGACY-OPTION-BETA-UNIFORM-ENDSTATE (over the relations); G-LEGACY-TARGET-SEALED (over the sealed set); birth/QT-002 path intact | restore prior grants/owner per the S14 snapshot | birth gateway transitively depends on a retained object |
| S18 | legacy deprecate-marker (history retention) | mark the superseded legacy qt001_* as deprecated/read-only history (a descriptive sentinel, not an authority disposition); never DROP; retain as read-only history governed by #21 |
S17 + stable active period | RETAIN | OP | history readable per #21; no active reference | clear the deprecation marker | any active reference remains |
| S19 | post-cutover verification | re-run all guards; readiness gate facts; bypass-vector facts; scale runs (REAL_RUN, separately gated) | S18 | verify | T1+OP | full 47-guard suite green incl. G-NOLEGACY-POST/G-U-LEGACY-OPTION-BETA-UNIFORM-ENDSTATE/G-LEGACY-NO-DISPOSITION-AUTHORITY/G-U-LEGACY-OBJECT-ONLY/G-PRINCIPAL-SET-SEPARATE/G-ENTRY-VECTOR-SEPARATE/G-ACTIVE-AUTHORITY-SCOPE/G-NO-SUPERSEDED-CONSUMPTION/G-NOMIXED-AUTHORITY/G-WRITER-GATEWAY-IDENTITY/G-LEGACY-TARGET-SEALED/G-LEGACY-TARGET-CLOSED-DENOMINATOR/G-NO-QT001-PERMIT-DURING-FIX7/G-DOT-NOOVERWRITE; readiness reflects real facts | n/a | any guard red |
Dependency notes
- FK cycles (manifest_set <-> manifest_activation; evidence/identity/principal) are broken by the deferred ALTERs in S08 (doc 06 groups 3-5), exactly as approved RP-03.
- The 4 forward child FKs (policy-rule/operator; metric/unit; capability/workload; signoff/tier) are deferred to S08 so the 27 tables can be created in any internal order in S04.
- Expected-constraint catalog (#20) must be seeded in S09 BEFORE seal S12 so S11 both-EXCEPT has a
target; the dropped-deferred-FK rehearsal in S08 must already fail
OBJECT_AUTHORITY_IMMUTABLE. - regclass binding order (XHigh-E):
hash_component_manifest#10 hassource_relation regclass NOT NULL, so the runtime-evidence tables (S07) and the 27 surfaces (S04) MUST physically exist before any #10/H02/H04/H05 row is seeded (S10). The order S04/S07 < S10 already satisfies this; the constraint is now explicit so an implementer cannot reorder #10 seeding ahead of its referenced relations. Likewisestorage_class_manifest/adapterregprocedurecolumns require the referenced functions to exist before those rows seed. - The authoritative repoint (S13->S15) is the load-bearing refactor act and the historical failure
point: it MUST be gated on the
dependency_manifest#11 closure proof (G-NOLEGACY-PRE before the cutover, G-NOLEGACY-POST after it - the guard is phase-split, Codex BLOCKER 2), reproducing the FIX5 recursive-callgraph discipline as sealed data over the sealedU_legacyset, not a name deny-list. PRE proves structural closure + sealed-set completeness + the uniform end-state assigned + staged rollback and does NOT require EXECUTE already revoked (so it can gate the very step that revokes); POST proves the uniform end-state actually holds (owner=qt001_cp_owner, body unchanged, effective privileges == exact #21; non-superuser non-owner executability=0) after the owner-transfer + privilege reconcile (S15.1-S15.2). This removes the prior deadlock (a single G-NOLEGACY required green before the action that made it green). - PostgreSQL owner semantics (Codex recheck BLOCKER A - decisive). An object's owner retains
implicit privileges;
REVOKE EXECUTEcannot make the owner's effective EXECUTE zero while it still owns the routine.directus(live read-only 2026-06-08:rolsuper=false) OWNS every legacyqt001_*routine. Therefore G-NOLEGACY-POST's "directuseffective EXECUTE = 0" is impossible by REVOKE alone and is only reachable AFTER ownership is moved offdirectus. The order is fixed: S15.1 ownership transfer (offdirectus→qt001_cp_owner) precedes S15.2 privilege reconcile precedes S15.3 POST verification.qt001_cp_owneris NOLOGIN, non-superuser, and not granted to any login role, so its owner-implicit EXECUTE is held by an unreachable principal. Superusers (live: the cluster superuserworkflow_admin,rolsuper=true/rolbypassrls=true) inherently bypass all object ACL and CANNOT be made privilege-zero by ownership/ACL changes; every effective-privilege guard (G-NOLEGACY-POST, G-U-LEGACY-OPTION-BETA-UNIFORM-ENDSTATE, G-OWNER-CUTOVER) therefore computes over non-superuser, non-owner roles and explicitly dispositions the superuser as an accepted out-of-band property outside FIX7's removable scope - it is documented, not silently assumed. - Owner reachability (recheck-2 BLOCKER A). Making
directusnon-owner is necessary but not sufficient: the new ownerqt001_cp_ownermust itself be operationally unreachable, else the owner-implicit EXECUTE is just relocated to a reachable principal. The blueprint requires, andG-OWNER-UNREACHABLE(doc 06) verifies overpg_roles/pg_auth_members: (a)qt001_cp_ownerisNOLOGIN(approved CP-01 §2.1) and non-superuser; (b) no role with login (directus, runtime, app, or anyrolcanloginrole) is a direct or transitive member ofqt001_cp_ownerinpg_auth_members— so no login principal canSET ROLE qt001_cp_owner; (c) the only sanctioned path to act as the owner is the sealed Level-B migrator/owner principal (principal_registry.auth_db_rolebound to a verifiedhuman_identity_registryrow of the requiredprincipal_class, CP-09), used only inside an authorized cutover transaction; (d)qt001_cp_ownermust hold no grants to any login role. A guard that asserts "legacy effective EXECUTE = 0" while the owner role is reachable is itself a defect. - Superuser break-glass (recheck-2 BLOCKER F).
workflow_admin(liverolsuper=true,rolbypassrls=true,rolcanlogin=true) bypasses all object ACL and RLS and cannot be reduced to effective-privilege zero by any ownership/ACL change — it is outside the ACL-zero model entirely. The blueprint therefore (a) treats superuser/bypassrlsuse as break-glass / operator-gated, never as a normal operational path; (b) requires every FIX7 live step (S15/S16) to run as the Level-B-bound migrator principal, never asworkflow_admin; (c) reframes readiness from "superuser effective privilege = 0" (impossible) to "no unauthorized superuser use path" — proven by the operator session identity being the Level-B principal plus monitoring (pg_stat_activity/ audit) showing noworkflow_adminsession in the cutover window; (d) addsG-SUPERUSER-BREAKGLASS(doc 06), which FAILS if aworkflow_admin(or anyrolsuper/rolbypassrls) session performs FIX7 authority changes outside an explicitly authorized Level-B break-glass record. The break-glass policy and any superuser use remain OPERATOR-gated and outside T1's authorable scope. - Author / rehearse / seal order (recheck-2 BLOCKER H). All load-bearing artifacts — #11 closure,
the
U_legacyroots/denominator, #20/#26/#27 rows, the closed-world #21 set, and the rollback/ operator-authorization bindings — MUST be authored and statically validated, then rehearsed against the exact same artifact set, BEFORE any complete rehearsal seal, and the seal hashes MUST be computed from the final authored artifacts. The prior order (S12 seal before S13 authors #26/#27) is corrected: #26/#27 and the root/closure bindings are authored at S13 and the COMPLETE rehearsal seal occurs only after S13 (the production seal/stage S12-equivalent and the live cutover S15/S16 are distinct later phases — author → static-validate → rehearse-exact-set → compute-hashes → seal → independent review → operator authorization → apply/cutover, with no implicit reordering of the numbered normative dependencies).G-SEAL-AFTER-AUTHOR-REHEARSE(doc 06) FAILS if any manifest is sealed before the artifact it seals exists and was rehearsed, or if any activation precedes seal/review/authorization. See doc 07 for the corrected package sequence. - Owner/ACL cutover (S16) MUST run only after S15 (which now performs the activation at S15.4),
because it reconciles the residual
directusauthority and finishes any remaining legacy-relation ownership move - doing it earlier would orphan the live writer. The executable legacy ROUTINE ownership is already moved at S15.1 (it is a precondition for effective-EXECUTE=0); S16 handles the remaining relations and residual grants. - Activation order / no mixed authority (Max-D + Codex BLOCKER 4 + recheck BLOCKER D). Activation
is STAGED at S14 (
activated_atNULL; the manifest is sealed-not-active, the gateway routes fail-closed, readiness BLOCKED) and only flipped to ACTIVE at S15.4 - AFTER legacy is neutralized (S15.1-S15.3). G-NOMIXED-AUTHORITY tests a PG-native route/authority fact (an ACTIVEmanifest_activationfor the writer type, i.e.manifest_set.activated_at IS NOT NULL, vs legacy effective-executability), NOT mere manifest existence: a STAGED manifest beside executable legacy is NOT mixed (legacy is the sole authoritative path); an ACTIVE manifest beside executable legacy IS forbidden and cannot occur because activation follows neutralization within one atomic transaction. The whole S15 (owner→reconcile→verify→activate→repoint) is a single atomic operator transaction; any sub-step failing rolls the whole transaction back fail-closed, so no observable intermediate state leaks. The S15 rollback is an explicit ordered deactivation-first sequence (doc 05 note 5): (1) supersede the new authoritative path FORWARD — never clear or editactivated_at(recheck-2 BLOCKER G): a rollback is a NEWmanifest_activationof a prior-payload candidate (newactivation_id/control_epoch/quorum/evidence) plus setting the predecessor'ssuperseded_by_manifest_id; the active row is derived by themanifest_setpartial unique indexactivated_at IS NOT NULL AND superseded_by_manifest_id IS NULL, so the predecessor'sactivated_atand history stay immutable (CP-01 §2.1/§2.4); (2) verify readiness BLOCKED via the derived current-active route (not a mutated timestamp); (3) verify the gateway cannot route the new path; (4) only THEN restore legacy state purely by replaying the verified S14 owner+ACL snapshot — restore the prior owner (directus) + captured ACL, with NO body change (Option Beta removes the STUB body-restore path entirely), uniquely sourced from the snapshot artifact bound bymanifest_activation.rollback_evidence_id; (5) verify G-NOMIXED-AUTHORITY + G-BIRTH-NEUTRAL. Any step that cannot prove the safe-blocked state halts fail-closed. The "never CREATE OR REPLACE the gateway" rule applies to theqt001_cpwriter gateway and the birth gateway (owner-isolation / HARD_BLOCK); under Option Beta no legacy body is ever replaced or restored, so there is no body-replacement operation at all in the legacy path (this removes the former CR-E3 carve-out). S16 partial failure restores ownership + full effective-privilege ACL from the verified S14 snapshot. - Legacy retention (S17/S18) MUST run only after #11 proves no live-required object (birth gateway, QT-002) depends on the retained target.
Writer-gateway-identity (phase-explicit; Codex BLOCKER 6 / CHECK_D)
S15/S16 reference the writer gateway by pinned identity, never a name pattern. The QT001
control-plane writer gateway is the single sealed gateway_manifest #26 row:
| attribute | value / contract |
|---|---|
| object | the QT001 control-plane writer gateway function in schema qt001_cp |
| identity | regprocedure (schema + name + identity arguments) + prokind, pinned in #26 |
| owner before S15 | qt001_cp_owner (born owner-isolated at PKG-E/S01-S14; there is NO directus phase for the new gateway) |
| owner after S15 | qt001_cp_owner (unchanged) |
| owner after S16 | qt001_cp_owner (no owner transition - resolves the CHECK_D ambiguity) |
source_sha256 before/after |
the #26-bound hash, unchanged across cutover - the cutover repoints the live writer to route through the gateway via manifest_activation, it does not rewrite the gateway body |
| expected active path after S15 | live writer → #26 gateway → manifest-active path |
| expected active path before S15 | legacy apply/writer (directus-owned, member of the sealed U_legacy set) |
| rollback path | #27 rollback_stub_source_sha256 re-points away from the new gateway; legacy restored purely by the S14 owner+ACL snapshot (no body change) |
| #26 binding | gateway identity + source_sha256 + fail_closed=true + protected_target_set_sha256 |
| #27 binding | old_source_sha256 = legacy writer; new_source_sha256 = #26 gateway; rollback_stub_source re-point binding (no legacy body artifact) |
fn_birth_registry_auto |
HARD_BLOCK; explicitly NOT the QT001 writer gateway (it is the birth gateway, a different layer; directus-owned; protected by G-BIRTH-NEUTRAL + G-DOT-FROZEN + policy, not owner-isolation; a closure that reaches it is a boundary collision → fail closed) |
Phase-explicit ownership of the objects S15/S16 touch (uniform end-state; no per-object disposition):
| object class | owner before S15 | after S15 | after S16 |
|---|---|---|---|
new qt001_cp writer gateway (#26) |
qt001_cp_owner |
qt001_cp_owner |
qt001_cp_owner |
legacy apply/writer routines (U_legacy members) |
directus |
qt001_cp_owner (transferred at S15.1; body unchanged; effective privileges == exact #21 → EXECUTE = 0) |
qt001_cp_owner |
other legacy routines (U_legacy members) |
directus |
qt001_cp_owner (transferred at S15.1; body unchanged; effective privileges == exact #21 → EXECUTE = 0) |
qt001_cp_owner |
legacy tables/views (U_legacy members) |
directus |
qt001_cp_owner if reached + transferred at S15.1; otherwise directus (no EXECUTE concern; relation move deferred to S16) |
qt001_cp_owner; effective privileges == exact #21 (retained SELECT only if a #21 row grants it) |
birth gateway fn_birth_registry_auto |
directus |
directus |
directus (HARD_BLOCK boundary; collision → fail closed) |
The owner-transfer of executable routines at S15.1 precedes the privilege reconcile at S15.2
specifically because PostgreSQL owners keep implicit EXECUTE (Codex recheck BLOCKER A): leaving an
executable legacy routine owned by directus after S15 would keep directus effective-EXECUTE
non-zero and fail G-NOLEGACY-POST. The legacy tables/views carry no EXECUTE, so a relation whose
ownership move is not needed for effective-EXECUTE=0 may have its move deferred to S16 with the rest
of the relation cutover; either way every member reaches the uniform end-state.
Guard G-WRITER-GATEWAY-IDENTITY (doc 06) verifies the live active writer post-S15 == the #26-bound
regprocedure with matching source_sha256 and owner qt001_cp_owner; that the legacy writer/apply
objects are members of the sealed #20-root/#11-closure set; and that fn_birth_registry_auto is
unchanged. No guard may assume the post-S16 owner state at S15 (each phase has its explicit expected
owner above).
No-SQL-now boundary
This document defines order only. No CREATE/ALTER/GRANT/REVOKE/seal/activate is performed. S01-S19 each become reviewable artifacts in later, separately authorized packages (doc 07), and the LIVE/SEAL/ACTIVATE/REVOKE/RETAIN steps are OPERATOR_GATED.