Layer Vocabulary
Layer Vocabulary
Section titled “Layer Vocabulary”Definition
Section titled “Definition”Audience-and-depth classification, standing on its own layer_vocabulary DB table (admin_ui CRUD) rather than as a column on a content-record table. Captures who the content is for and at what level of detail — sales_brief for benefit-led internal-sales positioning, bid_detail for tender-response factual content, company_reference for product-agnostic corporate documents, and research for background material that feeds guides.
Ownership: the Guides application type (RESOLVED — owner round-4, D5; ID-133 BI-4). layer is the Guides audience/depth axis, matched against guide_sections.expected_layer — see Relationships. This CV predates ID-131 and originally also joined via content_items.layer, dropped with that table at ID-131 M6 (S450 GO); no source_documents.layer or q_a_pairs.layer column exists or is planned (the cocoindex SD/QA pipeline never wrote content_items.layer, flow.py:2515), so layer is retired from the SD/QA homes rather than re-homed onto them. The CV is KEPT, not deprecated — the Guides relationship was already live before this reframe; only the framing of primary ownership changes here.
Layer is orthogonal to domain/subtopic and to the per-item depth axis (Summary / In Depth / Takeaways / Original Text — see the “Four orthogonal axes” Notes bullet); it answers “who reads this?” rather than “how deep does this go?”. Ships as 4 baseline core rows; clients may extend via the admin UI (/settings → Layers section).
Synonyms / Acronyms
Section titled “Synonyms / Acronyms”None formalised at present.
Baseline values
Section titled “Baseline values”| key | label | provenance |
|---|---|---|
| sales_brief | Sales Brief | core |
| bid_detail | Bid Detail | core |
| company_reference | Company Reference | core |
| research | Research | core |
(Verified 14/05/2026 against layer_vocabulary rows on the live DB — all four rows are is_active=true with display_order 10/20/30/40.)
Relationships
Section titled “Relationships”guide_sections.expected_layer— the CV’s live home (Guides application type, RESOLVED D5). Free-text column matched at query time against a record’s classified layer value; the Guides audience/depth filter on a guide section. No FK/CHECK binds it tolayer_vocabulary.keydirectly (supabase/migrations/20260617130000_squash_baseline.sql:6748) — matching happens in theget_guide_content/get_guide_coverageSQL RPCs and inlib/guide-section-mapping.ts’s reverse (item→section) match, not via a schema constraint. See the Notes bullet below on the RPCs’ current unrepaired state.layer_vocabulary— DB table (columnsid,key,label,description,display_order,is_active), independent of any content-record table.reference_items.layer— text column, live, validated againstlayer_vocabulary.keyby the sharedvalidate_layer_key()trigger function (trg_validate_reference_items_layer) — the same function also fired (astrg_validate_layer_key) oncontent_items.layeruntil that table was dropped at ID-131 M6 (supabase/migrations/20260706110000_id131_drops.sql:121-128,318). Rendered oncomponents/reference/reference-card.tsxandapp/reference/[id]/reference-detail-client.tsx.content_items.layer— GONE (pre-ID-131). Was a text column referencinglayer_vocabulary.key, carried thetrg_validate_layer_keytrigger; DROPPED withcontent_itemsat ID-131 M6 (S450 GO,supabase/migrations/20260706110000_id131_drops.sql:310). Retired from the SD/QA homes entirely (RESOLVED — owner round-4, D5): nosource_documents.layerorq_a_pairs.layercolumn exists or is planned (the cocoindex SD/QA pipeline never wrotecontent_items.layer,flow.py:2515).contexts/layer-vocabulary-context.tsx— React context that caches the vocabulary for app-side reads (withFALLBACK_LAYERSfromlib/client-config.tsif the DB fetch fails).
Consumers
Section titled “Consumers”Guides application type (live):
contexts/layer-vocabulary-context.tsx— React context that caches the vocabulary for app-side reads.components/guide/guide-section.tsx—expected_layerrendering hint on a guide section.components/guide/guide-section-banner.tsx— surfacessuggestGuideSections()(lib/guide-section-mapping.ts) match results to editors.components/settings/layers-section.tsx,section-form-dialog.tsx— admin CRUD surface (thelayer_vocabularytable itself, and a guide section’sexpected_layerfilter).lib/layer-inference.ts—inferLayer(), called fromlib/guide-section-mapping.tsandlib/queue/handlers/batch-reclassify.ts.lib/validation/layer-schemas.ts— DB-driven validation;app/api/layers/*— admin CRUD endpoints.
reference_items.layer (live, separate consumer — see Relationships):
components/reference/reference-card.tsx,app/reference/[id]/reference-detail-client.tsx— display badge.components/create-content/ingestion-success-card.tsx— layer-suggestion<Select>on the reference-ingestion success flow (useLayerVocabulary()); its PATCH target/api/items/${itemId}/metadatadoes not currently resolve to any route underapp/api/items/— flagged, not fixed, by this Subtask (see the {133.14} out-of-scope routing).components/content/layer-suggestion-banner.tsx— the Accept/Change layer-suggestion banner (rendered fromcomponents/guide/guide-section-banner.tsx).
Retired with content_items (pre-ID-131, dropped at ID-131 M6 — no longer live):
components/browse/filter-panel.tsx— the browse-filter chip; dropped.components/browse/coverage-layer-filter.tsxsurvives on disk but is unreferenced by any caller today (orphaned, not wired to any route/component) — not removed by this Subtask.components/content/content-card.tsx,content-row.tsx— display badges; both dropped.components/item-detail/layer-switcher-nav.tsx— sibling-at-other-layer navigation; dropped.components/content/content-layer-selector.tsx— dropped.components/create-content/upload-tab-content.tsx(relocated fromcomponents/content/upload-tab-content.tsx) survives but no longer referenceslayerat all.
get_guide_content/get_guide_coverage— the SQL RPCs behind the Guides live-home relationship above — stillLEFT JOIN content_items, unrepaired after that table’s drop at ID-131 M6 (supabase/migrations/20260617130000_squash_baseline.sql:3094-3176; the M6 migration20260706110000_id131_drops.sqlhandles every othercontent_itemsdependent — six api views, citations/feed_articles columns, four child tables, retiring functions — but does not mention “guide” anywhere). Postgres does not track a hard dependency forLANGUAGE sql/plpgsqlfunction bodies on tables referenced in the body, soDROP TABLE content_itemssucceeded without touching these two functions — they are now expected to error at call time.app/api/guides/[slug]/route.ts:64still callsget_guide_content. Flagged for the owner/ID-131-successor by this Subtask, not fixed (docs-only worktree) — routed as an out-of-scope finding in the {133.14} journal.- Live shape verified 14/05/2026: the 4 keys above are the live
layer_vocabularyrows on staging/prod; the earlier “regulatory / customer / internal” model was never live (it appeared as a stale example in source §2.1 and was inadvertently transcribed by the Drafter wave). The audience-and-depth model superseded it before this register was authored. - Editable via admin UI today. Layers are administered through
app/api/layers/*andcomponents/settings/layers-section.tsxperdocs/specs/p1-36-db-driven-layer-validation-spec.md.editable_via: admin_uireflects current behaviour; the SQL seed atcore_seed_pathis intended to formalise the baseline rows for multi-tenant onboarding (file does not yet exist — Phase 1 build creates it). - Provenance column ALTER (Ratified-S237): the live
layer_vocabularytable has noprovenancecolumn today. Liam ratified S237 that theALTER TABLE … ADD COLUMN provenance textmigration lands in the Q-OQR1-16 combined PR — alongside theentity_aliasescategory→provenancerename, the application_types introduce, kb_section retire, procurement rename,project_id → workspace_id,digests → change_reports, form_templates rename, and seed-file emission for CV 01/02. v1.1 admin UI per Q-OQR1-13 can safely tag client-extended rows once the column lands. - UI nesting spec (Deferred-S238+): Liam’s gap-analysis ruling (
docs/client-documentation/kb-hub-gap-analysis-action-tracker.md§B.1) makes layer a UI nesting rule with Sales Brief at the top and Bid Detail nested beneath. The supporting specdocs/specs/p0-layer-nesting-spec.mdis not yet authored — Liam ratified S237 that authorship is deferred to S238+ when the UI nesting implementation work begins. The CV does not gate that spec; the renderer composeslayer+guide_sections.parent_section_idto produce the nested view at runtime, independent of the spec. v1 spec and implementation confirmed in scope per Liam direction; this CV provides the data-side contract. - Four orthogonal axes (architectural pattern, INV-1 §6.2): layer is the audience axis; the per-item
Summary/In Depth/Takeaways/Original Texttabs were the depth axis (typed columnsbrief/detail/reference/summary_dataoncontent_items, pre-ID-131 — dropped with the table at ID-131 M6, nosource_documentsequivalent exists);q_a_pairs+scope_tagoverlap is the application-surfacing axis (per Q-OQR1-06); and the OKF storage-layer axis (l_raw/l_records/l_concepts) is a separate CV,36-three-layer-model.md. Do NOT collapse these into one column — and in particular do NOT conflate THISlayer_vocabularyaudience axis with thethree_layer_modelstorage axis, despite both being called “layer”. core_seed_pathpoints to a SQL seed file that does not yet exist; create as part of Phase 1 build perphase-b-prerequisite-1-onthology-pipeline.md§6.- Inference rule logic (
lib/layer-inference.ts) hard-codes the 4 keys for its 7 rule branches perdocs/specs/p1-36-db-driven-layer-validation-spec.md§Non-goals; admin add/remove is decoupled from inference.