KB-61A2

07 — UI/API Topic-Axis Contract (Workstream E)

6 min read Revision 1
registries-pivotui-apitopic-axissurfacegraphapply-packet2026-06-03

07 — UI/API Topic-Axis Contract (Workstream E)

Goal: ensure the UI does not break when topics are graph-like (many parents), and define the exact backend fields. No UI patch is authored here — §10/§12: lock the contract first.

The core problem

The live v_registries_pivot_surface is tree-shaped: node_code, parent_code, is_root assume one parent. A topic axis is a DAG — a topic can have multiple parents and lateral broader/narrower edges. Rendering a DAG through a single-parent tree silently drops parents (a correctness bug) — exactly the "do not make UI assume a tree only" forbidden item.

Decision: a graph-aware companion surface, not a mutation of the tree surface

Add v_registries_pivot_axis_surface (new, additive) alongside the existing tree surface. The legacy registry surface keeps working unchanged; the axis surface carries the DAG. This mirrors the prior pattern (v_registries_pivot_surface was added as a companion to v_registries_pivot_node_contract).

Fields the backend must expose (per node, computed in PG — never Nuxt)

Field Source Why
axis_code axis_registry which axis this node belongs to
node_code taxonomy.code the topic node
label / name_en taxonomy.name display
canonical_parent_code taxonomy.parent_id the breadcrumb default
parent_codes[] universal_edges + parent_id ALL parents (DAG)
has_multiple_parents derived UI shows context chip when true
path / breadcrumb recursive over canonical parent navigation
relation_type universal_edges.kind broader/narrower/related
lifecycle_status taxonomy.status candidate/active/deprecated badges
governance_status governance_object_ownership join owned / owner_gap
count_value pivot result the measure (honest, may be 0)
count_status derived pivot_backed / PIVOT_MISSING (never silent 0)
child_count derived drives layer + grouping
child_layer_kind axis rule how children group
grouping_status rp_grouping_policy SATISFIED / NEEDS_GROUPING / NOT_REQUIRED
pin_state / pin_sort_rank registry_pin root priority/pinning
substrate_ref fn_topic_node_substrate the final drill target
warning_flags derived orphan/phantom/drift/owner_gap

The existing 34-col surface already provides ~20 of these (count_status, grouping_status, pin_, warning_flags, final_substrate_ref, child_). The net-new axis fields are: axis_code, parent_codes[], has_multiple_parents, path/breadcrumb, relation_type, lifecycle_status, governance_status.

UI behavior contract

  • Root topics = Layer 1 (axis root_rule).
  • Child topics = next layers (dynamic depth; no hardcoded 3 levels).
  • Multiple-parent topic = render once with a breadcrumb/context chip; do not duplicate or pick a parent arbitrarily; has_multiple_parents=true drives the chip.
  • Topic substrate page = drill terminal renders fn_topic_node_substrate (documents/IU/workflows/DOTs/events/governance/birth/lifecycle).
  • Badges: candidate/warning (lifecycle_status, warning_flags), pin/root priority (pin_*), grouping when children > threshold (grouping_status).
  • Forbidden in UI: tree-only assumption; hardcoded 3 levels; computing counts/depth/grouping in Nuxt.

API surface

Extend the existing API family (no breaking change):

  • /api/registries-pivot/axes → list registered axes from axis_registry.
  • /api/registries-pivot/axis/{axis_code}/rows → nodes from v_registries_pivot_axis_surface.
  • /api/registries-pivot/axis-node/{node_code}fn_topic_node_substrate. Reuses the live pattern (counts in PG, Nuxt renders contract only).

Apply-packet (authored, NOT applied — keep prod minimal)

The companion view + resolver are specified as a paste-ready apply packet held for operator/owner, not executed this session (Live mutation = NO):

  1. axis_registry + axis_assignment DDL (additive, born, reversible) — owner-gated.
  2. v_registries_pivot_axis_surface (DROP-reversible read view over taxonomy facet 8 + universal_edges + governance_object_ownership + pivot results).
  3. fn_topic_node_substrate(topic_code) (STABLE, read-only).
  4. Pivot rows PIV-310, PIV-320..332 (additive pivot_definitions inserts). Why not apply now: FAC-08 is empty and axis_registry law is unratified; projecting an empty axis would add prod objects with nothing to render and pre-empt owner law. The packet is the deliverable; enactment is doc 09's next macro.

UI/API impact summary (answer to macro Q8)

The current UI/API does not break if the tree surface is left intact and the axis DAG is served by a separate companion surface + axis API. The required additions are 7 net-new fields, one companion view, one resolver function, one axes endpoint — all additive. No tree-shaped assumption may leak into topic rendering.

Workstream E completion: UI/API topic-axis contract is explicit; surface extension is specified as an unapplied apply-packet.

Back to Knowledge Hub knowledge/dev/reports/architecture/information-piece-topic-axis-registries-pivot-design-2026-06-03/07-ui-api-topic-axis-contract.md