10 — UI Projection Contracts (view-level, build-ready for later UI/API)
10 — UI Projection Contracts (view-level, build-ready for later UI/API)
Package:
one-roof-axis-auth-proposal-operational-hardening-build-ready-design-2026-06-02Mode: DESIGN ONLY · READ-ONLY · NO COMMIT · NO MUTATION · no UI implementation Hardens: prior…-2026-06-01/10-ui-projection-tree-graph-and-human-reading.md. Closes GPT review gap #6: "UI projections need exact view contracts for tree/graph/topic/detail/reconstruction readers."
10.0 Principle
UI reads named projection views only; it is never a source of truth. Assembly flow is PG → Directus → Nuxt (no direct PG from Nuxt; constitutional guardrail). Every UI surface reads the view named in axis_registry.projection_view. Writes from the UI route the approval ladder (docs 02/06) — the UI cannot promote anything.
10.1 The projection view contracts
Each contract: view name · source tables · official-lane filter · columns exposed · badges. Live precedent views to reuse/extend: v_ui_iu_three_axis_envelope, v_iu_three_axis_envelope_refresh_status, v_iu_three_axis_envelope_drift, v_kg_edges_all, v_pivot_dot_by_category.
| Surface | View (proposed) | Source | Official-lane filter | Columns | Badges |
|---|---|---|---|---|---|
| Official axis tree | v_ui_axis_tree |
iu_tree_path + taxonomy(active) |
status='active' only |
node, parent, depth, path_addresses, sibling_order | lifecycle |
| Graph browser | v_kg_edges_all (live) / v_ui_axis_graph |
universal_edges/iu_relation |
status='active' + provenance present |
source/target code+collection, edge_type, weight, confidence | confidence, provenance |
| Topic detail | v_ui_topic_detail |
taxonomy(FAC-08 active) + axis_assignment(zone='approved') |
active + approved | topic, definition, owner, member count | lifecycle, owner |
| Topic IU list | v_ui_topic_iu_list |
axis_assignment(zone='approved') + entity_labels + information_unit |
zone='approved' |
IU code, title, match_score, confidence | confidence vs match_score (distinct), evidence |
| Reconstruction reader | v_ui_reconstruction_reader |
fn_iu_reconstruct_source + fingerprint |
integrity PASS to mark "official" | ordered IU sequence, source_position, content | integrity (pass/fail), fingerprint |
| Containment tree | v_ui_containment_tree |
iu_tree_path + iu_relation(contains) |
primary spine | node, parents (multi), depth, primary flag | multi-parent, cycle-warning |
| Axis browser | v_ui_axis_registry |
axis_registry(active) |
lifecycle_status='active' |
axis, family, kind, owner, projection_view | lifecycle, kind |
| Candidate lane (all axes) | v_ui_candidate_lane |
axis_assignment(zone IN candidate,quarantine) + taxonomy(status IN candidate,provisional) |
NOT official | object, zone, confidence, provenance, reviewer | CANDIDATE / QUARANTINE (loud) |
10.2 Candidate vs official visibility (the critical rule)
- Official lane =
active/born nodes +zone='approved'assignments + integrity-PASS reconstructions only. This is what a normal reader sees. - Candidate lane = clearly-marked, separate surface (
v_ui_candidate_lane); AI/reviewer-facing; excluded from the official tree. - Never present a candidate/provisional/quarantine object as official. Never let the UI promote — a "promote" button issues an
approval_requestsproposal and routes the ladder; it does not write truth.
10.3 Badges (exact, for later UI/API)
| Badge | Source | Meaning |
|---|---|---|
| lifecycle | taxonomy.status / axis_registry.lifecycle_status |
birth/register/active/deprecate/retire |
| zone | axis_assignment.zone |
approved / candidate / quarantine |
| confidence | axis_assignment.confidence |
calibrated trust — shown distinctly from match_score |
| match_score | axis_assignment.match_score |
raw similarity (never collapsed into confidence/zone — doc 05 §5.7) |
| evidence / provenance | axis_assignment.evidence/provenance |
expandable panel; missing provenance ⇒ quarantine badge |
| integrity | reconstruction fingerprint / containment checks | pass/fail (non-exemptable) |
10.4 Why the UI is never the source of truth
- Truth is PG (
taxonomy,axis_registry,axis_assignment, IUs,birth_registry). Views are read-only projections. - A UI edit becomes a proposal (
approval_requests/unit_edit_draft/axis_assignment(candidate)), reviewed and L3-applied (docs 06/11). The UI has no path to setzone='approved', set a grantactive, or writeentity_labelsdirectly. - A view exposing a non-
active/non-approvedobject in the official lane is itself a governance issue (ui_visible_unapproved, doc 09 §9.3 D4) — the projection contract is enforced by coverage.
10.5 Reuse & extension
- Reuse the live
v_ui_*/v_kg_edges_all/v_pivot_*views. - Each axis declares its
projection_viewinaxis_registry(doc 05). New axis ⇒ new view name in the row + the view; no UI code change to discover axes (the axis browser enumeratesaxis_registry). - The
iu_three_axis_envelopebecomes a projection overaxis_registry(SB-3 generalization, doc 04 §4.8); existing envelope views are rebuilt on top, non-breaking.
10.6 API / contract notes (no implementation)
- Directus exposes the
v_ui_*views (read); Nuxt reads Directus (no direct PG). - Refresh: after SB-11, projection refresh is signal-driven (Điều 45
governanceevent); until then, synchronous + manual (doc 16). - Draft/provisional nodes are not indexed into production Qdrant (content-policy; doc 16).
Open decisions & forbidden-compliance: O-UI-1 exact view DDL + Directus exposure config (next phase). Design-only; no view created; no UI built; read-only.