04 — Axis Registry / Assignment Rehearsal Results (live, BEGIN..ROLLBACK)
04 — Axis Registry / Assignment Rehearsal Results (live, BEGIN..ROLLBACK)
Package:
one-roof-auth-axis-bootstrap-ratification-rehearsal-go-nogo-2026-06-02Mode: author-mode live rehearsal, sameBEGIN … ROLLBACKas doc 03, zero COMMIT, zero residue. Object specs: hardening doc 05 (axis_registry/axis_assignmentCREATE-TABLE) + doc 04 (axis model).
4.1 What was rehearsed (R3 + R9)
| Phase | Object / action | Result |
|---|---|---|
| R3 | axis_registry table + 5 CHECK vocabularies + 2 indexes |
COMPILED |
| R3 | axis_assignment table + FK→axis_registry + self-FK + chk_provenance_or_quarantine + 2 partial-uniques + 2 indexes |
COMPILED |
| R9 | seed 1 uncertain axis (AX-TOPIC) + 1 deterministic axis (AX-RECON) |
inserted (under rollback) |
| R9 | candidate / approved / quarantine zone behaviour + UI-visibility gate | PASS |
| R9 | 6 axis constraint negative/positive tests (A1–A7) | PASS (detail in doc 05) |
4.2 axis_registry (SB-AXIS-1) — compiled live (R3)
Created per hardening doc 05 §5.1 with full CHECK vocabularies as text, not enums (Điều 37 no-hardcode):
axis_family ∈ (structural,label,semantic,pivot,system);axis_kind ∈ (deterministic,uncertain,system)(the behavioural switch);scope ∈ (global,domain-local,object-local);node_kind ∈ (taxonomy_node,information_unit,born_entity);relation_store ∈ (iu_relation,universal_edges,taxonomy_parent,entity_relations,none);assignment_store ∈ (entity_labels,iu_metadata_tag,axis_assignment,iu_parent_ref,intrinsic);lifecycle_status ∈ (birth,register,active,deprecate,retire)(defaultregister);cardinality ∈ (single,multiple);max_labels_per_entitydefault 0 (matches FAC-08 today);- soft text refs for
owner_scope_ref/coverage_rule_ref/issue_path_ref(hardened to FK when SB-2/SB-11 land — avoids ordering deadlock); - indexes on
(axis_family,axis_kind)and(lifecycle_status).
psql: CREATE TABLE + 2×CREATE INDEX. Two rows seeded under rollback: AX-TOPIC (semantic/uncertain/assignment_store=axis_assignment/cardinality=single/lifecycle=active) and AX-RECON (structural/deterministic/assignment_store=intrinsic) — proving both behavioural classes register as plain rows.
4.3 axis_assignment (SB-AXIS-2) — compiled live (R3)
Created per hardening doc 05 §5.2, including the canonical-key fix (H1): keys on entity_collection + entity_code (matching live entity_labels/birth_registry), never canonical_address (NULL in all birth rows). Key columns/constraints:
id uuid PK default gen_random_uuid();axis_codeFK →axis_registry;entity_kind ∈ (information_unit,born_entity,collection);zone ∈ (approved,candidate,quarantine)defaultcandidate; separatematch_scorevsconfidence(never collapse score into approval state);assigned_by ∈ (dot,agent,human,rule);valid_time tstzrangedefault[now,);revision;superseded_byself-FK;status ∈ (active,superseded,retracted);chk_provenance_or_quarantine=provenance IS NOT NULL OR zone='quarantine';uq_axis_assignment_active=UNIQUE(axis_code,entity_collection,entity_code,node_ref) WHERE status='active';uq_axis_single_approved=UNIQUE(axis_code,entity_collection,entity_code) WHERE status='active' AND zone='approved'.
node_ref and rule_ref were kept soft refs in the rehearsal (production hardens node_ref → taxonomy(code), rule_ref → label_rules(id)); this keeps the rehearsal self-contained while still exercising the FK to axis_registry, the provenance guard, both partial-uniques and the self-FK. psql: CREATE TABLE + 4×CREATE INDEX (2 partial-unique + 2 plain).
4.4 Zone / candidate / approved / quarantine behaviour (R9)
| Test | Input | Result | Invariant |
|---|---|---|---|
| A1 | candidate + provenance present | ALLOWED | well-formed candidate |
| A2 | zone='candidate', provenance=NULL |
REJECTED (chk_provenance_or_quarantine, 23514) |
a candidate must carry provenance |
| A3 | zone='quarantine', provenance=NULL |
ALLOWED | quarantine is the safe sink for missing provenance |
| A4 | axis_code not in axis_registry |
REJECTED (FK, 23503) | no orphan assignment / anti-island |
| A5 | two zone='approved' on same entity, single-cardinality axis |
2nd REJECTED (uq_axis_single_approved, 23505) |
one approved node per single-axis entity |
| A6 | duplicate status='active' (same axis/collection/entity/node) |
2nd REJECTED (uq_axis_assignment_active, 23505) |
one active assignment per (axis,entity,node) |
| A7 | zone='bogus_zone' |
REJECTED (zone enum, 23514) | zone vocabulary closed |
This proves the candidate→approved promotion gate cannot be short-circuited: no provenance-less candidate, no double-approval on a single-axis entity, no island assignment, no out-of-vocabulary zone.
4.5 UI-visibility gate (R9)
The official-UI gate is axis_registry.lifecycle_status='active' AND axis_assignment.zone='approved':
axis_code | axis_life | entity_code | node_ref | zone | ui_visible
-----------+-----------+-------------+----------+------------+-----------
AX-TOPIC | active | IU-1 | TOPIC-A | candidate | f
AX-TOPIC | active | IU-Q | TOPIC-Q | quarantine | f
AX-TOPIC | active | IU-S | TOPIC-X | approved | t
Only the approved assignment under an active axis projects to the UI lane (ui_visible=t); candidate and quarantine are AI-visible but never official-UI-visible (hardening doc 10).
4.6 Axis verdict
Axis storage substrate (axis_registry + axis_assignment): REHEARSED-GREEN. Both compile; the canonical-key fix (H1) is honored; the provenance-or-quarantine guard, both partial-uniques, the axis FK, the zone vocabulary and the UI-visibility gate all behave as designed. Build remains NO-GO — axis tables are downstream of this package's acceptance and SB-0 (itself gated on the L2+L4 ratification). Entry==exit / zero-residue shared with doc 03 §3.7 (same transaction).
Forbidden-compliance: BEGIN..ROLLBACK; zero COMMIT; no taxonomy/entity_labels/taxonomy_facets row touched (axis seed rows were in the rehearsal-only tables, fully rolled back); no projection/UI/Qdrant write.
4.7 Cross-links
- compiles [[one-roof-axis-auth-proposal-operational-hardening-build-ready-design-2026-06-02]] doc 05.
- negatives consolidated in [[05-negative-forgery-and-fail-closed-tests]]; baseline in [[02-live-preflight-baseline]].