KB-95B7
03 — Data Contract (node / list object the API returns)
5 min read Revision 1
designregistries-pivotdata-contractnodelistpivotrender-shellos-agency2026-05-31
title: 03 — Data Contract (node / list object) date: 2026-05-31
03 — Data Contract
The contract is the JSON object the PG→Directus/API layer returns for any node or list. Nuxt renders it verbatim — no derivation, no math, no thresholds, no label/pin arrays (Đ28 NT-D1/NT-D3, Đ26 §0-BA/§0-AU). Every numeric field is a pivot_count/pivot_query value or the literal token PIVOT_MISSING.
A. Identity & counts (OS-Agency reflection core)
node_code— pivot code or filter-path identitylayer·composition_level·species·group/label_reftotal— pivot value orPIVOT_MISSINGplus/minus— period delta vsbaseline_count(pivot-backed; elsePIVOT_MISSING)orphan_count— frommeta_catalog.orphan_count/ orphan pivotphantom_count—GREATEST(record_count − actual_count, 0)(needsmeta_catalog.phantom_count; doc 05)verification_status— verified | unverified | failed (fromlast_scan_date+ invariant)drift_status— none | drift (storedrecord_count≠ live pivot /actual_count)count_integrity_status— ok | failed (doc 05)warning_flags[]— orphan | phantom | unmonitored | unregistered | ghost | pivot_missing | label_missing | driftnext_action— register | onboard | recount | propose_pivot | propose_label | investigate | nonesource_ref—source_object+ filter-path (provenance / Đ28 traceability / Đ31 contract)
B. Drill-down
has_children(true ifftotal > 1∧ a next layer resolves)children_countnext_layer_kind(species | composition_level | group | facet | collection | substrate)child_grouping_dimensionnext_pivot_code(or null → leaf)drilldown_query_ref(the pivot/query that expands this node)final_substrate_ref(set only at leaf: real rows / relationship edges / IU)group_size
C. Child-summary (per GPT addendum §C — shown on a parent before drilling)
child_countchild_species_countchild_collection_countchild_status_breakdown(e.g. {active, draft, deprecated, retired})child_orphan_countchild_phantom_countchild_drift_countchild_missing_birth_countchild_missing_pivot_countchild_missing_iu_countchild_missing_dot_counttop_child_groups(the largest groups, for triage)warning_flags(rolled up from children)next_recommended_actionEach of these is a pivot/aggregate over the child set, served from PG — never computed in Nuxt. Where a sub-metric has no pivot yet it isPIVOT_MISSING(e.g.child_missing_iu_countuntil an IU-coverage pivot exists).
D. Auto-label / grouping (doc 07; threshold addendum)
requires_auto_labelclassification_status(classified | inspectable | classification_required | LABEL_MISSING)classification_dimensionlabel_ref(→taxonomy.code/label_rules.id)grouping_requiredgrouping_reasonmax_ungrouped_threshold(per-species; default 50 = MAX ceiling, may be smaller; read from PG)suggested_next_groupingclassification_workflow_trigger
E. Pin / ghim (doc 08)
pin_state(pinned | unpinned | pinned-by-role | pinned-by-team) — fromregistry_pin, scoped to viewer
Contract invariants
- Any numeric field is a pivot result or literally
PIVOT_MISSING— never client arithmetic (Đ26, Đ28 Test-4). max_ungrouped_threshold, labels, layers, pins all come from PG (no Nuxt constants/arrays).has_children+ depth are backend-decided; Nuxt rendersnext_layer_kindwith no level logic.- A failed invariant is represented (warning_flags + count_integrity_status), never hidden (Đ28/Đ23/Đ31).
source_refalways present so any rendered cell is traceable to its PG origin (Đ31 contract / Đ28 Truth Check).
Serving path
pivot_* / views → meta_catalog & registry tables → Directus collection or /api/registries-pivot/* endpoint → Nuxt readItems → render via a registered Đ28 template. No direct PG-from-Nuxt; no business logic in the endpoint beyond shaping the contract from pivot outputs.