@sdd-method/verify-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +17 -0
  3. package/README.md +7 -0
  4. package/dist/lib/catalogue/baseline-check.js +136 -0
  5. package/dist/lib/catalogue/canonical-schema.yaml +3557 -0
  6. package/dist/lib/catalogue/cli-version.js +10 -0
  7. package/dist/lib/catalogue/coverage-predicates.js +603 -0
  8. package/dist/lib/catalogue/coverage-render.js +522 -0
  9. package/dist/lib/catalogue/coverage-run.js +115 -0
  10. package/dist/lib/catalogue/csv-reader.js +97 -0
  11. package/dist/lib/catalogue/csv-writer.js +96 -0
  12. package/dist/lib/catalogue/ddl-generator.js +233 -0
  13. package/dist/lib/catalogue/engine-validator.js +222 -0
  14. package/dist/lib/catalogue/finding-identity.js +183 -0
  15. package/dist/lib/catalogue/findings.js +46 -0
  16. package/dist/lib/catalogue/fk-validator.js +136 -0
  17. package/dist/lib/catalogue/gate-checks.js +338 -0
  18. package/dist/lib/catalogue/graph-projection.js +329 -0
  19. package/dist/lib/catalogue/impact-run.js +228 -0
  20. package/dist/lib/catalogue/manifest-loader.js +422 -0
  21. package/dist/lib/catalogue/relationship-semantics.js +66 -0
  22. package/dist/lib/catalogue/rubric-coverage-map.yaml +764 -0
  23. package/dist/lib/catalogue/scaffold-delta.js +261 -0
  24. package/dist/lib/catalogue/schema-compat.js +52 -0
  25. package/dist/lib/catalogue/schema-loader.js +87 -0
  26. package/dist/lib/catalogue/scores-coverage.js +535 -0
  27. package/dist/lib/catalogue/staleness-verdicts.js +345 -0
  28. package/dist/lib/catalogue/validate.js +176 -0
  29. package/dist/lib/catalogue/version.js +18 -0
  30. package/dist/lib/list/discover.js +100 -0
  31. package/dist/lib/list/format.js +84 -0
  32. package/dist/lib/list/index.js +16 -0
  33. package/dist/lib/lock-file.js +413 -0
  34. package/dist/lib/pack/log.js +18 -0
  35. package/dist/lib/pack/schema.js +121 -0
  36. package/dist/lib/pack/seed.js +182 -0
  37. package/dist/lib/pack/validate.js +49 -0
  38. package/dist/lib/package-version.js +25 -0
  39. package/dist/lib/repo-kind.js +129 -0
  40. package/dist/lib/scripts.js +7 -0
  41. package/dist/lib/validate/aggregate.js +35 -0
  42. package/dist/lib/validate/bundle-coherence.js +69 -0
  43. package/dist/lib/validate/dispatch.js +218 -0
  44. package/dist/lib/validate/index.js +88 -0
  45. package/dist/lib/validate/runner.js +85 -0
  46. package/dist/verbs/catalogue-verify.js +114 -0
  47. package/dist/verbs/list.js +45 -0
  48. package/dist/verbs/pack-validate.js +17 -0
  49. package/dist/verbs/path-option.js +25 -0
  50. package/dist/verbs/validate.js +22 -0
  51. package/dist/verify-bin.js +8 -0
  52. package/dist/verify-program.js +115 -0
  53. package/package.json +32 -0
@@ -0,0 +1,3557 @@
1
+ # GENERATED — DO NOT EDIT. This file is a projection of the authored model (M-ADR 0210 §4.6, flip 1):
2
+ # docs/method/foundations/schemas/catalogue-schema.tql (the type system; header carries the bump log)
3
+ # docs/method/foundations/schemas/catalogue-schema-meta.tql (what a type system cannot say)
4
+ # Regenerate: sdd-cli metamodel roundtrip --write
5
+ # Guard: sdd-cli metamodel roundtrip (any difference fails the build)
6
+ # Direction of truth: authored .tql -> this projection (round-trip gate) -> vendored copies (digest hook).
7
+ # Emitted by sdd-cli's YAML emitter with no line folding; the three header scalars are quoted for the
8
+ # textual readers downstream. The one deliberate difference from the authored form is schema_status:
9
+ # the authored form says canonical; a projection never does.
10
+ schema_version: "3.13.0"
11
+ schema_owner: "sdd-method"
12
+ schema_status: "generated"
13
+ enums:
14
+ quality_gate:
15
+ values:
16
+ - value: pass
17
+ description: Meets the rubric's pass threshold with no hard gate triggered.
18
+ - value: pass-with-waiver
19
+ description: A pass granted despite a known dimension shortfall, with the waiver RECORDED (granted_by + expires; see the scoring-registry guide). Passing for gate purposes, flagged for review purposes; an expired waiver reads as conditional. Adopted 2026-08-07, generalising the domain-architecture rubric's waiver machinery.
20
+ - value: conditional
21
+ description: Below threshold or carrying flags — remediation required, not a failure.
22
+ - value: fail
23
+ description: Below the fail threshold, or a hard gate triggered.
24
+ - value: unscored
25
+ description: "The entry exists but carries no assessment. Distinct from absent: an unscored row asserts that nothing has been judged, which is exactly the silence M-ADR 0205 §4.5's coverage instrument exists to make loud."
26
+ description: |
27
+ Gate verdict a rubric assessment records for a target, in `quality_scores.gate` (per M-ADR 0205 §4.5). The vocabulary all fifteen method-side gate registries declare.
28
+ DELIBERATELY NOT BOUND via `column_enums`, and the reason is measured rather than assumed — do not "fix" this by binding it. These values come from hand-authored score registries written by scoring runs, not from a method-mandated authoring surface, and one estate's `domain-architecture-scores.yaml` declared `pass-with-waiver` before the method did, and uses it — the extension was RULED INTO this vocabulary (2026-08-07); the next estate extension would meet the same choice, and binding would hard-fail a build over a deliberate, self-documented row. This follows the `products.synthesis_band` precedent — the other column fed from a rubric registry — where an out-of-vocabulary value is reported as a convention finding and the cell left EMPTY, rather than emitting a value no consumer can interpret. The builder names the file, the entry, the value and the remedy, which is better diagnosis than a generic enum violation could give. Contrast `service_type`, which IS bound: it comes from repo-config, an authoring surface the method mandates.
29
+ score_selection_method:
30
+ values:
31
+ - value: latest
32
+ description: Most recent review by scored_at. The default and, at 2026-08-06, the only value in use across either estate.
33
+ - value: human-selected
34
+ description: A human chose the effective review over the automatic pick.
35
+ - value: consensus
36
+ description: Effective score reconciled across several reviews.
37
+ - value: highest-severity
38
+ description: The most severe review wins — the conservative policy for gate-blocking rubrics.
39
+ description: |
40
+ How the effective review was chosen from a target's review history, in `quality_scores.selection_method` — the `selection_policy.method` field every gate registry carries. The catalogue models only the EFFECTIVE score (one row per target/rubric); this column makes the row say WHICH review it is rather than implying there was only one. Not bound, for the same registry-authored reason as `quality_gate`.
41
+ staleness_basis:
42
+ values:
43
+ - value: corpus_ref
44
+ description: The row carries the commit the assessment read — the precise anchor. Authored; introduced by the M-ADR 0205 §4.5 change-set, so absent from every score written before it.
45
+ - value: scored_at
46
+ description: No corpus_ref; staleness computed from the assessment date against the target's last content change, resolved through target_path. Correct but coarser — it cannot distinguish a re-commit that changed nothing from a real edit.
47
+ - value: none
48
+ description: Neither anchor available (no corpus_ref and no resolvable target_path). Staleness is UNKNOWN for this row and must be reported as unknown, never as fresh.
49
+ description: |
50
+ Which anchor a `quality_scores` row's staleness verdict can be computed from, in `quality_scores.staleness_basis`. This column exists because a staleness verdict whose basis is unstated is not a measurement — the basis-error class that produced six wrong figures in a single day of this method's own arc. The coverage predicate MUST NOT be able to emit a staleness claim without naming which of these it used.
51
+ scoring_form:
52
+ values:
53
+ - value: weighted
54
+ description: Weighted 1-5 dimensions rolled into a weighted_score against a pass threshold, with flags and hard gates. The forward house form; all fifteen method-side registries use it.
55
+ - value: banded
56
+ description: Dimensions summed to an integer total and mapped to a named band. The reverse family's form. Added in 3.3.0. The band vocabulary is PER-RUBRIC and deliberately unbound — see the band column.
57
+ description: |
58
+ The scoring shape a rubric uses, in `quality_scores.scoring_form`. Reserved by M-ADR 0205 §4.5 so the banded reverse family can arrive additively without reshaping rows.
59
+ Both forms are now declared. `banded` was added in 3.3.0 once the reverse family was modelled; before that it was deliberately absent so a premature banded row would fail loudly rather than pass against an unemitted value.
60
+ The two forms are NOT interchangeable and must not be averaged together — which is why they never share a score column. A weighted row carries `weighted_score` (1-5) and leaves `band`/`band_total` empty; a banded row carries `band` + `band_total` and leaves `weighted_score` empty. Any aggregate over `weighted_score` is therefore correct by construction rather than by the caller remembering to filter.
61
+ capability_service_role:
62
+ values:
63
+ - value: primary
64
+ description: Realises this capability.
65
+ - value: related
66
+ description: Participates in delivering this capability without being its primary realiser. Contributes; kept in repo_capability.
67
+ - value: dependency
68
+ description: This capability DEPENDS ON the service — the inverse direction of contribution. The relationship is real and catalogued here; it does NOT produce a repo_capability row.
69
+ - value: backend-gateway
70
+ description: Owned by ANOTHER domain and the sanctioned entry point into that domain's data for this capability — not merely a dependency, the door in. Expect it on cross-domain rows only. Contributes; kept in repo_capability.
71
+ description: |
72
+ The part a service plays in delivering ONE capability. A property of the capability↔service RELATIONSHIP, never of the service: the same service is legitimately `primary` for capabilities in its own domain and `backend-gateway` for capabilities elsewhere. Authored in the capability traceability manifest services[].role (see the capability-traceability-manifest-template). Bound in 3.8.0; the values and their meanings are the template's, unchanged. Consumers deriving "which repos realise this capability" MUST read this column or use repo_capability, which excludes `dependency` (M-ADR 0157 §4.3 as amended) — a repo_capability row is a contribution claim.
73
+ c4_system_kind:
74
+ values:
75
+ - value: platform
76
+ description: A platform-root system — the one system that identifies a platform (M-ADR 0208 §4.1; 'platform-ecosystem' is the long form, 1:1 with the root). Exactly one per PLATFORM; an organisation-tier aggregate legitimately carries one per constituent platform, keyed by platform_sdd_id (0208 §4.2). An invariant `subsystem` exists to protect — do not reuse `platform` for subsystem rows.
77
+ - value: subsystem
78
+ description: A promoted platform subsystem (M-ADR 0170 §4.2) — a separate deployable that is a peer System in the platform model, contained by the platform root on the same footing as application and integration (M-ADR 0208 §4.1). Added 2.28.0 per M-ADR 0133 §4.2c.
79
+ - value: application
80
+ description: An application-product system, consumes platform services and contracts.
81
+ - value: integration
82
+ description: An integration-provider system, bridges an external provider into the platform.
83
+ description: |
84
+ Architectural kind of a C4 system. Derived 1:1 from the originating SDD manifest's category — every architectural product (the only ones that get a c4_systems row) maps to exactly one of these four kinds. Non-architectural categories (integration-umbrella, support-repo) emit no c4_systems row — and the builder MUST say so with a coverage finding, never silently (M-ADR 0133 §4.2c). Mapping table:
85
+ platform-root → platform
86
+ platform-subsystem → subsystem
87
+ application-product → application
88
+ integration-provider → integration
89
+ c4_container_type:
90
+ values:
91
+ - value: Application
92
+ description: A separately deployable/runnable application — a service, BFF, UI, consumer, worker, etc.
93
+ - value: Data Store
94
+ description: A database or persistence layer (also covers running stores like a message broker when modelled as a container).
95
+ description: |
96
+ Canonical C4 container kind for `c4_containers.type`, aligned with c4model.com/abstractions (per M-ADR 0155). A C4 container is something that must be running for the system to work — an application or a data store.
97
+ BOUND via `c4_containers.column_enums` since 3.0.0 (M-ADR 0203 §4.1, completing 0155's staged enforcement): a non-member value hard-fails build and validate. The 2.x-era legacy values are removed; their migration rule (0155's own): `External System` boxes belong in `c4_external_systems` (C4 L1 peer systems, not L2 containers); running infrastructure (broker, gateway, cache) retypes to Application or Data Store; pure deployment infrastructure (load balancer, DNS) leaves the container catalogue (it belongs in a C4 deployment diagram, which is not catalogued).
98
+ service_type:
99
+ values:
100
+ - value: api_service
101
+ description: REST/GraphQL/RPC service exposing an API.
102
+ runtime: true
103
+ emits_service_row: true
104
+ - value: worker
105
+ description: Background event/queue processor.
106
+ runtime: true
107
+ emits_service_row: true
108
+ - value: gateway
109
+ description: Edge or API gateway (Zuplo, Apigee, etc.).
110
+ runtime: true
111
+ emits_service_row: true
112
+ - value: frontend
113
+ description: Web UI deployable (Vue, React, Svelte, etc.). Includes vertical-domain application frontends — the SDD profile distinguishes platform-frontends from app-frontends.
114
+ runtime: true
115
+ emits_service_row: true
116
+ - value: mobile
117
+ description: Mobile app deployable (iOS, Android).
118
+ runtime: true
119
+ emits_service_row: true
120
+ - value: library
121
+ description: Shared package shipped to consumers (npm, PyPI, Maven, etc.).
122
+ runtime: false
123
+ emits_service_row: false
124
+ - value: infrastructure
125
+ description: IaC, CI/CD, build tooling — not a runtime deployable.
126
+ runtime: false
127
+ emits_service_row: false
128
+ - value: documentation
129
+ description: Docs-only repo.
130
+ runtime: false
131
+ emits_service_row: false
132
+ description: |
133
+ Type of repository, declared in `orchestration/repo-config/*.yaml` as `service_type` and surfaced in `repositories.component_type` and `services.component_type`. The canonical builder uses this to decide which repos are runtime services (api_service, worker, gateway, frontend, mobile) and which are non-runtime (library, infrastructure, documentation). Whether a repo is a vertical-domain application is conveyed by its SDD manifest's `profile: application-product`, not by a service_type tag — this enum is strictly about runtime artefact shape (per resolution of adopt-canonical-catalogue-builder.md §7.1).
134
+ capability_exemption_reason:
135
+ values:
136
+ - value: infrastructure
137
+ description: Provisions or operates the estate; realises no product capability.
138
+ - value: build-tooling
139
+ description: Build, release, CI or repository-management machinery.
140
+ - value: test-scaffolding
141
+ description: Test helpers and fixtures with no runtime role.
142
+ - value: vendored
143
+ description: Third-party or forked code the SDD does not model.
144
+ - value: prototype
145
+ description: Exploratory; not part of the product model.
146
+ - value: archived
147
+ description: Retained for reference; no longer live.
148
+ description: |
149
+ Why a catalogued repository deliberately bears no capability, per M-ADR 0188 §4.2. Closed vocabulary: reason codes make exemptions countable and trendable (a growing `prototype` or `archived` population is itself an estate signal), where free text would bury them. Extensions are method-owned and proceed by ADR amendment, so that adopters cannot locally widen the exemption surface to silence findings.
150
+ ENFORCED, not advisory. The builder drops a `repo_capability_exemption` row whose reason is outside this vocabulary and emits a `convention` finding. The repository then resolves to nothing and is reported as an orphan — which is the point. If an unrecognised reason still exempted the repo, `reason: whatever` would be a universal silencer.
151
+ service_capability_exemption_reason:
152
+ values:
153
+ - value: platform-internal
154
+ description: Runs, but serves the platform's own operation rather than a product capability (e.g. an internal control-plane or ops service).
155
+ - value: deprecated
156
+ description: No longer live; retained for reference or wind-down.
157
+ description: |
158
+ Why a catalogued service deliberately bears no capability, per M-ADR 0133 §4.2b. Closed vocabulary — narrower than `capability_exemption_reason` by design: a repository can be exempt for six reasons (packaging, tooling, provenance), but a SERVICE, by definition, already runs something — the repository-tier distinctions that don't reproduce at the service tier (pure IaC, build tooling, test scaffolding, vendored code) fold into `platform-internal`, since a service that exists at all is doing platform-internal work if it isn't product-facing.
159
+ ENFORCED, not advisory. The builder drops a `service_capability_exemption` row whose reason is outside this vocabulary and emits a `convention` finding. The service then resolves to nothing and is reported per the coverage predicate's tier-scoped verdict set — which is the point.
160
+ external_system_exemption_reason:
161
+ values:
162
+ - value: third-party-saas
163
+ description: An operated vendor service the estate consumes (billing, auth, maps, email…).
164
+ - value: partner-system
165
+ description: Another organisation's system integrated across an agreed boundary.
166
+ - value: customer-system
167
+ description: A customer-owned system the estate serves or consumes.
168
+ - value: device-hardware
169
+ description: Physical devices or device fleets at the estate boundary.
170
+ - value: public-infrastructure
171
+ description: Public networks, registries, or services no party in the estate operates.
172
+ - value: estate-owned-unmodelled
173
+ description: "Operated by this estate but with no SDD or container home yet — the row is an accounted-for stand-in, and this population is the estate's modelling backlog, countable (F16, 2.32.0). Not an assertion of externality: an assertion of accountability for a boundary row."
174
+ - value: organisation-internal
175
+ description: Owned elsewhere in the same organisation, outside this estate's modelling boundary (F16, 2.32.0).
176
+ description: |
177
+ Why an external-system candidate is ACCOUNTED FOR at the estate boundary, per M-ADR 0189 §4.6 (WS15; wording corrected by F16, 2.32.0): five values assert another party owns the system, and two assert the estate/organisation owns it but it has no model home yet — forcing the latter through the former would demand a false reason, and a false reason is worse than silence. The adjudicator can prove a candidate internal; it cannot prove one accounted-for — that is an assertion the author is accountable for, in the shape M-ADR 0188 ratified for repositories. Closed vocabulary, method-owned, extended only by ADR amendment, so adopters cannot locally widen the exemption surface to silence the unverified-candidate coverage finding.
178
+ ENFORCED, not advisory: the builder drops a row whose reason is outside this vocabulary (convention finding) and the candidate stays unverified — which is the point. An unrecognised reason must not succeed at the one thing an exemption does.
179
+ scaffold_status:
180
+ values:
181
+ - value: open
182
+ description: The unit of work is in flight. `declared` items are a state, not a defect (M-ADR 0207 §4.2).
183
+ - value: closed
184
+ description: The author has recorded the unit of work as done. A `declared` item under a closed scaffold presumes the scaffold right — the work is incomplete — and is reported (M-ADR 0207 §4.3).
185
+ description: |
186
+ Lifecycle of a scaffold declaration, in `scaffolds.status`. AUTHORED in the manifest, copied by the builder: closing a scaffold is a recorded act of the unit of work finishing (M-ADR 0207 §4.3), not a computed consequence — the delta instrument reports a closed scaffold whose delta is not zero as a finding, it never closes one itself.
187
+ scaffold_item_kind:
188
+ values:
189
+ - value: entity
190
+ description: A node catalogue row the work will add (a service, capability, feature, screen, …). target_ref is the declared id in that catalogue's vocabulary.
191
+ - value: edge
192
+ description: An edge catalogue row the work will add. Endpoints are declared in edge_source_ref/edge_target_ref, mapped to the edge catalogue's FK columns in schema declaration order.
193
+ - value: contract
194
+ description: A contract artefact the work will introduce or amend. target_ref is the repo-relative spec path, matching `contracts.spec_path`.
195
+ description: |
196
+ The grain of a scaffold declaration item, in `scaffold_items.item_kind`. Declares which family of catalogue surface the item promises; `target_kind` names the specific catalogue.
197
+ scaffold_item_state:
198
+ values:
199
+ - value: declared
200
+ description: The target does not (yet) resolve in the built catalogues. Under an open scaffold this is the computable backlog; under a closed one it is a reported finding (M-ADR 0207 §4.2/§4.3).
201
+ - value: realised
202
+ description: The target resolves in the built catalogues. The declaration is met for this item.
203
+ description: |
204
+ Realisation state of a scaffold item, in `scaffold_items.state`. DERIVED by the builder's resolution pass against the same build's catalogue rows — never authored. The manifest declares intent; this column records whether the intent is realised in the corpus the build read. Staleness is deliberately NOT a value here: it is a coverage-time verdict against `scaffolds.corpus_ref` (M-ADR 0207 §4.6), because a git-derived value in a derived row would break rebuild determinism against unchanged authored inputs.
205
+ interaction_pattern:
206
+ values:
207
+ - value: event-stream-consume
208
+ description: Subscribe to and drain a broker / stream / feed the provider produces; the consumer drains a durable, ordered channel (Event-Driven / Polling Consumer over a Message Channel).
209
+ - value: webhook
210
+ description: Expose an endpoint the other side pushes events to as they occur (Event-Driven Consumer, HTTP push).
211
+ - value: socket-listen
212
+ description: Accept connection-oriented sessions the source initiates and read framed data (Channel Adapter, transport listener).
213
+ - value: poll
214
+ description: Periodically request current or incremental state from the source (Polling Consumer).
215
+ - value: request-response
216
+ description: Synchronous call-and-wait; the result returns in the same exchange (Request-Reply, synchronous).
217
+ - value: async-request
218
+ description: Submit a request; the result returns later via a separate channel, correlated by identifier (Request-Reply, asynchronous + Correlation Identifier).
219
+ - value: publish
220
+ description: Fire-and-forget write to a broker / queue / endpoint with no awaited response (Publish-Subscribe / fire-and-forget Message).
221
+ description: "How a capability's declared dependency on a service is coupled at RUNTIME — M-ADR 0171's closed interaction-pattern vocabulary (the union of its ingestion and invocation sets), reused on `capability_service.interaction_pattern` per M-ADR 0211 §4.1 and not widened. BOUND because the value comes from the traceability manifest, a method-mandated authoring surface (M-ADR 0210 §4.5). A NON-RUNTIME coupling — build-time code generation, a load-time singleton, packaging, an authoring sequence — leaves the column EMPTY and states its kind in the manifest's dependency_notes; that is T4's excluded-by-class case and reaches no band 5. An entry declares ONE coupling: two tokens in one entry is two entries. Measured at two estates before binding: 17 of 18 runtime couplings mapped onto exactly one token; none needed a token the vocabulary lacks."
222
+ event_participation:
223
+ values:
224
+ - value: publishes
225
+ description: The participant emits the event.
226
+ - value: consumes
227
+ description: The participant receives the event.
228
+ description: "The part a service, capability or feature plays toward an event, in `service_event.role`, `capability_event.role` and `feature_event.role`. `service_event.role` is also M-ADR 0206 §4.2's role-conditional impact flow (publishes → toward-target, consumes → toward-source). Bound at 3.9.0 (M-ADR 0210 §4.5): the values come from repo-config and derived edges, method-mandated surfaces; every row at both adopter estates' committed aggregates was in-vocabulary when bound."
229
+ contract_participation:
230
+ values:
231
+ - value: exposes
232
+ description: The service publishes the contract as its own surface.
233
+ - value: consumes
234
+ description: The service depends on a contract another service exposes.
235
+ description: The part a service plays toward a contract, in `service_contract.role`. Bound at 3.9.0 (M-ADR 0210 §4.5); one estate's rows were all `exposes`, the other's all `consumes` — the union is the vocabulary, and each estate's usage was in it.
236
+ consumption_role:
237
+ values:
238
+ - value: consumes
239
+ description: The product depends on / consumes the target.
240
+ description: "The part a product plays toward a capability or service it depends on, in `product_capability.role` and `product_service.role`. EXACTLY ONE VALUE, deliberately: every row at both estates carries `consumes`, and a column with one value is a population of one (M-ADR 0200 §4.10). Bound so the constant is DECLARED rather than accidental — a second value arriving is then a vocabulary decision with a finding, not a silent widening."
241
+ journey_participation:
242
+ values:
243
+ - value: primary
244
+ description: The persona the journey is designed around.
245
+ - value: handoff
246
+ description: A persona the journey passes to or from.
247
+ - value: supporting
248
+ description: A persona present in the journey without owning it.
249
+ description: "The kind of participation a persona has in a user journey, in `persona_journey.role` — the ADR 0210 worked example's `participation`. Bound at 3.9.0 (M-ADR 0210 §4.5): parsed from the persona spec's declared `Roles:` line, a method template surface; every row at both estates was in-vocabulary when bound."
250
+ model_notation:
251
+ values:
252
+ - value: mermaid-erd
253
+ description: M-ADR 0042's diagram grammar (data-model.mermaid.md) — the pre-Decision-1 form; migrates at the model's next requirements pass.
254
+ - value: typeql
255
+ description: The documented TypeQL subset of M-ADR 0210 §4.2 (data-model.tql) — the canonical form of every model authored from 2026-09-17 and of every migrated model.
256
+ description: "The notation a domain-model artefact is written in. Bound at 3.11.0 as the instrument of M-ADR 0210 §4.6 Decision 2: the builder derives it from the file, the metric line counts it, and a mermaid-erd row becomes an error at the first rebuild after the sunset 2027-03-31."
257
+ sdd_profile:
258
+ values:
259
+ - value: application-product
260
+ - value: integration-product
261
+ - value: platform-profile
262
+ - value: support-repo
263
+ description: "The SDD profile vocabulary (M-ADR 0135: one method, four profiles), as products/applications.profile and domains.method_profile carry it. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4)."
264
+ sdd_category:
265
+ values:
266
+ - value: application-product
267
+ - value: integration-provider
268
+ - value: integration-umbrella
269
+ - value: platform-root
270
+ - value: platform-subsystem
271
+ - value: support-repo
272
+ description: "The product category taxonomy (M-ADR 0131 / 0170): the architectural classification a products row carries. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4)."
273
+ product_lifecycle:
274
+ values:
275
+ - value: active
276
+ - value: planned
277
+ - value: deprecated
278
+ description: Product lifecycle (M-ADR 0201). Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
279
+ product_surface:
280
+ values:
281
+ - value: ui
282
+ - value: api
283
+ description: "M-ADR 0167: an application-product's surface trait. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4)."
284
+ product_packaging:
285
+ values:
286
+ - value: self-operated
287
+ - value: vendor-saas
288
+ description: "M-ADR 0175: the packaging axis. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4)."
289
+ domain_status:
290
+ values:
291
+ - value: active
292
+ - value: deferred
293
+ - value: absent
294
+ description: Domain lifecycle as domains.status carries it. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
295
+ invocation_pattern:
296
+ values:
297
+ - value: request-response
298
+ - value: async-request
299
+ - value: publish
300
+ description: M-ADR 0171's invocation half of the interaction vocabulary (the ingestion half is event-stream-consume | webhook | socket-listen | poll; both halves together are enums.interaction_pattern). Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
301
+ integration_component_resolution:
302
+ values:
303
+ - value: repository
304
+ - value: service
305
+ - value: undeclared
306
+ - value: unresolved
307
+ description: How an integration component's implementation was resolved. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
308
+ integration_component_declared_in:
309
+ values:
310
+ - value: component-manifest
311
+ - value: components-array
312
+ description: Where the component was declared in the integration manifest. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
313
+ confidence_level:
314
+ values:
315
+ - value: high
316
+ - value: medium
317
+ - value: low
318
+ description: Three-level confidence used by reverse-derived rows. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
319
+ capability_adr_confidence:
320
+ values:
321
+ - value: spec
322
+ - value: high
323
+ - value: medium
324
+ description: "capability_adr edge confidence: spec when the capability spec cites the ADR; high | medium when inferred. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4)."
325
+ glossary_xref_relation:
326
+ values:
327
+ - value: references
328
+ - value: supersedes
329
+ - value: alias-of
330
+ - value: conflicts-with
331
+ description: M-ADR 0158 glossary cross-reference relations. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
332
+ capability_source:
333
+ values:
334
+ - value: capability-spec
335
+ - value: capability-tree
336
+ - value: product-map
337
+ description: Which artefact a capabilities row was derived from. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
338
+ feature_source:
339
+ values:
340
+ - value: feature-spec
341
+ - value: feature-set
342
+ - value: feature-tree
343
+ - value: feature-grounding
344
+ - value: capability-spec
345
+ description: Which artefact a features row was derived from (M-ADR 0145). Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
346
+ artefact_maturity:
347
+ values:
348
+ - value: absent
349
+ - value: provisional
350
+ - value: working
351
+ - value: unknown
352
+ description: Maturity of a feature or screen as its grounding declares it. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
353
+ contract_kind:
354
+ values:
355
+ - value: rest
356
+ - value: event
357
+ - value: graphql
358
+ - value: rpc
359
+ - value: authz
360
+ description: Contract kind. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
361
+ contract_status:
362
+ values:
363
+ - value: active
364
+ - value: deprecated
365
+ description: Contract lifecycle status. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
366
+ contract_visibility:
367
+ values:
368
+ - value: public
369
+ - value: internal
370
+ - value: private
371
+ description: Contract visibility. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
372
+ contract_discovery:
373
+ values:
374
+ - value: discovered
375
+ - value: declared-external
376
+ description: Whether the contract was discovered in the SDD or declared as external. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
377
+ persistence_kind:
378
+ values:
379
+ - value: relational-table
380
+ - value: document-collection
381
+ - value: event-payload
382
+ - value: dto
383
+ - value: view
384
+ - value: other
385
+ description: M-ADR 0159 entity persistence kind. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
386
+ required_stability:
387
+ values:
388
+ - value: locked
389
+ - value: provisional
390
+ - value: unknown
391
+ description: "M-ADR 0204: the stability a consumer requires of a target; external | legacy live in target_locus, not here. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4)."
392
+ service_entity_relation:
393
+ values:
394
+ - value: owns
395
+ - value: reads
396
+ - value: writes
397
+ - value: references
398
+ description: How a service relates to a data-model entity. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
399
+ edge_source:
400
+ values:
401
+ - value: authored
402
+ - value: derived
403
+ description: Whether an edge row was authored in a manifest or derived by the builder. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
404
+ feature_contract_derivation_path:
405
+ values:
406
+ - value: cap-feature-cap-contract
407
+ - value: feature-service-service-contract
408
+ description: The join path a feature_contract row was derived through. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
409
+ subscription_channel_transport:
410
+ values:
411
+ - value: sse
412
+ - value: appsync-websocket
413
+ - value: pekko-ws
414
+ - value: mqtt
415
+ - value: webhook-push
416
+ - value: other
417
+ description: Transport of a feature subscription channel. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
418
+ capability_domain_model_source:
419
+ values:
420
+ - value: traceability-manifest
421
+ - value: inferred
422
+ description: "M-ADR 0142: whether the capability→domain-model edge was declared or inferred. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4)."
423
+ target_locus:
424
+ values:
425
+ - value: platform
426
+ - value: external
427
+ - value: legacy
428
+ description: "M-ADR 0204 §4.1: a statement about the dependency TARGET only. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4)."
429
+ dependency_contract_type:
430
+ values:
431
+ - value: openapi
432
+ - value: graphql
433
+ - value: grpc
434
+ - value: event
435
+ - value: event-stream
436
+ - value: stream
437
+ - value: rest
438
+ - value: other
439
+ description: Contract type of a platform dependency. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
440
+ data_plane_pattern:
441
+ values:
442
+ - value: own-store
443
+ - value: project
444
+ - value: retrieve
445
+ - value: stream-ingest
446
+ - value: publish
447
+ - value: generate
448
+ description: M-ADR 0193 / 0194 data-plane patterns, both sides. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
449
+ data_plane_direction:
450
+ values:
451
+ - value: inbound
452
+ - value: output
453
+ description: "M-ADR 0193 §4.7: the side of the data plane a binding is on. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4)."
454
+ data_plane_locality:
455
+ values:
456
+ - value: internal-platform
457
+ - value: internal-domain
458
+ - value: external-vendor
459
+ description: M-ADR 0193 locality of a data-plane binding's source. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
460
+ ui_component_kind:
461
+ values:
462
+ - value: element
463
+ - value: layout
464
+ - value: input
465
+ - value: display
466
+ - value: chart
467
+ - value: composite
468
+ - value: remote
469
+ - value: remote-iframe
470
+ - value: remote-webcomponent
471
+ description: M-ADR 0166 UI component kinds. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
472
+ conformance_target:
473
+ values:
474
+ - value: code-vs-contract
475
+ - value: binding-vs-reality
476
+ description: M-ADR 0194 conformance finding target. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
477
+ conformance_role:
478
+ values:
479
+ - value: as-is
480
+ - value: to-be
481
+ description: M-ADR 0194 conformance finding role. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
482
+ conformance_lifecycle:
483
+ values:
484
+ - value: active
485
+ - value: planned
486
+ - value: deprecated
487
+ - value: migrating
488
+ - value: legacy-active
489
+ - value: decommissioned
490
+ description: M-ADR 0194 conformance finding lifecycle. Bound at 3.13.0 from the column descriptions; measured against both reference estates before binding (M-ADR 0205 §4.4).
491
+ catalogues:
492
+ domains:
493
+ primary_key: id
494
+ columns:
495
+ - name: id
496
+ type: string
497
+ nullable: false
498
+ description: Slug, e.g. identity, asset.
499
+ - name: name
500
+ type: string
501
+ nullable: false
502
+ description: Display name.
503
+ - name: description
504
+ type: string
505
+ nullable: false
506
+ - name: method_profile
507
+ type: string
508
+ nullable: false
509
+ description: platform-profile | application-product | integration-product.
510
+ - name: reference_architecture_equivalent
511
+ type: string
512
+ nullable: true
513
+ - name: status
514
+ type: string
515
+ nullable: false
516
+ description: active | deferred | absent. The builder emits 'active' for every discovered domain directory — a domain that exists on disk is active by definition; deferred/absent rows have no authoring source yet (would come from roadmap/archetype declarations, not discovery).
517
+ - name: repo_count
518
+ type: int
519
+ nullable: false
520
+ - name: source_sdd_id
521
+ type: string
522
+ nullable: true
523
+ description: Originating SDD slug. Populated by the aggregator at merge time per M-ADR 0134; left empty by per-SDD builders.
524
+ - name: platform_sdd_id
525
+ type: string
526
+ nullable: true
527
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
528
+ column_enums:
529
+ method_profile: enums.sdd_profile
530
+ status: enums.domain_status
531
+ products:
532
+ primary_key: id
533
+ columns:
534
+ - name: id
535
+ type: string
536
+ nullable: false
537
+ description: product_id slug.
538
+ - name: name
539
+ type: string
540
+ nullable: false
541
+ - name: domain_id
542
+ type: string
543
+ nullable: true
544
+ description: Owning capability domain. Populated for platform-profile products (platform-root, platform-subsystem). App and integration products do not have a primary domain — see M-ADR 0136.
545
+ - name: profile
546
+ type: string
547
+ nullable: false
548
+ description: platform-profile | application-product | integration-product | support-repo.
549
+ - name: category
550
+ type: string
551
+ nullable: true
552
+ description: "Architectural classification per docs/method/methods/standards/product-category-taxonomy.md. Values: platform-root | platform-subsystem | application-product | integration-provider | integration-umbrella | support-repo. Determines whether the Product gets a c4_systems row."
553
+ - name: doc_path
554
+ type: string
555
+ nullable: false
556
+ description: Path to _product/ directory, relative to docs/.
557
+ - name: lifecycle
558
+ type: string
559
+ nullable: true
560
+ description: "planned | active | deprecated (default active when empty). Owner-declared product lifecycle from the SDD manifest's lifecycle: field (sdd-manifest-schema 1.1.0; `planned` added 1.9.0 / catalogue 2.47.0). `planned` = the product is real and intended but does not exist yet, which is the normal opening state of a forward-authored product — so a forward estate that has generated nothing should read `planned`, not the `active` the empty default implies. Distinct from status (documentation maturity): lifecycle is a fact about the PRODUCT, status about the DOCUMENT, and both can hold at once — a product can be reviewed AND deprecated, or planned AND thinly documented. Added in 2.22.0."
561
+ - name: deprecated_date
562
+ type: date
563
+ nullable: true
564
+ description: Date the deprecation decision took effect. Only meaningful when lifecycle=deprecated. From the manifest's deprecated_date:. Added in 2.22.0.
565
+ - name: successor_sdd_id
566
+ type: string
567
+ nullable: true
568
+ description: "For deprecated products: sdd_id of the superseding SDD. Same vocabulary as sdd_id/source_sdd_id (NOT products.id). Soft reference — the aggregator orphan-checks it against contributing sdd_ids ([finding] orphan when unresolved), never a hard FK: the successor may live outside the aggregation scope. Added in 2.22.0."
569
+ - name: exemplar
570
+ type: string
571
+ nullable: true
572
+ description: "`true` when this SDD is a reference exemplar — it demonstrates a profile shape rather than modelling a real product or provider relationship. Empty otherwise, which is the unmarked norm (absent in the manifest = a real SDD, no finding). From the manifest's `exemplar:` field (sdd-manifest-schema 1.8.0). PROFILE-AGNOSTIC, unlike surface/packaging/application_archetype which are application-product-only — the first exemplar cohort found was integration-products. DERIVED, not authorable: this column and `integrations.exemplar` both come from the one manifest field, so they cannot disagree; two independently authored copies could, which is the failure mode the trait exists to remove. No builder branches on it — it is emitted to be filterable and nothing consumes it, because an implicit exclusion inside a rollup is much harder to remove than to add. Added in 2.46.0."
573
+ - name: surface
574
+ type: string
575
+ nullable: true
576
+ description: "ui | api (empty for non-application-product). Application-product surface trait from the manifest's surface: field (M-ADR 0167, sdd-manifest-schema 1.2.0). Empty on non-application products. Added in 2.35.0."
577
+ - name: packaging
578
+ type: string
579
+ nullable: true
580
+ description: "vendor-saas | self-operated (empty for non-application-product). Application-product packaging trait from the manifest's packaging: field (M-ADR 0175, sdd-manifest-schema 1.7.0). `vendor-saas` marks a packaged-SaaS product — vendor-operated runtime (no own deployment evidence) and a vendor-versioned base capability set. Absent in the manifest resolves to `self-operated`, the unmarked norm. Per M-ADR 0175 §4 no builder may branch on this trait beyond evidence/deployment handling. Column position follows the M-ADR 0194 §3.1 canonical axis order (surface, packaging, application_archetype). Added in 2.41.0."
581
+ - name: application_archetype
582
+ type: string
583
+ nullable: true
584
+ description: "Application-product shape classification from the manifest's application_archetype: field (M-ADR 0191, sdd-manifest-schema 1.2.0). Resolved-enum over a tiered vocabulary (method: unclassified; reference-architecture bundle; adopter). Defaults to 'unclassified' for application-product (with a coverage finding), empty for other profiles. Distinct from the M-ADR 0173 domain archetype and M-ADR 0169 openui archetype. Added in 2.35.0."
585
+ - name: synthesis_quality
586
+ type: int
587
+ nullable: true
588
+ description: "DEPRECATED at 3.3.0, for removal at 4.0.0 — superseded by `quality_scores` (rubric_id `reverse-product-quality.product_synthesis_quality`). Score 0-10 from the product-synthesis rubric (reverse method only). WIRED in 2.47.0 from `orchestration/gate-registry/reverse-product-quality-scores.yaml` — the registry family at product granularity — via the SELF-PRODUCT rule: the unit whose `product_path` is '.' AND whose key equals the SDD's sdd_id. Both conditions are required; product_path alone admits synthetic gate fixtures, key-matching alone admits covered sub-products. Backfill only: it fills an empty cell and never overwrites an emitted value. Empty on a forward estate by design — a forward-authored product has no reverse rubric score, and residue-based authoring signals deliberately do NOT write here (see status)."
589
+ - name: synthesis_band
590
+ type: string
591
+ nullable: true
592
+ description: "DEPRECATED at 3.3.0, for removal at 4.0.0 — superseded by `quality_scores.band`, which is UNBOUND because the vocabulary is per-rubric. This column's closed set accepts only three of the SEVEN band values the reverse estate actually authors (measured 3.3.0: strong, working, weak, moderate, easy, hard, very-hard), silently emptying the rest. developing | working | strong — a CLOSED vocabulary; a band outside it is reported as a convention finding and the cell left empty rather than emitting a value no consumer can interpret. Wired in 2.47.0 alongside synthesis_quality."
593
+ - name: last_assessed
594
+ type: date
595
+ nullable: true
596
+ - name: highest_snapshot_impact
597
+ type: string
598
+ nullable: true
599
+ - name: repo_count
600
+ type: int
601
+ nullable: false
602
+ description: Number of repos mapped to this product.
603
+ - name: source_sdd_id
604
+ type: string
605
+ nullable: true
606
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
607
+ - name: platform_sdd_id
608
+ type: string
609
+ nullable: true
610
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
611
+ foreign_keys:
612
+ - column: domain_id
613
+ references: domains.id
614
+ nullable: true
615
+ column_enums:
616
+ profile: enums.sdd_profile
617
+ category: enums.sdd_category
618
+ lifecycle: enums.product_lifecycle
619
+ surface: enums.product_surface
620
+ packaging: enums.product_packaging
621
+ applications:
622
+ primary_key: id
623
+ columns:
624
+ - name: id
625
+ type: string
626
+ nullable: false
627
+ description: product_id slug.
628
+ - name: name
629
+ type: string
630
+ nullable: false
631
+ - name: domain_id
632
+ type: string
633
+ nullable: true
634
+ description: Owning capability domain. Populated for platform-profile products (platform-root, platform-subsystem). App and integration products do not have a primary domain — see M-ADR 0136.
635
+ - name: profile
636
+ type: string
637
+ nullable: false
638
+ description: platform-profile | application-product | integration-product | support-repo.
639
+ - name: category
640
+ type: string
641
+ nullable: true
642
+ description: "Architectural classification per docs/method/methods/standards/product-category-taxonomy.md. Values: platform-root | platform-subsystem | application-product | integration-provider | integration-umbrella | support-repo. Determines whether the Product gets a c4_systems row."
643
+ - name: doc_path
644
+ type: string
645
+ nullable: false
646
+ description: Path to _product/ directory, relative to docs/.
647
+ - name: lifecycle
648
+ type: string
649
+ nullable: true
650
+ description: "planned | active | deprecated (default active when empty). Owner-declared product lifecycle from the SDD manifest's lifecycle: field (sdd-manifest-schema 1.1.0; `planned` added 1.9.0 / catalogue 2.47.0). `planned` = the product is real and intended but does not exist yet, which is the normal opening state of a forward-authored product — so a forward estate that has generated nothing should read `planned`, not the `active` the empty default implies. Distinct from status (documentation maturity): lifecycle is a fact about the PRODUCT, status about the DOCUMENT, and both can hold at once — a product can be reviewed AND deprecated, or planned AND thinly documented. Added in 2.22.0."
651
+ - name: deprecated_date
652
+ type: date
653
+ nullable: true
654
+ description: Date the deprecation decision took effect. Only meaningful when lifecycle=deprecated. From the manifest's deprecated_date:. Added in 2.22.0.
655
+ - name: successor_sdd_id
656
+ type: string
657
+ nullable: true
658
+ description: "For deprecated products: sdd_id of the superseding SDD. Same vocabulary as sdd_id/source_sdd_id (NOT products.id). Soft reference — the aggregator orphan-checks it against contributing sdd_ids ([finding] orphan when unresolved), never a hard FK: the successor may live outside the aggregation scope. Added in 2.22.0."
659
+ - name: exemplar
660
+ type: string
661
+ nullable: true
662
+ description: "`true` when this SDD is a reference exemplar — it demonstrates a profile shape rather than modelling a real product or provider relationship. Empty otherwise, which is the unmarked norm (absent in the manifest = a real SDD, no finding). From the manifest's `exemplar:` field (sdd-manifest-schema 1.8.0). PROFILE-AGNOSTIC, unlike surface/packaging/application_archetype which are application-product-only — the first exemplar cohort found was integration-products. DERIVED, not authorable: this column and `integrations.exemplar` both come from the one manifest field, so they cannot disagree; two independently authored copies could, which is the failure mode the trait exists to remove. No builder branches on it — it is emitted to be filterable and nothing consumes it, because an implicit exclusion inside a rollup is much harder to remove than to add. Added in 2.46.0."
663
+ - name: surface
664
+ type: string
665
+ nullable: true
666
+ description: "ui | api (empty for non-application-product). Application-product surface trait from the manifest's surface: field (M-ADR 0167, sdd-manifest-schema 1.2.0). Empty on non-application products. Added in 2.35.0."
667
+ - name: packaging
668
+ type: string
669
+ nullable: true
670
+ description: "vendor-saas | self-operated (empty for non-application-product). Application-product packaging trait from the manifest's packaging: field (M-ADR 0175, sdd-manifest-schema 1.7.0). `vendor-saas` marks a packaged-SaaS product — vendor-operated runtime (no own deployment evidence) and a vendor-versioned base capability set. Absent in the manifest resolves to `self-operated`, the unmarked norm. Per M-ADR 0175 §4 no builder may branch on this trait beyond evidence/deployment handling. Column position follows the M-ADR 0194 §3.1 canonical axis order (surface, packaging, application_archetype). Added in 2.41.0."
671
+ - name: application_archetype
672
+ type: string
673
+ nullable: true
674
+ description: "Application-product shape classification from the manifest's application_archetype: field (M-ADR 0191, sdd-manifest-schema 1.2.0). Resolved-enum over a tiered vocabulary (method: unclassified; reference-architecture bundle; adopter). Defaults to 'unclassified' for application-product (with a coverage finding), empty for other profiles. Distinct from the M-ADR 0173 domain archetype and M-ADR 0169 openui archetype. Added in 2.35.0."
675
+ - name: synthesis_quality
676
+ type: int
677
+ nullable: true
678
+ description: "DEPRECATED at 3.3.0, for removal at 4.0.0 — superseded by `quality_scores` (rubric_id `reverse-product-quality.product_synthesis_quality`). Score 0-10 from the product-synthesis rubric (reverse method only). WIRED in 2.47.0 from `orchestration/gate-registry/reverse-product-quality-scores.yaml` — the registry family at product granularity — via the SELF-PRODUCT rule: the unit whose `product_path` is '.' AND whose key equals the SDD's sdd_id. Both conditions are required; product_path alone admits synthetic gate fixtures, key-matching alone admits covered sub-products. Backfill only: it fills an empty cell and never overwrites an emitted value. Empty on a forward estate by design — a forward-authored product has no reverse rubric score, and residue-based authoring signals deliberately do NOT write here (see status)."
679
+ - name: synthesis_band
680
+ type: string
681
+ nullable: true
682
+ description: "DEPRECATED at 3.3.0, for removal at 4.0.0 — superseded by `quality_scores.band`, which is UNBOUND because the vocabulary is per-rubric. This column's closed set accepts only three of the SEVEN band values the reverse estate actually authors (measured 3.3.0: strong, working, weak, moderate, easy, hard, very-hard), silently emptying the rest. developing | working | strong — a CLOSED vocabulary; a band outside it is reported as a convention finding and the cell left empty rather than emitting a value no consumer can interpret. Wired in 2.47.0 alongside synthesis_quality."
683
+ - name: last_assessed
684
+ type: date
685
+ nullable: true
686
+ - name: highest_snapshot_impact
687
+ type: string
688
+ nullable: true
689
+ - name: repo_count
690
+ type: int
691
+ nullable: false
692
+ description: Number of repos mapped to this product.
693
+ - name: source_sdd_id
694
+ type: string
695
+ nullable: true
696
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
697
+ - name: platform_sdd_id
698
+ type: string
699
+ nullable: true
700
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
701
+ description: Filtered view of products where profile = application-product.
702
+ foreign_keys:
703
+ - column: domain_id
704
+ references: domains.id
705
+ nullable: true
706
+ column_enums:
707
+ profile: enums.sdd_profile
708
+ category: enums.sdd_category
709
+ lifecycle: enums.product_lifecycle
710
+ surface: enums.product_surface
711
+ packaging: enums.product_packaging
712
+ integrations:
713
+ primary_key: id
714
+ columns:
715
+ - name: id
716
+ type: string
717
+ nullable: false
718
+ description: Provider slug.
719
+ - name: name
720
+ type: string
721
+ nullable: false
722
+ - name: domain_id
723
+ type: string
724
+ nullable: true
725
+ description: Provider adapters are federation nodes, not capability-domain members. Left empty per M-ADR 0136.
726
+ - name: parent_product_id
727
+ type: string
728
+ nullable: true
729
+ description: Umbrella integration-product. Empty for an SDD's own row; set to the SDD's integrationId for sub-integration rows declared via integration-manifest.yaml `sub_integrations:` (per M-ADR 0144, schema 2.6.0).
730
+ - name: category
731
+ type: string
732
+ nullable: false
733
+ description: oem | device | fleet | camera | legacy | data-sharing | gateway-framework (extensible per ecosystem).
734
+ - name: doc_path
735
+ type: string
736
+ nullable: false
737
+ - name: repo_count
738
+ type: int
739
+ nullable: false
740
+ - name: ingestion_pattern
741
+ type: string
742
+ nullable: true
743
+ description: "Closed method-tier enum (event-stream-consume | webhook | socket-listen | poll) from the manifest's SDD-level `ingestionPattern` — HOW the integration acquires data (M-ADR 0171 §4.2). SCALAR: §9.3's multi-valued allowance was withdrawn in §10.5. Empty when undeclared or on an outbound-only integration. Empty on `sub_integrations` rows — the patterns are declared once at SDD level and are not per-provider. Added in 2.45.0."
744
+ - name: invocation_pattern
745
+ type: string
746
+ nullable: true
747
+ description: Closed method-tier enum (request-response | async-request | publish) from the manifest's SDD-level `invocationPattern` — HOW the integration invokes the provider (M-ADR 0171 §4.3). Scalar; empty when undeclared, on an inbound-only integration, or on a sub_integrations row. Added in 2.45.0.
748
+ - name: pattern_qualifier
749
+ type: string
750
+ nullable: true
751
+ description: Free-text sub-variant from `patternQualifier` where delivery semantics differ materially within a pattern (e.g. poll as a provider-issued ordered cursor vs a client-built window). Deliberately unconstrained — the method owns the pattern vocabulary, not every provider's delivery nuance. Added in 2.45.0.
752
+ - name: exemplar
753
+ type: string
754
+ nullable: true
755
+ description: "`true` when the emitting SDD is a reference exemplar (demonstrates a profile shape rather than modelling a real provider relationship); empty otherwise. Derived from the SDD manifest's `exemplar:` field (sdd-manifest-schema 1.8.0), same source as `products.exemplar` — neither column is independently authorable. Carried on `sub_integrations` rows too, INHERITED from the emitting SDD. That deliberately differs from `ingestion_pattern`/`invocation_pattern`, which are empty on sub rows, and the difference is the point: a pattern is a MECHANISM (how this integration acquires data), genuinely one per SDD, whereas `exemplar` is a REALITY STATUS that propagates to everything the SDD emits — if the SDD is a demonstration then every provider relationship it declares is a demonstration. Leaving sub rows empty would flag the umbrella and count its demonstration sub-providers as real, reproducing the rollup overcount this column exists to fix one level down. Do not normalise it to match the pattern columns. The trade accepted: a real SDD with one demonstration sub-provider is unexpressible — a state that should not exist. Added in 2.46.0."
756
+ - name: source_sdd_id
757
+ type: string
758
+ nullable: true
759
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
760
+ - name: platform_sdd_id
761
+ type: string
762
+ nullable: true
763
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
764
+ description: Granular provider adapters. Each row is either (a) an integration-product SDD's own row (one per SDD; parent_product_id empty), or (b) a manifest-declared sub-integration of a multi-provider monolith (parent_product_id = umbrella SDD's id). Per M-ADR 0144 (schema 2.6.0), sub-integrations are declared via the optional `sub_integrations:` array in `integration-manifest.yaml`.
765
+ foreign_keys:
766
+ - column: domain_id
767
+ references: domains.id
768
+ nullable: true
769
+ - column: parent_product_id
770
+ references: products.id
771
+ nullable: true
772
+ column_enums:
773
+ invocation_pattern: enums.invocation_pattern
774
+ integration_component:
775
+ primary_key: id
776
+ columns:
777
+ - name: id
778
+ type: string
779
+ nullable: false
780
+ description: "{integration_id}__{component_id}. A duplicate emits a divergence finding and is dropped — two components of one integration cannot share an id."
781
+ - name: integration_id
782
+ type: string
783
+ nullable: false
784
+ description: The integration-product declaring this component (this SDD's integrationId).
785
+ - name: component_id
786
+ type: string
787
+ nullable: false
788
+ description: The component's declared id, from `components[].id`. Unique within its manifest (a duplicate is dropped with a divergence finding). Names an INTERACTION SURFACE — commonly one provider feed — not necessarily a deployable; the optional `component_repo` carries the code linkage where one is asserted (M-ADR 0171 §10.2).
789
+ - name: component_repo
790
+ type: string
791
+ nullable: true
792
+ description: "OPTIONAL explicit code linkage from `components[].componentRepo` — the deployable (repositories.id / services.id) that realises this component. Empty is the normal case for a feed-level component: the tier is at interaction-surface granularity, not deployable granularity, and the method does not require a component to name a deployable (M-ADR 0171 §10.2). When declared it MUST resolve, since a declared link is a positive assertion the method can check. Added in 2.44.0."
793
+ - name: resolution
794
+ type: string
795
+ nullable: false
796
+ description: undeclared | repository | service | unresolved. `undeclared` = no `componentRepo` given (normal, no finding). `repository`/`service` = the declared linkage resolved. `unresolved` = declared but matched no repositories.id or services.id of this SDD, which carries a coverage finding. Re-based on `component_repo` in 2.44.0 — it previously described resolution of `component_id` itself.
797
+ - name: component_type
798
+ type: string
799
+ nullable: true
800
+ description: Optional adopter-defined framework-role label from `componentType` (e.g. the adopter's archetype name). NOT enumerated or validated by the method (M-ADR 0171 §9.1/§9.5) — it exists so an adopter's role→pattern mapping is traceable. Empty when unauthored.
801
+ - name: direction
802
+ type: string
803
+ nullable: true
804
+ description: "inbound | outbound | bidirectional, from `dataFlow.direction`. Determines which pattern field is meaningful: inbound → ingestion_pattern, outbound → invocation_pattern, internal components declare neither (M-ADR 0171 §9.1)."
805
+ - name: frequency
806
+ type: string
807
+ nullable: true
808
+ description: real-time | on-demand | batch, from `dataFlow.frequency`. Open string — adopters carry finer cadences in prose.
809
+ - name: transport
810
+ type: string
811
+ nullable: true
812
+ description: Concrete wire mechanism from `protocol.transport` (kafka | sns | sqs | kinesis | amqp | tcp | udp | https | grpc | ...). Open string. Insufficient alone to determine the pattern — https may be webhook, poll or request-response; direction + initiator disambiguate (M-ADR 0171 §9.2).
813
+ - name: format
814
+ type: string
815
+ nullable: true
816
+ description: Payload format from `protocol.format` (json | protobuf | binary | avro | ...). Open string.
817
+ - name: auth
818
+ type: string
819
+ nullable: true
820
+ description: Auth mechanism from `protocol.auth` (tls | sasl | oauth2 | api-key | mtls | none | ...). Open string — real estates carry vendor-specific grant variants here.
821
+ - name: ingestion_pattern
822
+ type: string
823
+ nullable: true
824
+ description: Closed method-tier enum (event-stream-consume | webhook | socket-listen | poll) from `components[].ingestionPattern`. Meaningful on inbound components; empty otherwise (M-ADR 0171 §4.2).
825
+ - name: invocation_pattern
826
+ type: string
827
+ nullable: true
828
+ description: Closed method-tier enum (request-response | async-request | publish) from `components[].invocationPattern`. Meaningful on outbound components; empty otherwise (M-ADR 0171 §4.3).
829
+ - name: pattern_qualifier
830
+ type: string
831
+ nullable: true
832
+ description: Free-text sub-variant from `patternQualifier` where delivery semantics differ materially within a pattern (e.g. poll as token-feed vs windowed). Deliberately unconstrained.
833
+ - name: primary_entities
834
+ type: string
835
+ nullable: true
836
+ description: Semicolon-joined `dataFlow.primaryEntities`. Adopter-tier entity names; joined rather than normalised because the tier is descriptive, not an FK surface.
837
+ - name: declared_in
838
+ type: string
839
+ nullable: false
840
+ description: "components-array | component-manifest — WHICH of M-ADR 0171 §9.1's two homes declared this component. Added in 2.49.0, when the second home became catalogued. Required because §10.1 states that any coverage reasoning MUST say which form it counts, and once one table holds both, a consumer cannot tell them apart: merging them without this recreates the reference-exemplar problem — well-formed rows that do not mean what a consumer assumes. Measured at the time of wiring: the array form was 15 components across 5 SDDs, the per-component form 86 across 21, and the two are DISJOINT (no id collision, no SDD using both). `resolution` also reads differently by form — for the array form `componentRepo` is an optional declaration (0 of 15 declared it); for the per-component form the containing `repos/<component>/` directory IS the repo, so linkage is structural rather than declared."
841
+ - name: source_sdd_id
842
+ type: string
843
+ nullable: true
844
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
845
+ - name: platform_sdd_id
846
+ type: string
847
+ nullable: true
848
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
849
+ description: |
850
+ Integration-product edge (M-ADR 0171 §9, catalogued per §10.1): one row per component declared in the SDD's `integration-manifest.yaml` `components:` array. A component is one of the integration's component code repos (M-ADR 0106) — an integration SDD is a one-to-many spec→code unit — and the tier is the source of truth for the interaction pattern, with the SDD-level `ingestionPattern`/`invocationPattern` as its aggregate (§9.3).
851
+ Built per-SDD, integration-product only (other profiles emit headers-only). A component id is unique within its manifest and names an **interaction surface** — commonly one provider feed — which is NOT necessarily a deployable (§10.2). The optional `component_repo` carries an explicit code linkage; when declared it MUST resolve to a `repositories.id` or `services.id` of the same SDD, and a declared-but-unresolvable linkage is a **coverage finding, not a load failure**. `resolution` records the outcome inline, including `undeclared` for the normal feed-level case, so a consumer filters on it rather than inferring from a join miss.
852
+ The method deliberately does NOT enumerate `component_type` — that is the adopter's own framework-role label (§9.1/§9.5), carried so an adopter's role→pattern mapping stays machine-traceable. `transport`/`format`/`auth` are open strings for the same reason: they describe the wire, and the portable semantic is the pattern. Added in schema 2.43.0.
853
+ foreign_keys:
854
+ - column: integration_id
855
+ references: integrations.id
856
+ nullable: false
857
+ column_enums:
858
+ invocation_pattern: enums.invocation_pattern
859
+ resolution: enums.integration_component_resolution
860
+ declared_in: enums.integration_component_declared_in
861
+ adrs:
862
+ primary_key: id
863
+ columns:
864
+ - name: id
865
+ type: string
866
+ nullable: false
867
+ description: ADR id, e.g. ADR-0001 or {domain}-D001.
868
+ - name: title
869
+ type: string
870
+ nullable: false
871
+ - name: status
872
+ type: string
873
+ nullable: true
874
+ description: Accepted | Proposed | Superseded | Deprecated | Deferred (forward) plus reverse-inferred | reverse-adapted (reverse).
875
+ - name: domain_id
876
+ type: string
877
+ nullable: true
878
+ description: "Domain slug for a domain-scoped ADR (docs/domains/<slug>/…); 'platform' for a platform-scoped ADR (docs/platform/adr/), whose owner has that domain by construction; EMPTY for a method-scoped ADR (docs/method/adr/, docs/method/platform-adr/) — method ADRs are cross-cutting governance and belong to no domain. Nullable since 3.10.0 (M-ADR 0136 §4.3 amendment): before it, method ADRs were pinned to 'platform' and dangled in every platform-root without a domain of that name."
879
+ - name: decision_date
880
+ type: date
881
+ nullable: true
882
+ - name: doc_path
883
+ type: string
884
+ nullable: false
885
+ - name: superseded_by_id
886
+ type: string
887
+ nullable: true
888
+ - name: inference_confidence
889
+ type: string
890
+ nullable: true
891
+ description: high | medium | low (reverse-inferred ADRs only).
892
+ - name: supersedes_raw
893
+ type: string
894
+ nullable: true
895
+ description: Raw text from Supersedes bullet for later parsing.
896
+ - name: source_sdd_id
897
+ type: string
898
+ nullable: true
899
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
900
+ - name: platform_sdd_id
901
+ type: string
902
+ nullable: true
903
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
904
+ foreign_keys:
905
+ - column: domain_id
906
+ references: domains.id
907
+ nullable: true
908
+ - column: superseded_by_id
909
+ references: adrs.id
910
+ nullable: true
911
+ column_enums:
912
+ inference_confidence: enums.confidence_level
913
+ glossary_items:
914
+ primary_key: id
915
+ columns:
916
+ - name: id
917
+ type: string
918
+ nullable: false
919
+ description: "Slug: {domain}-{term-slug} for uniqueness."
920
+ - name: term
921
+ type: string
922
+ nullable: false
923
+ - name: definition
924
+ type: string
925
+ nullable: false
926
+ - name: owning_domain_id
927
+ type: string
928
+ nullable: true
929
+ description: Null for platform-level terms.
930
+ - name: canonical_term_id
931
+ type: string
932
+ nullable: true
933
+ description: Set when this term is an alias for another.
934
+ - name: aliases
935
+ type: string
936
+ nullable: true
937
+ description: "';'-separated list."
938
+ - name: evidence
939
+ type: string
940
+ nullable: true
941
+ - name: notes
942
+ type: string
943
+ nullable: true
944
+ - name: source_sdd_id
945
+ type: string
946
+ nullable: true
947
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
948
+ - name: platform_sdd_id
949
+ type: string
950
+ nullable: true
951
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
952
+ foreign_keys:
953
+ - column: owning_domain_id
954
+ references: domains.id
955
+ nullable: true
956
+ - column: canonical_term_id
957
+ references: glossary_items.id
958
+ nullable: true
959
+ glossary_xref:
960
+ primary_key: id
961
+ columns:
962
+ - name: id
963
+ type: string
964
+ nullable: false
965
+ description: "Composite: {source_id}__{relation}__{target_id}."
966
+ - name: source_id
967
+ type: string
968
+ nullable: false
969
+ - name: target_id
970
+ type: string
971
+ nullable: false
972
+ - name: relation
973
+ type: string
974
+ nullable: false
975
+ description: alias-of | conflicts-with | references | supersedes (extended in schema 2.12.0 per M-ADR 0158).
976
+ description: "Edge: cross-domain glossary relationships from glossary-alignment-manifest.yaml. Per M-ADR 0158, four walkers ingest into this catalogue: (a) forward declared pair-form {source, target} entries under aliases/conflicts, (b) reverse-method cross_domain_terms (emits references edges per referencer→owner), (c) reverse-method multi-domain conflicts (pair-wise expansion across domains[]), (d) forward-method supersedes (status: superseded entries with superseded_by back-link)."
977
+ foreign_keys:
978
+ - column: source_id
979
+ references: glossary_items.id
980
+ nullable: false
981
+ - column: target_id
982
+ references: glossary_items.id
983
+ nullable: false
984
+ column_enums:
985
+ relation: enums.glossary_xref_relation
986
+ entity_glossary:
987
+ primary_key: id
988
+ columns:
989
+ - name: id
990
+ type: string
991
+ nullable: false
992
+ description: "Composite: {domain_id}__{entity_name_slug}__{glossary_item_id}."
993
+ - name: domain_id
994
+ type: string
995
+ nullable: false
996
+ - name: entity_name
997
+ type: string
998
+ nullable: false
999
+ - name: glossary_item_id
1000
+ type: string
1001
+ nullable: false
1002
+ - name: status
1003
+ type: string
1004
+ nullable: false
1005
+ description: aligned | matched_direct. Conflicting statuses within a domain resolve matched_direct > aligned with a divergence finding.
1006
+ - name: source_sdd_id
1007
+ type: string
1008
+ nullable: true
1009
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
1010
+ - name: platform_sdd_id
1011
+ type: string
1012
+ nullable: true
1013
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1014
+ - name: entity_id
1015
+ type: string
1016
+ nullable: true
1017
+ description: The data-model entity this glossary mapping is about — an entities.id. The edge was always emitted per (domain, entity, glossary_term) and this end was missing from its keys (found at M-ADR 0210 flip 2; added at 3.9.0). Nullable until every builder populates it.
1018
+ description: "Edge: data-model entity → canonical glossary term. Added in schema 2.12.0 per M-ADR 0158. Source: glossary-alignment-manifest.yaml `models[].entities[]` with status ∈ {aligned, matched_direct} and non-empty glossary_term. PK derives from (domain, entity_name, glossary_item) so same-domain multi-diagram entries collapse to one row; cross-domain entries (e.g. platform-wide conceptual model + domain-specific model) emit one row per domain — legitimate cross-level cataloguing."
1019
+ foreign_keys:
1020
+ - column: domain_id
1021
+ references: domains.id
1022
+ nullable: false
1023
+ - column: glossary_item_id
1024
+ references: glossary_items.id
1025
+ nullable: false
1026
+ - column: entity_id
1027
+ references: entities.id
1028
+ nullable: true
1029
+ services:
1030
+ primary_key: id
1031
+ columns:
1032
+ - name: id
1033
+ type: string
1034
+ nullable: false
1035
+ description: Service id, derived from artifact_id where artifact_type=service.
1036
+ - name: name
1037
+ type: string
1038
+ nullable: false
1039
+ - name: product_id
1040
+ type: string
1041
+ nullable: false
1042
+ - name: domain_id
1043
+ type: string
1044
+ nullable: true
1045
+ description: Owning capability domain. Populated when the repo-config declared domain resolves to a docs/domains/<slug>/ in the local SDD; left empty otherwise per M-ADR 0136.
1046
+ - name: primary_repo_id
1047
+ type: string
1048
+ nullable: true
1049
+ description: Main contributing repo. Nullable when service spans repos. Per M-ADR 0197, a repository MAY declare a `services:` block naming more than one service it builds — every declared entry's primary_repo_id equals the declaring repository's id, so this column is m:n (several services legitimately sharing one repository), not the 1:1 identity it holds when no repository declares the block.
1050
+ - name: runtime_type
1051
+ type: string
1052
+ nullable: true
1053
+ description: serverless-framework | jvm-service | lambda | k8s | ...
1054
+ - name: language
1055
+ type: string
1056
+ nullable: true
1057
+ - name: component_type
1058
+ type: string
1059
+ nullable: true
1060
+ description: bff | api | consumer | ui | collector | processor | ...
1061
+ - name: status
1062
+ type: string
1063
+ nullable: true
1064
+ description: production-wired | non-production | library.
1065
+ - name: confidence
1066
+ type: string
1067
+ nullable: true
1068
+ description: high | medium | low (reverse-method classification).
1069
+ - name: context
1070
+ type: string
1071
+ nullable: true
1072
+ description: Bounded-context membership (per M-ADR 0170 §4.6). Free-form adopter label, orthogonal to domain_id. Not an FK. Carried for forward-parity; awaits a derivation source (e.g. from the service's contracts' x-context). Added in schema 2.19.0.
1073
+ - name: description
1074
+ type: string
1075
+ nullable: true
1076
+ - name: source_sdd_id
1077
+ type: string
1078
+ nullable: true
1079
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
1080
+ - name: platform_sdd_id
1081
+ type: string
1082
+ nullable: true
1083
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1084
+ foreign_keys:
1085
+ - column: product_id
1086
+ references: products.id
1087
+ nullable: false
1088
+ - column: domain_id
1089
+ references: domains.id
1090
+ nullable: true
1091
+ - column: primary_repo_id
1092
+ references: repositories.id
1093
+ nullable: true
1094
+ column_enums:
1095
+ component_type: enums.service_type
1096
+ confidence: enums.confidence_level
1097
+ capabilities:
1098
+ primary_key: id
1099
+ columns:
1100
+ - name: id
1101
+ type: string
1102
+ nullable: false
1103
+ description: Capability slug.
1104
+ - name: name
1105
+ type: string
1106
+ nullable: false
1107
+ - name: domain_id
1108
+ type: string
1109
+ nullable: false
1110
+ - name: tree_category
1111
+ type: string
1112
+ nullable: true
1113
+ description: Top-level grouping when capability comes from a capability tree (reverse).
1114
+ - name: parent_capability_id
1115
+ type: string
1116
+ nullable: true
1117
+ - name: evidence_class
1118
+ type: string
1119
+ nullable: true
1120
+ description: Evidence class of the capability's claims, from `capability.evidence_class` in the traceability manifest. Free-form; conventional values code-reverse | vendor-doc | operational (M-ADR 0175). Empty when undeclared. Added in schema 2.20.0.
1121
+ - name: context
1122
+ type: string
1123
+ nullable: true
1124
+ description: Bounded-context membership from `capability.context` in the traceability manifest (per M-ADR 0170 §4.6) — completes the context dimension across screens/contracts/services/entities (2.19.0). Free-form adopter label, orthogonal to domain_id. Not an FK. Enables the screen↔capability context cross-check (convention finding, not FK). Empty when undeclared. Added in schema 2.21.0.
1125
+ - name: description
1126
+ type: string
1127
+ nullable: true
1128
+ - name: status
1129
+ type: string
1130
+ nullable: false
1131
+ description: "Capability LIFECYCLE phase — this column carries ONE axis and the reader may rely on that. active | planned | exploration | deprecated. Default 'active'. History, because the shape of the mistake is the useful part: the prior three-member set (active|planned|deprecated) could not express what estates authored, so 3.5.0 widened it to six on measured evidence — 44 of one estate's 78 manifests were outside it (exploration 26, placeholder 11, detailed-pre-lock 6, first-draft 1), each recurring value varying WITHIN a domain, which is the ruled discriminator for a genuine phase over an authoring convention. But 3.6.0 RETRACTED `placeholder` and `detailed-pre-lock`: per M-ADR 0201 §1 those are rungs on the SPEC-AUTHORING ladder (`placeholder | first-draft | detailed-pre-lock`, plus §4.1's `reverse-derived`), declared in each spec's own `**Status:**` header and gated there by the spec-lifecycle gate. Admitting them here made one column carry two orthogonal axes, so a reader could not tell whether `placeholder` described the capability or its document. **Where the other axis lives: the spec header. Do not re-import it here.** `exploration` stays and is NOT authoring vocabulary — it is absent from 0201's ladder, has M-ADR 0089's workflow and named gates behind it, and describes the capability rather than its spec; a capability declaring it must carry a populated `traceability.exploration` block, and one that does not is a loud contradiction (validate-traceability enforces this; measured 0 of 26 violations). ⚠ A rule this column deliberately does NOT carry: `placeholder`'s. The obvious one (no authored features) was MEASURED FALSE — 4 of 11 carried features, one of them 9 — and the deeper reason no rule fit is that `placeholder` was never making a claim about the capability at all. That unwritable rule was the first symptom of the axis error, before anyone had named it. ⚠ DELIBERATELY NOT BOUND via column_enums, and this is staged rather than permanent: binding carries hard-fail teeth, and at 3.5.0 one out-of-vocabulary row remains (forward estate, `first-draft`, n=1, referred to that estate; the reverse estate measures ZERO across 180 manifests). An out-of-vocabulary value is CARRIED, not emptied and not rejected, and is reported as a convention finding by validate-traceability — nullable stays false and no cell is ever emptied, so the empty-means-unauthored-or-rejected ambiguity of the products.synthesis_band / quality_scores.gate precedents does not arise here. Bind only once that count is ZERO at both estates; binding a set not proven to cover what estates author is how synthesis_band earned its deprecation. On drift and enforcement, stated with its confound rather than as a slogan: the enforced sibling `contracts.status` drifted 1.2% (2 of 172) while this unenforced field drifted 56% (44 of 78) at the SAME estate — but the other estate's copy of this same unenforced field drifted 0% of 180, so enforcement is not the only variable. The difference is authoring shape: the forward estate hand-authors per capability across 13 domains and explores vocabulary doing it, while the reverse estate's manifests come from one largely uniform extraction process. That uniformity is itself the phase-vs-convention discriminator firing — a value uniform across a whole estate is tracking the process that wrote it."
1132
+ - name: spec_path
1133
+ type: string
1134
+ nullable: true
1135
+ description: Path to capability spec file when one exists.
1136
+ - name: contract_provenance
1137
+ type: string
1138
+ nullable: true
1139
+ description: "How this capability's declared contract SET was produced, from `traceability.contracts.provenance`. hand-authored | reverse-extracted | generated — the vocabulary the method already ships for `authoring-mode`, reused deliberately so provenance has one vocabulary and not two. Empty means undeclared, and undeclared reads as `hand-authored` by convention. Added at 3.5.0. ⚠ STRICTLY ORTHOGONAL to the contract-set maturity ladder (`traceability.contracts.status`: planned | provisional | partial | complete | locked | none): provenance never constrains status and status never constrains provenance, and `reverse-extracted` + `complete` is the legitimate pair that motivated the field. Evidence: 2 reverse-estate manifests had written `reverse-extracted` INTO contracts.status, where it is invalid, because a complete reverse-derived contract surface had no way to say both true things at once and the author picked the provenance one. A rule here that constrained maturity would re-create exactly that defect. ⚠ Note the asymmetry this column exposes and does not fix: the maturity ladder it is orthogonal to has NO catalogue column at all — `traceability.contracts.status` is validator-enforced but uncatalogued, so it is queryable by no consumer. That is the authored-but-uncatalogued class (a block with no column has no automated reader, so nothing can notice when it is absent or wrong); this column is given one precisely so the provenance half does not join it. Giving the ladder a column is a candidate follow-on, not done here."
1140
+ - name: source
1141
+ type: string
1142
+ nullable: false
1143
+ description: capability-tree | product-map | capability-spec.
1144
+ - name: runway_classification
1145
+ type: string
1146
+ nullable: true
1147
+ description: Business | Enabler-Runway | Hybrid (forward declares; reverse nullable until backfilled).
1148
+ - name: data_subset
1149
+ type: string
1150
+ nullable: true
1151
+ description: Keying-axis marker for foundational-tier / synthesis-tier capabilities whose evidence is keyed by ownership boundary or data subset rather than app group. Populated from `capability.data_subset` in the traceability manifest. Empty for implementing-tier capabilities (those use app_group on per-evidence rows). See `docs/method/methods/reverse/rubrics/reverse-platform-evidence-quality.md` §`app_group:` → `data_subset:` rename. Added in schema 2.9.0.
1152
+ - name: slice_scope
1153
+ type: string
1154
+ nullable: true
1155
+ description: "Per-slice marker when one capability legitimately covers multiple app groups or data subsets (e.g. a compliance capability spanning several regulated-fleet sub-groups). Same capability_id may appear across multiple rows when sliced; row identity is then `(id, slice_scope)`. Empty when the capability is not sliced. Per-slice AC numbering convention: AC1-ACN unsuffixed for the first slice; subsequent slices use AC numbering suffixed by slice. See `docs/method/methods/reverse/rubrics/reverse-platform-evidence-quality.md` §`slice_scope:` and `docs/method/methods/capability-spec-template.md` Guideline 9. Added in schema 2.9.0."
1156
+ - name: source_sdd_id
1157
+ type: string
1158
+ nullable: true
1159
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
1160
+ - name: platform_sdd_id
1161
+ type: string
1162
+ nullable: true
1163
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1164
+ foreign_keys:
1165
+ - column: domain_id
1166
+ references: domains.id
1167
+ nullable: false
1168
+ external_for_profiles:
1169
+ - application-product
1170
+ - integration-product
1171
+ - column: parent_capability_id
1172
+ references: capabilities.id
1173
+ nullable: true
1174
+ column_enums:
1175
+ source: enums.capability_source
1176
+ feature_groups:
1177
+ primary_key: id
1178
+ columns:
1179
+ - name: id
1180
+ type: string
1181
+ nullable: false
1182
+ description: "{product_id|capability_id}-group-{slug}[-{nested-slug}]."
1183
+ - name: name
1184
+ type: string
1185
+ nullable: false
1186
+ description: Display name from H2/H3 heading or authored.
1187
+ - name: product_id
1188
+ type: string
1189
+ nullable: true
1190
+ description: Owning product (when group is product-scoped).
1191
+ - name: capability_id
1192
+ type: string
1193
+ nullable: true
1194
+ description: Owning capability (when group is capability-scoped).
1195
+ - name: parent_group_id
1196
+ type: string
1197
+ nullable: true
1198
+ description: Self-reference for nested groups (H3 within H2).
1199
+ - name: description
1200
+ type: string
1201
+ nullable: true
1202
+ description: Authored description (when group has explicit metadata) or null when derived from heading only.
1203
+ - name: source
1204
+ type: string
1205
+ nullable: false
1206
+ description: feature-tree-h2 | feature-tree-h3 | feature-spec-explicit (when an authored feature spec declares group membership) | capability-spec-explicit.
1207
+ - name: source_sdd_id
1208
+ type: string
1209
+ nullable: true
1210
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
1211
+ - name: platform_sdd_id
1212
+ type: string
1213
+ nullable: true
1214
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1215
+ description: |
1216
+ Hierarchical grouping for features. First-class entity per resolution of adopt-canonical-catalogue-builder.md §7.2 — replaces the previous reverse-only synthetic `feature-tree-group` rows in features.csv. Both forward and reverse can use feature_groups: forward application-product SDDs whose `feature-tree.md` has H2/H3 structure, reverse SDDs whose extracted feature trees are inherently hierarchical, and any SDD that promotes groups to first-class with authored metadata. Groups can nest via `parent_group_id`.
1217
+ foreign_keys:
1218
+ - column: product_id
1219
+ references: products.id
1220
+ nullable: true
1221
+ - column: capability_id
1222
+ references: capabilities.id
1223
+ nullable: true
1224
+ - column: parent_group_id
1225
+ references: feature_groups.id
1226
+ nullable: true
1227
+ features:
1228
+ primary_key: id
1229
+ columns:
1230
+ - name: id
1231
+ type: string
1232
+ nullable: false
1233
+ description: "{product_id|capability_id}-{feature-slug}."
1234
+ - name: name
1235
+ type: string
1236
+ nullable: false
1237
+ - name: product_id
1238
+ type: string
1239
+ nullable: true
1240
+ description: Owning product (null for capability-spec-sourced features).
1241
+ - name: capability_id
1242
+ type: string
1243
+ nullable: true
1244
+ - name: parent_group_id
1245
+ type: string
1246
+ nullable: true
1247
+ description: Owning feature_group (typical when feature comes from a hierarchical feature-tree.md). Use this OR parent_feature_id, not both.
1248
+ - name: parent_feature_id
1249
+ type: string
1250
+ nullable: true
1251
+ description: Self-reference for explicit feature nesting (rare — most hierarchies are group-based via parent_group_id).
1252
+ - name: description
1253
+ type: string
1254
+ nullable: true
1255
+ - name: maturity
1256
+ type: string
1257
+ nullable: true
1258
+ description: "Standard: working | provisional | unknown | absent. Ecosystem-specific values may be added with parser awareness."
1259
+ - name: status
1260
+ type: string
1261
+ nullable: false
1262
+ description: Default 'active'.
1263
+ - name: source
1264
+ type: string
1265
+ nullable: false
1266
+ description: "feature-tree | feature-set | capability-spec | feature-spec | feature-grounding. NOTE: feature-tree-group source removed in 1.3.0 — groups are now first-class in feature_groups.csv. As of schema 2.2.0, source: feature-tree is emitted by the canonical builder for rows derived from feature-tree.md bullets. As of schema 2.5.0, source: feature-grounding is emitted for rows derived from `docs/domains/<dom>/design/<capability>/feature-grounding.md` markdown tables (per M-ADR 0143). As of schema 2.7.0, source: capability-spec is emitted by the canonical builder for rows derived from `## Feature Grounding (code-path trace)` tables in `docs/domains/<dom>/product/<capability>.md` capability spec markdown (per M-ADR 0145). Feature-grounding and capability-spec rows are both capability-owned: product_id is empty; capability_id resolves from the file path."
1267
+ - name: runway
1268
+ type: string
1269
+ nullable: true
1270
+ description: Optional adopter-owned lifecycle / migration marker. Free string at method level — the schema declares no enum and ships no controlled vocabulary. Adopters MAY declare a per-SDD `feature-runway-vocabulary.yaml` at their SDD root; when present, the canonical builder validates captured values against it and emits a `convention` finding for unknown values. Empty when the adopter does not track migration state. Comparability across SDDs requires ecosystem-level vocabulary alignment as an explicit pre-step. Added in schema 2.2.0.
1271
+ - name: source_sdd_id
1272
+ type: string
1273
+ nullable: true
1274
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
1275
+ - name: platform_sdd_id
1276
+ type: string
1277
+ nullable: true
1278
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1279
+ foreign_keys:
1280
+ - column: product_id
1281
+ references: products.id
1282
+ nullable: true
1283
+ - column: capability_id
1284
+ references: capabilities.id
1285
+ nullable: true
1286
+ - column: parent_group_id
1287
+ references: feature_groups.id
1288
+ nullable: true
1289
+ - column: parent_feature_id
1290
+ references: features.id
1291
+ nullable: true
1292
+ column_enums:
1293
+ source: enums.feature_source
1294
+ maturity: enums.artefact_maturity
1295
+ personas:
1296
+ primary_key: id
1297
+ columns:
1298
+ - name: id
1299
+ type: string
1300
+ nullable: false
1301
+ description: "{product_id}-{persona-slug}."
1302
+ - name: name
1303
+ type: string
1304
+ nullable: false
1305
+ - name: product_id
1306
+ type: string
1307
+ nullable: false
1308
+ - name: role
1309
+ type: string
1310
+ nullable: true
1311
+ - name: description
1312
+ type: string
1313
+ nullable: true
1314
+ - name: source_sdd_id
1315
+ type: string
1316
+ nullable: true
1317
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
1318
+ - name: platform_sdd_id
1319
+ type: string
1320
+ nullable: true
1321
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1322
+ foreign_keys:
1323
+ - column: product_id
1324
+ references: products.id
1325
+ nullable: false
1326
+ user_journeys:
1327
+ primary_key: id
1328
+ columns:
1329
+ - name: id
1330
+ type: string
1331
+ nullable: false
1332
+ description: "{product_id}-{journey-slug}."
1333
+ - name: name
1334
+ type: string
1335
+ nullable: false
1336
+ - name: product_id
1337
+ type: string
1338
+ nullable: false
1339
+ - name: primary_persona
1340
+ type: string
1341
+ nullable: true
1342
+ description: Free-text. Supports 'X → Y (handoff)'.
1343
+ - name: supporting_personas
1344
+ type: string
1345
+ nullable: true
1346
+ - name: trigger
1347
+ type: string
1348
+ nullable: true
1349
+ - name: goal
1350
+ type: string
1351
+ nullable: true
1352
+ - name: source_sdd_id
1353
+ type: string
1354
+ nullable: true
1355
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
1356
+ - name: platform_sdd_id
1357
+ type: string
1358
+ nullable: true
1359
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1360
+ foreign_keys:
1361
+ - column: product_id
1362
+ references: products.id
1363
+ nullable: false
1364
+ contracts:
1365
+ primary_key: id
1366
+ columns:
1367
+ - name: id
1368
+ type: string
1369
+ nullable: false
1370
+ description: "{domain}-{stem}-{kind} — the kind component joined the id at schema 3.0.0 (M-ADR 0203 §4.4), ending the kindless collision class where one service published as two contract families (openapi + proto) minted one id (measured cost: 1 row + 2 edges permanently unrepresentable, plus legitimate shared-contract citation flagged as divergence). Mechanical migration: new id = old id + '-' + kind; `sdd-cli catalogue migration-map` emits the pairs, and authored alias targets (M-ADR 0147) re-key automatically during the cut window."
1371
+ - name: name
1372
+ type: string
1373
+ nullable: false
1374
+ description: Display name from info.title or artifact_id.
1375
+ - name: service_id
1376
+ type: string
1377
+ nullable: true
1378
+ description: Exposing service; resolved via primary_repo_id ↔ OpenAPI x-source-repo.
1379
+ - name: source_repo_id
1380
+ type: string
1381
+ nullable: true
1382
+ description: Repo owning the contract source. Distinct from exposing service's repo per M-ADR 0110 (sibling-repo pattern).
1383
+ - name: kind
1384
+ type: string
1385
+ nullable: false
1386
+ description: rest | graphql | rpc | event | authz. rpc covers Proto/gRPC; event covers Avro schemas; authz covers authorization/policy schemas (SpiceDB .zed and equivalents), added because an adopter contract lock-in gate certified .zed schemas as contracts while no kind could represent them.
1387
+ - name: version
1388
+ type: string
1389
+ nullable: true
1390
+ - name: status
1391
+ type: string
1392
+ nullable: false
1393
+ description: active | deprecated. Default 'active'. As of 2.22.0 the builder wires 'deprecated' from BASELINE.md deprecation-runway entries (contracts.{openapi|proto|avro}[].status, matched on path == spec_path; per M-ADR 0073 §4.8) when a BASELINE.md exists at the SDD root.
1394
+ - name: spec_path
1395
+ type: string
1396
+ nullable: true
1397
+ - name: visibility
1398
+ type: string
1399
+ nullable: true
1400
+ description: public | private | internal.
1401
+ - name: context
1402
+ type: string
1403
+ nullable: true
1404
+ description: Bounded-context membership from OpenAPI `info.x-context` (per M-ADR 0170 §4.6). Free-form adopter label, orthogonal to the contract's domain folder. Not an FK. Empty when untagged. Added in schema 2.19.0.
1405
+ - name: evidence_class
1406
+ type: string
1407
+ nullable: true
1408
+ description: Evidence class of the contract surface, from OpenAPI `info.x-evidence-class` (document root accepted as fallback, exactly like x-context). Free-form; conventional values code-reverse | vendor-doc | operational (M-ADR 0175). Empty when untagged. Added in schema 2.20.0.
1409
+ - name: description
1410
+ type: string
1411
+ nullable: true
1412
+ - name: discovery
1413
+ type: string
1414
+ nullable: true
1415
+ description: discovered | declared-external. `discovered` (default) means the builder walked the spec file and parsed it, so title/version/context/evidence_class are trustworthy. `declared-external` means the row exists ONLY because a capability traceability manifest declared it with an explicit external marker and the file was never read — so those columns are necessarily EMPTY and their emptiness carries no information. A consumer that cannot tell the two apart will treat a declaration as a validated contract. Added in schema 2.51.0 (D13).
1416
+ - name: source_sdd_id
1417
+ type: string
1418
+ nullable: true
1419
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
1420
+ - name: platform_sdd_id
1421
+ type: string
1422
+ nullable: true
1423
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1424
+ foreign_keys:
1425
+ - column: service_id
1426
+ references: services.id
1427
+ nullable: true
1428
+ - column: source_repo_id
1429
+ references: repositories.id
1430
+ nullable: true
1431
+ column_enums:
1432
+ kind: enums.contract_kind
1433
+ status: enums.contract_status
1434
+ visibility: enums.contract_visibility
1435
+ discovery: enums.contract_discovery
1436
+ events:
1437
+ primary_key: id
1438
+ columns:
1439
+ - name: id
1440
+ type: string
1441
+ nullable: false
1442
+ - name: name
1443
+ type: string
1444
+ nullable: false
1445
+ - name: publisher_service_id
1446
+ type: string
1447
+ nullable: true
1448
+ - name: domain_id
1449
+ type: string
1450
+ nullable: true
1451
+ - name: transport
1452
+ type: string
1453
+ nullable: true
1454
+ description: "Open string per M-ADR 0156. Recommended values: kafka | sns | sqs | kinesis | eventbridge | mongodb-change-stream | nats | activemq | rabbitmq | jms | other. Values outside the recommended set emit [finding] convention."
1455
+ - name: schema_path
1456
+ type: string
1457
+ nullable: true
1458
+ description: "Path to event schema (Avro .avsc or JSON-Schema .json/.schema.json). Nullable — leave empty for loosely-typed events (e.g. ActiveMQ JMS, NATS with payload_schema: {type: object}). Per M-ADR 0156."
1459
+ - name: version
1460
+ type: string
1461
+ nullable: true
1462
+ - name: evidence_class
1463
+ type: string
1464
+ nullable: true
1465
+ description: Evidence class of the event claim, from the per-event `evidence_class` key (alias `evidence-class`) in event-catalog.yaml, falling back to a file-level `evidence_class`/`evidence-class` top-level key in the same catalog YAML. Free-form; conventional values code-reverse | vendor-doc | operational (M-ADR 0175). Empty for avsc-only events and when undeclared. Added in schema 2.20.0.
1466
+ - name: source_sdd_id
1467
+ type: string
1468
+ nullable: true
1469
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
1470
+ - name: platform_sdd_id
1471
+ type: string
1472
+ nullable: true
1473
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1474
+ description: "Asynchronous messages. Cross-domain events (e.g. shared envelopes) leave domain_id empty. Per M-ADR 0156 (multi-source ingestion, schema 2.12.0): forward-method canonical source is `contracts/avro/*.avsc` files; reverse-method canonical source is `docs/domains/{domain}/contracts/events/event-catalog.yaml`. YAML wins on name/domain/publisher/transport/consumers; avsc augments schema_path/version. Both paths run and merge by id slug."
1475
+ foreign_keys:
1476
+ - column: publisher_service_id
1477
+ references: services.id
1478
+ nullable: true
1479
+ - column: domain_id
1480
+ references: domains.id
1481
+ nullable: true
1482
+ c4_systems:
1483
+ primary_key: id
1484
+ columns:
1485
+ - name: id
1486
+ type: string
1487
+ nullable: false
1488
+ description: Typically {product_id}-system.
1489
+ - name: name
1490
+ type: string
1491
+ nullable: false
1492
+ - name: product_id
1493
+ type: string
1494
+ nullable: true
1495
+ description: "Owning product, when the system corresponds to one. Nullable: every product is a system, but not every system is a product (external/SaaS systems have no owning product). Architectural products only (per category taxonomy). Relaxed to nullable in schema 2.11.0."
1496
+ - name: kind
1497
+ type: string
1498
+ nullable: false
1499
+ description: platform | subsystem | application | integration. Derived 1:1 from manifest.category — see enums.c4_system_kind.
1500
+ - name: diagram_path
1501
+ type: string
1502
+ nullable: true
1503
+ description: Path to L1 mermaid/markdown. Nullable — row exists for any architectural Product even if no L1 diagram has been authored yet (visible coverage gap).
1504
+ - name: description
1505
+ type: string
1506
+ nullable: true
1507
+ - name: source_sdd_id
1508
+ type: string
1509
+ nullable: true
1510
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
1511
+ - name: platform_sdd_id
1512
+ type: string
1513
+ nullable: true
1514
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1515
+ foreign_keys:
1516
+ - column: product_id
1517
+ references: products.id
1518
+ nullable: true
1519
+ column_enums:
1520
+ kind: enums.c4_system_kind
1521
+ c4_containers:
1522
+ primary_key: id
1523
+ columns:
1524
+ - name: id
1525
+ type: string
1526
+ nullable: false
1527
+ description: "{system_id}-{container-slug}."
1528
+ - name: name
1529
+ type: string
1530
+ nullable: false
1531
+ - name: system_id
1532
+ type: string
1533
+ nullable: false
1534
+ description: Owning C4 system (every container is in exactly one system).
1535
+ - name: domain_id
1536
+ type: string
1537
+ nullable: true
1538
+ description: Optional organisational domain tag (denormalised; not C4-structural).
1539
+ - name: service_id
1540
+ type: string
1541
+ nullable: true
1542
+ description: Matched by container name ↔ service name/repo where possible.
1543
+ - name: type
1544
+ type: string
1545
+ nullable: true
1546
+ description: "Canonical C4 container kind — bound to enums.c4_container_type (Application | Data Store) since 3.0.0, hard-fail (M-ADR 0203 §4.1 completing M-ADR 0155). The 2.x legacy values are removed: External System boxes belong in c4_external_systems; running infrastructure retypes; deployment infrastructure leaves the catalogue."
1547
+ - name: technology
1548
+ type: string
1549
+ nullable: true
1550
+ - name: description
1551
+ type: string
1552
+ nullable: true
1553
+ - name: source_sdd_id
1554
+ type: string
1555
+ nullable: true
1556
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
1557
+ - name: platform_sdd_id
1558
+ type: string
1559
+ nullable: true
1560
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1561
+ description: |
1562
+ C4 L2. Each container belongs to exactly one C4 system. `domain_id` is a denormalised organisational tag, not a C4-structural attribute — multi-domain ecosystems use it for filtering/reporting. `service_id` is the optional "may represent" link to a runtime service when the container is a deployable application.
1563
+ foreign_keys:
1564
+ - column: system_id
1565
+ references: c4_systems.id
1566
+ nullable: false
1567
+ - column: domain_id
1568
+ references: domains.id
1569
+ nullable: true
1570
+ - column: service_id
1571
+ references: services.id
1572
+ nullable: true
1573
+ column_enums:
1574
+ type: enums.c4_container_type
1575
+ c4_components:
1576
+ primary_key: id
1577
+ columns:
1578
+ - name: id
1579
+ type: string
1580
+ nullable: false
1581
+ description: "{container_id}-{component-slug}."
1582
+ - name: name
1583
+ type: string
1584
+ nullable: false
1585
+ - name: container_id
1586
+ type: string
1587
+ nullable: false
1588
+ description: Owning C4 container.
1589
+ - name: service_id
1590
+ type: string
1591
+ nullable: true
1592
+ description: "Denormalised: the service the parent container represents, when applicable."
1593
+ - name: path
1594
+ type: string
1595
+ nullable: true
1596
+ - name: responsibility
1597
+ type: string
1598
+ nullable: true
1599
+ - name: source_sdd_id
1600
+ type: string
1601
+ nullable: true
1602
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
1603
+ - name: platform_sdd_id
1604
+ type: string
1605
+ nullable: true
1606
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1607
+ description: |
1608
+ C4 L3. Each component belongs to exactly one C4 container. `service_id` is denormalised from `c4_containers.service_id` for query convenience — populated when the parent container represents a runtime service.
1609
+ foreign_keys:
1610
+ - column: container_id
1611
+ references: c4_containers.id
1612
+ nullable: false
1613
+ - column: service_id
1614
+ references: services.id
1615
+ nullable: true
1616
+ c4_external_systems:
1617
+ primary_key: id
1618
+ columns:
1619
+ - name: id
1620
+ type: string
1621
+ nullable: false
1622
+ description: ext-{slug(diagram entry id)} — derived from the DECLARED identity (the first argument of System_Ext/Container_Ext), not from the display name, since 3.0.0 (M-ADR 0203 §4.2 completing M-ADR 0189 §4.2). The 2.x name-slug ids map to these mechanically; `sdd-cli catalogue migration-map` emits the old→new map, and authored exemption files keyed by a mapped old id re-key automatically during the cut window (regenerable, not drift).
1623
+ - name: name
1624
+ type: string
1625
+ nullable: false
1626
+ description: Display name from the System_Ext label.
1627
+ - name: technology
1628
+ type: string
1629
+ nullable: true
1630
+ description: Optional stack/protocol hint.
1631
+ - name: description
1632
+ type: string
1633
+ nullable: true
1634
+ description: What the external system provides.
1635
+ - name: declared_id
1636
+ type: string
1637
+ nullable: true
1638
+ description: The diagram entry id of the first-seen declaration (M-ADR 0189 §4.2) — the declared identity the aggregator resolves against estate identifiers at adjudication, and the source of the row id since 3.0.0. Added 2.30.0.
1639
+ - name: source_scope
1640
+ type: string
1641
+ nullable: true
1642
+ description: "Scope of the first-seen declaration: l1 (context diagram) or l2 (container diagram — scope-relative per M-ADR 0189 §4.1). Added 2.30.0."
1643
+ - name: source_sdd_id
1644
+ type: string
1645
+ nullable: true
1646
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
1647
+ - name: platform_sdd_id
1648
+ type: string
1649
+ nullable: true
1650
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1651
+ description: |
1652
+ C4 external software systems — peer systems at the L1 context level that the ecosystem integrates with but does not own (per M-ADR 0155). Rendered `System_Ext(...)` on L1/L2 diagrams. NOT a c4_container (external systems are not inside your system) and NOT a c4_system (they have no owning Product). External systems are inherently shared references: the same external system may be declared by multiple SDDs, so the aggregator dedups identical rows by PK rather than failing on duplicate (the one narrowly-scoped exception to M-ADR 0134's duplicate-PK rule); conflicting attributes on the same id surface as a `convention` finding.
1653
+ repositories:
1654
+ primary_key: id
1655
+ columns:
1656
+ - name: id
1657
+ type: string
1658
+ nullable: false
1659
+ description: canonical_repo_key.
1660
+ - name: name
1661
+ type: string
1662
+ nullable: false
1663
+ - name: domain_id
1664
+ type: string
1665
+ nullable: true
1666
+ description: Owning capability domain. Populated when the repo-config declared domain resolves to a docs/domains/<slug>/ in the local SDD; left empty otherwise per M-ADR 0136.
1667
+ - name: product_id
1668
+ type: string
1669
+ nullable: true
1670
+ - name: profile
1671
+ type: string
1672
+ nullable: false
1673
+ - name: group
1674
+ type: string
1675
+ nullable: true
1676
+ - name: category
1677
+ type: string
1678
+ nullable: true
1679
+ - name: tier
1680
+ type: string
1681
+ nullable: true
1682
+ description: S1..S4 for support repos, else null.
1683
+ - name: component_type
1684
+ type: string
1685
+ nullable: true
1686
+ - name: files
1687
+ type: int
1688
+ nullable: true
1689
+ - name: code
1690
+ type: int
1691
+ nullable: true
1692
+ - name: comment
1693
+ type: int
1694
+ nullable: true
1695
+ - name: blank
1696
+ type: int
1697
+ nullable: true
1698
+ - name: total_lines
1699
+ type: int
1700
+ nullable: true
1701
+ - name: languages
1702
+ type: string
1703
+ nullable: true
1704
+ description: "';'-separated."
1705
+ - name: doc_path
1706
+ type: string
1707
+ nullable: false
1708
+ - name: source_sdd_id
1709
+ type: string
1710
+ nullable: true
1711
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
1712
+ - name: platform_sdd_id
1713
+ type: string
1714
+ nullable: true
1715
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1716
+ foreign_keys:
1717
+ - column: domain_id
1718
+ references: domains.id
1719
+ nullable: true
1720
+ - column: product_id
1721
+ references: products.id
1722
+ nullable: true
1723
+ column_enums:
1724
+ component_type: enums.service_type
1725
+ domain_models:
1726
+ primary_key: id
1727
+ columns:
1728
+ - name: id
1729
+ type: string
1730
+ nullable: false
1731
+ description: "{domain_id}-data-model."
1732
+ - name: name
1733
+ type: string
1734
+ nullable: false
1735
+ - name: domain_id
1736
+ type: string
1737
+ nullable: false
1738
+ - name: doc_path
1739
+ type: string
1740
+ nullable: false
1741
+ description: Path to data-model.mermaid.md.
1742
+ - name: version
1743
+ type: string
1744
+ nullable: true
1745
+ description: Optional explicit version; null until the domain model is formally versioned (typically at first contract lock-in).
1746
+ - name: evidence_class
1747
+ type: string
1748
+ nullable: true
1749
+ description: Evidence class of the domain model, from a leading ```yaml fence in the data-model markdown carrying `evidence-class:` (documentation-reverse anchor convention). Free-form; conventional values code-reverse | vendor-doc | operational (M-ADR 0175). Empty when undeclared. Added in schema 2.20.0.
1750
+ - name: source_sdd_id
1751
+ type: string
1752
+ nullable: true
1753
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
1754
+ - name: platform_sdd_id
1755
+ type: string
1756
+ nullable: true
1757
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1758
+ - name: notation
1759
+ type: string
1760
+ nullable: true
1761
+ description: "The notation the model artefact is written in — one of enums.model_notation (mermaid-erd | typeql), DERIVED by the builder from the file (data-model.mermaid.md → mermaid-erd; data-model.tql → typeql), never authored. The compliance instrument of M-ADR 0210 §4.6 Decision 2 (as amended): a mermaid-erd row is advisory until the sunset 2027-03-31 and an error after it. Added in 3.11.0."
1762
+ description: "Per-domain ER diagram modelling the domain's aggregates, entities, and domain events. Platform-profile only — application and integration profiles emit headers-only. Forward source: `traceability.domain_model.path` in capability traceability manifests. Reverse source: file-system scan of `docs/domains/*/architecture/data-model.mermaid.md`. Added in schema 2.4.0; see M-ADR 0142."
1763
+ foreign_keys:
1764
+ - column: domain_id
1765
+ references: domains.id
1766
+ nullable: false
1767
+ column_enums:
1768
+ notation: enums.model_notation
1769
+ entities:
1770
+ primary_key: id
1771
+ columns:
1772
+ - name: id
1773
+ type: string
1774
+ nullable: false
1775
+ description: "Slugged PK: {domain_id}-{entitySlug(name)}. For manifest-sourced rows with domain=platform-wide, the leading domain segment is empty (`-{entitySlug(name)}`) and the row carries a [finding] convention."
1776
+ - name: name
1777
+ type: string
1778
+ nullable: false
1779
+ description: Entity name as authored. Preserves the original case/style (UPPER_SNAKE_CASE, PascalCase, lowercase camelCase all observed in the wild).
1780
+ - name: domain_id
1781
+ type: string
1782
+ nullable: true
1783
+ description: Owning domain. Nullable when the source is a non-canonical domain hint such as `platform-wide`; the walker emits a finding in that case.
1784
+ - name: source_domain_model_id
1785
+ type: string
1786
+ nullable: true
1787
+ description: FK to domain_models.csv — the file the entity was extracted from. Populated by the reverse-method walker (Mermaid parse); empty when authored only via the forward-method manifest.
1788
+ - name: persistence_kind
1789
+ type: string
1790
+ nullable: true
1791
+ description: "Open string; recommended values: relational-table | document-collection | event-payload | dto | view | other. Values outside the recommended set fire `[finding] convention`."
1792
+ - name: context
1793
+ type: string
1794
+ nullable: true
1795
+ description: Bounded-context membership (per M-ADR 0170 §4.6). Free-form adopter label, orthogonal to domain_id. Not an FK. Carried for forward-parity; awaits a derivation source (Mermaid ER has no per-entity slot — populate via a sidecar classification or owning-service derivation). Added in schema 2.19.0.
1796
+ - name: glossary_term
1797
+ type: string
1798
+ nullable: true
1799
+ description: FK to glossary_items.id when the entity name resolves to a canonical glossary term (by entity-aware slug). Drives entity_glossary edge emission.
1800
+ - name: notes
1801
+ type: string
1802
+ nullable: true
1803
+ description: Free-form notes preserved from the authoring source. Carries `status=...`, `superseded_by=...`, and column count for diagnostic value.
1804
+ - name: evidence_class
1805
+ type: string
1806
+ nullable: true
1807
+ description: Evidence class inherited from the owning domain model's file-level declaration (the leading ```yaml fence's `evidence-class:` in data-model markdown). Free-form; conventional values code-reverse | vendor-doc | operational (M-ADR 0175). Empty when the source file declares none, and for manifest-sourced rows (the glossary-alignment manifest has no evidence slot). Added in schema 2.20.0.
1808
+ - name: source_sdd_id
1809
+ type: string
1810
+ nullable: true
1811
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
1812
+ - name: platform_sdd_id
1813
+ type: string
1814
+ nullable: true
1815
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
1816
+ description: "Data-model entity (a structural realisation of a concept inside a domain's data model). Distinct from glossary_items (vocabulary-level) and from domain_models (file-level). Added in schema 2.13.0 per M-ADR 0159. Forward source: `models[].entities[]` in glossary-alignment-manifest.yaml. Reverse source: `EntityName { ... }` declarations inside `erDiagram` fences in `docs/domains/{domain}/architecture/data-model.mermaid.md`. PK uses an entity-aware slug that normalises across UPPER_SNAKE and PascalCase authoring styles."
1817
+ foreign_keys:
1818
+ - column: domain_id
1819
+ references: domains.id
1820
+ nullable: true
1821
+ - column: source_domain_model_id
1822
+ references: domain_models.id
1823
+ nullable: true
1824
+ - column: glossary_term
1825
+ references: glossary_items.id
1826
+ nullable: true
1827
+ column_enums:
1828
+ persistence_kind: enums.persistence_kind
1829
+ repo_capability:
1830
+ primary_key: id
1831
+ columns:
1832
+ - name: id
1833
+ type: string
1834
+ nullable: false
1835
+ - name: repo_id
1836
+ type: string
1837
+ nullable: false
1838
+ - name: capability_id
1839
+ type: string
1840
+ nullable: false
1841
+ description: "Edge: repo contributes to capability. Forward-declared via repo-config `capabilities[]` (M-ADR 0188 §6.1) or the legacy multi-purpose `additional_context[]`; reverse-derived via capability_service ⋈ services.primary_repo_id and capability_feature ⋈ feature_repo."
1842
+ foreign_keys:
1843
+ - column: repo_id
1844
+ references: repositories.id
1845
+ nullable: false
1846
+ - column: capability_id
1847
+ references: capabilities.id
1848
+ nullable: false
1849
+ repo_capability_exemption:
1850
+ primary_key: id
1851
+ columns:
1852
+ - name: id
1853
+ type: string
1854
+ nullable: false
1855
+ - name: repo_id
1856
+ type: string
1857
+ nullable: false
1858
+ - name: reason
1859
+ type: string
1860
+ nullable: false
1861
+ - name: note
1862
+ type: string
1863
+ nullable: false
1864
+ description: Mandatory, non-empty. The reason code makes exemptions countable; the note makes them reviewable. A row with an empty note is dropped with a `convention` finding.
1865
+ description: |
1866
+ A repository's declared, reasoned statement that it bears no product capability (M-ADR 0188 §4.3). Emitted from the repo-config `capability_exemption:` block.
1867
+ This is deliberately a catalogue row rather than an inert YAML aside. An exemption is a modelling assertion and belongs in the model: it is then queryable at the aggregate tier, reviewable in the same surface as the capabilities it stands in for, and countable — so that a reviewer watching the exemption population grow can see it happen. Never net exemptions off against orphans in a metric.
1868
+ The invariant it participates in (M-ADR 0188 §4.1): every `repositories` row must resolve, either by carrying a `repo_capability` edge or by declaring an exemption here. A row satisfying both is a declaration conflict, reported as a `divergence` finding.
1869
+ foreign_keys:
1870
+ - column: repo_id
1871
+ references: repositories.id
1872
+ nullable: false
1873
+ column_enums:
1874
+ reason: enums.capability_exemption_reason
1875
+ service_capability_exemption:
1876
+ primary_key: id
1877
+ columns:
1878
+ - name: id
1879
+ type: string
1880
+ nullable: false
1881
+ - name: service_id
1882
+ type: string
1883
+ nullable: false
1884
+ - name: reason
1885
+ type: string
1886
+ nullable: false
1887
+ - name: note
1888
+ type: string
1889
+ nullable: false
1890
+ description: Mandatory, non-empty. The reason code makes exemptions countable; the note makes them reviewable. A row with an empty note is dropped with a `convention` finding.
1891
+ description: |
1892
+ A service's declared, reasoned statement that it bears no product capability (M-ADR 0133 §4.2b). The services-tier equivalent of `repo_capability_exemption`, one tier down: `repo_capability_exemption` exists because M-ADR 0197 gave a repository a `services:` block, so a repository resolving under M-ADR 0188 no longer implies its services do. Emitted from the repo-config `service_capability_exemption:` block, keyed to the repo's own default/primary service id — a declared, non-primary `services:` entry has no per-entry authoring surface yet (M-ADR 0197 §4.7, design-only) and cannot be exempted through this block.
1893
+ Two reasons only (`enums.service_capability_exemption_reason`): `platform-internal` and `deprecated`. Narrower than the repository vocabulary by design — a service, by definition, already runs something, so the repository-tier packaging/tooling/provenance distinctions don't reproduce here.
1894
+ The invariant it participates in: every catalogued `services` row must resolve, either by carrying a `capability_service` edge or by declaring an exemption here — checked by a coverage predicate whose verdict set is tier-scoped (member tier cannot assert an unclaimed service is genuinely orphaned, only that it is unresolved locally; a cross-SDD claim on the service may exist in a sibling SDD's own capability_service.csv, invisible to this SDD's own build).
1895
+ foreign_keys:
1896
+ - column: service_id
1897
+ references: services.id
1898
+ nullable: false
1899
+ column_enums:
1900
+ reason: enums.service_capability_exemption_reason
1901
+ external_system_exemption:
1902
+ primary_key: id
1903
+ columns:
1904
+ - name: id
1905
+ type: string
1906
+ nullable: false
1907
+ description: Equals external_system_id (one assertion per candidate).
1908
+ - name: external_system_id
1909
+ type: string
1910
+ nullable: false
1911
+ - name: reason
1912
+ type: string
1913
+ nullable: false
1914
+ - name: note
1915
+ type: string
1916
+ nullable: false
1917
+ description: Mandatory, non-empty. The reason makes exemptions countable; the note makes them reviewable (M-ADR 0188 §4.2 pattern).
1918
+ description: |
1919
+ A declared, reasoned assertion that an external-system candidate is GENUINELY external (M-ADR 0189 §4.6 / WS15). Annotation catalogue (M-ADR 0133 §4.2b): one FK, declared never derived, closed reason enum. Sourced from `orchestration/external-system-exemptions.yaml`.
1920
+ The invariant it completes: c4_external_systems was the one catalogue family with no coverage predicate — a candidate producing no adjudication outcome was silent, and that silence hid a 28% dependency -graph distortion (ledger L4). Every candidate now either resolves at adjudication, or carries an exemption here, or is reported unverified. An exemption retires only the unverified finding — never an adjudication outcome (a converted candidate's exemption is a contradiction, reported and dropped). Shared entities may be exempted by multiple SDDs: identical rows dedup at aggregation (same exception class as c4_external_systems); conflicting rows keep first-seen with a convention finding.
1921
+ foreign_keys:
1922
+ - column: external_system_id
1923
+ references: c4_external_systems.id
1924
+ nullable: false
1925
+ column_enums:
1926
+ reason: enums.external_system_exemption_reason
1927
+ repo_contract:
1928
+ primary_key: id
1929
+ columns:
1930
+ - name: id
1931
+ type: string
1932
+ nullable: false
1933
+ - name: repo_id
1934
+ type: string
1935
+ nullable: false
1936
+ - name: contract_id
1937
+ type: string
1938
+ nullable: false
1939
+ description: "Edge: repo is bound to a contract — implements or consumes; the source (contributes_to.artifact_type=contract-surface) does not distinguish, so this description asserts no direction (M-ADR 0211 §1). From contributes_to.artifact_type=contract-surface. Per M-ADR 0147 service-architecture external interfaces are a contract-consumes source; contract_id is external_for_profiles app/integration because their repos reference platform-resident (or platform-held BFF) contracts — resolved at aggregation, staying internal for platform-profile."
1940
+ foreign_keys:
1941
+ - column: repo_id
1942
+ references: repositories.id
1943
+ nullable: false
1944
+ - column: contract_id
1945
+ references: contracts.id
1946
+ nullable: false
1947
+ external_for_profiles:
1948
+ - application-product
1949
+ - integration-product
1950
+ product_capability:
1951
+ primary_key: id
1952
+ columns:
1953
+ - name: id
1954
+ type: string
1955
+ nullable: false
1956
+ - name: product_id
1957
+ type: string
1958
+ nullable: false
1959
+ - name: capability_id
1960
+ type: string
1961
+ nullable: false
1962
+ - name: role
1963
+ type: string
1964
+ nullable: false
1965
+ description: consumes.
1966
+ - name: notes
1967
+ type: string
1968
+ nullable: true
1969
+ description: "Edge: product depends on / consumes capability. Forward sources from app-platform-dependencies.yaml. capability_id is external because the consuming product (an application-product SDD) references a capability owned by the platform SDD."
1970
+ foreign_keys:
1971
+ - column: product_id
1972
+ references: products.id
1973
+ nullable: false
1974
+ - column: capability_id
1975
+ references: capabilities.id
1976
+ nullable: false
1977
+ external: true
1978
+ column_enums:
1979
+ role: enums.consumption_role
1980
+ product_service:
1981
+ primary_key: id
1982
+ columns:
1983
+ - name: id
1984
+ type: string
1985
+ nullable: false
1986
+ - name: product_id
1987
+ type: string
1988
+ nullable: false
1989
+ - name: service_id
1990
+ type: string
1991
+ nullable: false
1992
+ - name: role
1993
+ type: string
1994
+ nullable: false
1995
+ description: consumes.
1996
+ - name: required_stability
1997
+ type: string
1998
+ nullable: true
1999
+ description: "provisional | locked | unknown. The consuming SDD's expectation of contract stability, carried verbatim from app-platform-dependencies.yaml. Not a bound enum: an out-of-vocabulary value is carried, not rejected, and is reported by validate-app-dependencies.sh."
2000
+ description: "Edge: product depends on / consumes service. Forward sources from app-platform-dependencies.yaml. service_id is external because the consuming product (an application-product SDD) references a service owned by the platform SDD."
2001
+ foreign_keys:
2002
+ - column: product_id
2003
+ references: products.id
2004
+ nullable: false
2005
+ - column: service_id
2006
+ references: services.id
2007
+ nullable: false
2008
+ external: true
2009
+ column_enums:
2010
+ role: enums.consumption_role
2011
+ required_stability: enums.required_stability
2012
+ service_contract:
2013
+ primary_key: id
2014
+ columns:
2015
+ - name: id
2016
+ type: string
2017
+ nullable: false
2018
+ description: "{service_id}__{contract_id}__{role}."
2019
+ - name: service_id
2020
+ type: string
2021
+ nullable: false
2022
+ - name: contract_id
2023
+ type: string
2024
+ nullable: false
2025
+ - name: role
2026
+ type: string
2027
+ nullable: false
2028
+ description: exposes | consumes.
2029
+ description: "Edge: service exposes or consumes contract. Both FKs are external (per M-ADR 0147): federated SDDs that walk per-repo service-architecture tables emit consumes rows where service_id resolves to the platform-root catalogue's services.csv (post-aggregation) and contract_id resolves to the platform-root contracts.csv. Internal builds (e.g. connect-mono) still optimistically validate locally. Schema 2.8.0."
2030
+ foreign_keys:
2031
+ - column: service_id
2032
+ references: services.id
2033
+ nullable: false
2034
+ external: true
2035
+ - column: contract_id
2036
+ references: contracts.id
2037
+ nullable: false
2038
+ external: true
2039
+ column_enums:
2040
+ role: enums.contract_participation
2041
+ service_event:
2042
+ primary_key: id
2043
+ columns:
2044
+ - name: id
2045
+ type: string
2046
+ nullable: false
2047
+ description: "{service_id}__{event_id}__{role}."
2048
+ - name: service_id
2049
+ type: string
2050
+ nullable: false
2051
+ - name: event_id
2052
+ type: string
2053
+ nullable: false
2054
+ - name: role
2055
+ type: string
2056
+ nullable: false
2057
+ description: publishes | consumes.
2058
+ description: "Edge: service publishes or consumes event."
2059
+ foreign_keys:
2060
+ - column: service_id
2061
+ references: services.id
2062
+ nullable: false
2063
+ - column: event_id
2064
+ references: events.id
2065
+ nullable: false
2066
+ column_enums:
2067
+ role: enums.event_participation
2068
+ service_entity:
2069
+ primary_key: id
2070
+ columns:
2071
+ - name: id
2072
+ type: string
2073
+ nullable: false
2074
+ description: "Composite PK: {service_id}__{entity_id}__{relation}."
2075
+ - name: service_id
2076
+ type: string
2077
+ nullable: false
2078
+ - name: entity_id
2079
+ type: string
2080
+ nullable: false
2081
+ - name: relation
2082
+ type: string
2083
+ nullable: false
2084
+ description: "Open string; recommended values: owns | reads | writes | references. Data Store Mapping table source emits `owns`. Values outside the recommended set fire `[finding] convention`."
2085
+ - name: evidence_path
2086
+ type: string
2087
+ nullable: true
2088
+ description: Source markdown path or feature-grounding row that produced the edge. Audit aid.
2089
+ - name: source_sdd_id
2090
+ type: string
2091
+ nullable: true
2092
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
2093
+ - name: platform_sdd_id
2094
+ type: string
2095
+ nullable: true
2096
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2097
+ description: "Edge: service touches data-model entity. Added in schema 2.13.0 per M-ADR 0159. Primary source: per-domain `## Data Store Mapping` markdown table in `docs/domains/{domain}/architecture/data-model.mermaid.md` (relation=owns). Optional forward source (Phase 5 deferred): `entities:` block in `orchestration/repo-config/<repo>.yaml`. Service names resolve via heuristic (slug-of-name; trailing-id-segment) with optional adopter-authored alias map at `docs/platform/reference/service-name-aliases.yaml`."
2098
+ foreign_keys:
2099
+ - column: service_id
2100
+ references: services.id
2101
+ nullable: false
2102
+ - column: entity_id
2103
+ references: entities.id
2104
+ nullable: false
2105
+ column_enums:
2106
+ relation: enums.service_entity_relation
2107
+ capability_feature:
2108
+ primary_key: id
2109
+ columns:
2110
+ - name: id
2111
+ type: string
2112
+ nullable: false
2113
+ - name: capability_id
2114
+ type: string
2115
+ nullable: false
2116
+ - name: feature_id
2117
+ type: string
2118
+ nullable: false
2119
+ description: "Edge: capability decomposes into features. Forward: traceability.runway.enables. Reverse: parsed from spec Feature Grounding."
2120
+ foreign_keys:
2121
+ - column: capability_id
2122
+ references: capabilities.id
2123
+ nullable: false
2124
+ - column: feature_id
2125
+ references: features.id
2126
+ nullable: false
2127
+ capability_service:
2128
+ primary_key: id
2129
+ columns:
2130
+ - name: id
2131
+ type: string
2132
+ nullable: false
2133
+ - name: capability_id
2134
+ type: string
2135
+ nullable: false
2136
+ - name: service_id
2137
+ type: string
2138
+ nullable: false
2139
+ - name: role
2140
+ type: string
2141
+ nullable: true
2142
+ description: "The part the service plays in delivering THIS capability — a property of the relationship, not of the service (capability-traceability-manifest-template). Closed enum, see enums.capability_service_role. Nullable: legacy rows may carry no role; the enum validator checks values, not presence. `dependency` rows are excluded from repo_capability Path X (M-ADR 0157 §4.3 as amended). Enum bound in 3.8.0."
2143
+ - name: contract_id
2144
+ type: string
2145
+ nullable: true
2146
+ description: "The contract this dependency is against — a contracts.id declared as `contract:` on the services[] entry (M-ADR 0211 §4.1). External FK on the pattern of feature_contract: resolved at aggregation. Empty when the entry declares none; a `dependency`-role entry that reaches T4 band 5 carries it."
2147
+ - name: interaction_pattern
2148
+ type: string
2149
+ nullable: true
2150
+ description: How the capability is coupled to the service at runtime — one of enums.interaction_pattern (M-ADR 0171 vocabulary, bound), from `interaction_pattern:` on the services[] entry. EMPTY for a non-runtime coupling (build-time, load-time, packaging, sequencing), whose kind the manifest states in dependency_notes; that entry is excluded by class from T4's dependency set and does not reach band 5.
2151
+ - name: qualifier
2152
+ type: string
2153
+ nullable: true
2154
+ description: Free-text qualifier on the interaction pattern per M-ADR 0171 §4.4 (e.g. idempotent, batched, cached, proxy, an auth scheme, a protocol version) — never a new pattern token. From `qualifier:` on the services[] entry.
2155
+ - name: evidence_ref
2156
+ type: string
2157
+ nullable: true
2158
+ description: Where the coupling is evidenced — a path or anchor in the SDD, from `evidence:` on the services[] entry. Prose about the coupling stays in dependency_notes; this is the pointer a reviewer follows.
2159
+ description: |
2160
+ Edge: capability is realised by services. Sourced from the capability traceability manifest services[] block. service_id is an external FK (schema 2.29.0, F4): a traceability entry marked `owner_sdd:` declares a cross-SDD reference (e.g. the service moved to a sibling SDD at an M-ADR 0170 §4.2 carve) — the per-SDD builder emits the edge, logs it `[finding] external`, and aggregation validates it hard against the owning sibling's rows. An UNMARKED id that does not resolve locally is NOT emitted — it stays a member-tier orphan finding (or convention, when it names a known external system).
2161
+ foreign_keys:
2162
+ - column: capability_id
2163
+ references: capabilities.id
2164
+ nullable: false
2165
+ - column: service_id
2166
+ references: services.id
2167
+ nullable: false
2168
+ external: true
2169
+ - column: contract_id
2170
+ references: contracts.id
2171
+ nullable: true
2172
+ external: true
2173
+ column_enums:
2174
+ role: enums.capability_service_role
2175
+ interaction_pattern: enums.interaction_pattern
2176
+ capability_event:
2177
+ primary_key: id
2178
+ columns:
2179
+ - name: id
2180
+ type: string
2181
+ nullable: false
2182
+ - name: capability_id
2183
+ type: string
2184
+ nullable: false
2185
+ - name: event_id
2186
+ type: string
2187
+ nullable: false
2188
+ - name: role
2189
+ type: string
2190
+ nullable: false
2191
+ description: publishes | consumes.
2192
+ - name: source
2193
+ type: string
2194
+ nullable: false
2195
+ description: authored | derived. `authored` rows come from a traceability declaration (shape A or shape B); `derived` rows come from `capability_service ⋈ service_event` and represent associative coupling, not ownership. Schema 2.14.0 per M-ADR 0160.
2196
+ description: "Edge: capability publishes or consumes event. Schema 2.14.0 (per M-ADR 0160) multi-source ingestion: (1) forward shape A — `traceability.events[{id, role}]` (legacy aspirational shape, unauthored across observed adopters); (2) forward shape B — `traceability.contracts.published_events[]` / `consumed_events[]` with `{event, status, notes}` (the observed forward-method shape; event name slug-resolves against events.csv); (3) derived — `capability_service ⋈ service_event` join (zero authoring; associative not authoritative). Authored rows win on PK conflict with derived. The `source` column distinguishes the two so governance queries can filter to authoritative ownership. The earlier `## Related Events` capability-spec heading is retired (no adopter authored it; the template never carried the section)."
2197
+ foreign_keys:
2198
+ - column: capability_id
2199
+ references: capabilities.id
2200
+ nullable: false
2201
+ - column: event_id
2202
+ references: events.id
2203
+ nullable: false
2204
+ column_enums:
2205
+ role: enums.event_participation
2206
+ source: enums.edge_source
2207
+ capability_contract:
2208
+ primary_key: id
2209
+ columns:
2210
+ - name: id
2211
+ type: string
2212
+ nullable: false
2213
+ - name: capability_id
2214
+ type: string
2215
+ nullable: false
2216
+ - name: contract_id
2217
+ type: string
2218
+ nullable: false
2219
+ - name: source
2220
+ type: string
2221
+ nullable: false
2222
+ description: "declared — the only emitted value. `derived` is reserved vocabulary: the reverse derivation it anticipated was never built (0 rows across 105 measured units) and the claim was corrected at 3.0.0 (M-ADR 0203 §4.5 / F2); the value re-enters if a decision builds a reverse source."
2223
+ description: "Edge: capability is bound to a contract. Whether the capability exposes or depends on it is not stated by the source (traceability.contracts), so this description asserts no direction (M-ADR 0211 §1). Forward-declared only. Forward-declared only (traceability.contracts). The reverse derivation this description long claimed (service_contract ⋈ capability_service) was measured nonexistent — 0 `source: derived` rows across 105 units, builder references neither catalogue — and the CLAIM was corrected at 3.0.0 (M-ADR 0203 §4.5 / F2, gap class absent-derivation per M-ADR 0196 §4.1). The edge is forward-one-directional until a decision builds a reverse source."
2224
+ foreign_keys:
2225
+ - column: capability_id
2226
+ references: capabilities.id
2227
+ nullable: false
2228
+ - column: contract_id
2229
+ references: contracts.id
2230
+ nullable: false
2231
+ journey_feature:
2232
+ primary_key: id
2233
+ columns:
2234
+ - name: id
2235
+ type: string
2236
+ nullable: false
2237
+ - name: journey_id
2238
+ type: string
2239
+ nullable: false
2240
+ - name: feature_id
2241
+ type: string
2242
+ nullable: false
2243
+ description: "Edge: journey touches features. Parsed from Related features bullet."
2244
+ foreign_keys:
2245
+ - column: journey_id
2246
+ references: user_journeys.id
2247
+ nullable: false
2248
+ - column: feature_id
2249
+ references: features.id
2250
+ nullable: false
2251
+ persona_feature:
2252
+ primary_key: id
2253
+ columns:
2254
+ - name: id
2255
+ type: string
2256
+ nullable: false
2257
+ - name: persona_id
2258
+ type: string
2259
+ nullable: false
2260
+ - name: feature_id
2261
+ type: string
2262
+ nullable: false
2263
+ description: "Edge: persona uses features. Parsed from Related features bullet."
2264
+ foreign_keys:
2265
+ - column: persona_id
2266
+ references: personas.id
2267
+ nullable: false
2268
+ - column: feature_id
2269
+ references: features.id
2270
+ nullable: false
2271
+ feature_service:
2272
+ primary_key: id
2273
+ columns:
2274
+ - name: id
2275
+ type: string
2276
+ nullable: false
2277
+ - name: feature_id
2278
+ type: string
2279
+ nullable: false
2280
+ - name: service_id
2281
+ type: string
2282
+ nullable: false
2283
+ description: "Edge: feature is implemented by service. Parsed from Feature Services table in feature-tree.md."
2284
+ foreign_keys:
2285
+ - column: feature_id
2286
+ references: features.id
2287
+ nullable: false
2288
+ - column: service_id
2289
+ references: services.id
2290
+ nullable: false
2291
+ feature_event:
2292
+ primary_key: id
2293
+ columns:
2294
+ - name: id
2295
+ type: string
2296
+ nullable: false
2297
+ - name: feature_id
2298
+ type: string
2299
+ nullable: false
2300
+ - name: event_id
2301
+ type: string
2302
+ nullable: false
2303
+ - name: role
2304
+ type: string
2305
+ nullable: false
2306
+ description: publishes | consumes — mirrors the role on the source service_event row.
2307
+ - name: source
2308
+ type: string
2309
+ nullable: false
2310
+ description: Always `derived` (schema 2.15.0). The column is retained for symmetry with `capability_event.source` and to keep the door open for an authored shape if one surfaces; today every row is derived.
2311
+ description: "Edge: feature publishes or consumes event. Derived only — emitted from the `feature_service ⋈ service_event` join, mirroring M-ADR 0160's capability_event derived path one rung lower in the capability/feature/service hierarchy. Every row carries `source=derived`; there is no authored shape (the authored signal lives at the service level via `service_event`, which the feature inherits through `feature_service`). PK is `{feature_id}__{event_id}__{role}` so the same feature can carry both publishes + consumes rows for the same event without collision. Schema 2.15.0 per M-ADR 0161."
2312
+ foreign_keys:
2313
+ - column: feature_id
2314
+ references: features.id
2315
+ nullable: false
2316
+ - column: event_id
2317
+ references: events.id
2318
+ nullable: false
2319
+ column_enums:
2320
+ role: enums.event_participation
2321
+ feature_repo:
2322
+ primary_key: id
2323
+ columns:
2324
+ - name: id
2325
+ type: string
2326
+ nullable: false
2327
+ - name: feature_id
2328
+ type: string
2329
+ nullable: false
2330
+ - name: repo_id
2331
+ type: string
2332
+ nullable: false
2333
+ description: "Edge: feature is implemented in repo. From contributes_to.artifact_type=feature-set."
2334
+ foreign_keys:
2335
+ - column: feature_id
2336
+ references: features.id
2337
+ nullable: false
2338
+ - column: repo_id
2339
+ references: repositories.id
2340
+ nullable: false
2341
+ feature_contract:
2342
+ primary_key: id
2343
+ columns:
2344
+ - name: id
2345
+ type: string
2346
+ nullable: false
2347
+ description: "{feature_id}__{contract_id}."
2348
+ - name: feature_id
2349
+ type: string
2350
+ nullable: false
2351
+ - name: contract_id
2352
+ type: string
2353
+ nullable: false
2354
+ - name: derivation_path
2355
+ type: string
2356
+ nullable: true
2357
+ description: cap-feature-cap-contract | feature-service-service-contract. Diagnostic only — records which join path produced the row.
2358
+ description: "Edge: feature is exposed via contract. Derived — forward: capability_feature ⋈ capability_contract (on capability_id); reverse: feature_service ⋈ service_contract (on service_id). Both join paths are run and merged; duplicate (feature_id, contract_id) pairs are deduplicated. contract_id is external for app/integration profiles where contracts live in the platform SDD. Added in schema 2.3.0."
2359
+ foreign_keys:
2360
+ - column: feature_id
2361
+ references: features.id
2362
+ nullable: false
2363
+ - column: contract_id
2364
+ references: contracts.id
2365
+ nullable: false
2366
+ external: true
2367
+ column_enums:
2368
+ derivation_path: enums.feature_contract_derivation_path
2369
+ feature_subscription_channels:
2370
+ primary_key: id
2371
+ columns:
2372
+ - name: id
2373
+ type: string
2374
+ nullable: false
2375
+ description: "{feature_id}__{channel_name}."
2376
+ - name: feature_id
2377
+ type: string
2378
+ nullable: false
2379
+ - name: channel_name
2380
+ type: string
2381
+ nullable: false
2382
+ description: Channel identifier (kebab-case slug, namespaced as the source evidence carries it — e.g. `customer.<customerId>.tracking-points` for AppSync subscription channels).
2383
+ - name: transport
2384
+ type: string
2385
+ nullable: false
2386
+ description: "Delivery protocol: `appsync-websocket | pekko-ws | mqtt | sse | webhook-push | other`. The `other` value is escape-valve; adopters using it SHOULD record the actual transport in evidence."
2387
+ - name: evidence
2388
+ type: string
2389
+ nullable: true
2390
+ description: Evidence-file citation (`<sub-repo>/<path>:<line>`) anchoring the channel declaration. Mirrors the citation pattern used elsewhere in evidence yamls.
2391
+ - name: payload_ref
2392
+ type: string
2393
+ nullable: true
2394
+ description: Optional reference to a payload-contract event (`{event-name}` in the `events` catalogue) when the channel carries a contract-shaped payload. Empty when the payload is channel-private.
2395
+ - name: source_sdd_id
2396
+ type: string
2397
+ nullable: true
2398
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
2399
+ - name: platform_sdd_id
2400
+ type: string
2401
+ nullable: true
2402
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2403
+ description: "Edge: feature delivers async push via a named channel/topic. Peer of `graphql_operations:` in the per-feature evidence shape — `graphql_operations:` carries the GraphQL operation names declared in the schema (Queries / Mutations / Subscriptions); `feature_subscription_channels` rows carry the channel/topic layer that physically delivers the push events (AppSync WebSocket endpoints, Pekko WS channels, MQTT topics, server-sent-event streams). Per resolved decision §1 of `content/plans/v0-9-0-cohort-sweep-derived-bundle.md`: a single GraphQL Subscription operation may listen on multiple channels; one channel may be consumed by multiple operations — modelling as a separate edge catalogue (not as a feature column) accommodates the many-to-many. Built per-SDD from `reverse-evidence/feature-grounding-evidence.yaml` `subscription_channels:` entries on each feature. Added in schema 2.9.0."
2404
+ foreign_keys:
2405
+ - column: feature_id
2406
+ references: features.id
2407
+ nullable: false
2408
+ column_enums:
2409
+ transport: enums.subscription_channel_transport
2410
+ capability_domain_model:
2411
+ primary_key: id
2412
+ columns:
2413
+ - name: id
2414
+ type: string
2415
+ nullable: false
2416
+ description: "{capability_id}__{domain_model_id}."
2417
+ - name: capability_id
2418
+ type: string
2419
+ nullable: false
2420
+ - name: domain_model_id
2421
+ type: string
2422
+ nullable: false
2423
+ - name: source
2424
+ type: string
2425
+ nullable: false
2426
+ description: traceability-manifest | inferred.
2427
+ description: "Edge: capability references a domain model. Forward: declared in `traceability.domain_model` field of the capability traceability manifest. Reverse: inferred via capability → domain → domain_model. Platform-profile only. Added in schema 2.4.0; see M-ADR 0142."
2428
+ foreign_keys:
2429
+ - column: capability_id
2430
+ references: capabilities.id
2431
+ nullable: false
2432
+ - column: domain_model_id
2433
+ references: domain_models.id
2434
+ nullable: false
2435
+ column_enums:
2436
+ source: enums.capability_domain_model_source
2437
+ feature_domain_model:
2438
+ primary_key: id
2439
+ columns:
2440
+ - name: id
2441
+ type: string
2442
+ nullable: false
2443
+ description: "{feature_id}__{domain_model_id}."
2444
+ - name: feature_id
2445
+ type: string
2446
+ nullable: false
2447
+ - name: domain_model_id
2448
+ type: string
2449
+ nullable: false
2450
+ - name: derivation_path
2451
+ type: string
2452
+ nullable: true
2453
+ description: cap-feature-cap-domain-model. Diagnostic only.
2454
+ description: "Edge: feature operates on a domain model. Derived from capability_feature ⋈ capability_domain_model (on capability_id). Platform-profile only. Orphan features (no capability link) get no row. Added in schema 2.4.0; see M-ADR 0142."
2455
+ foreign_keys:
2456
+ - column: feature_id
2457
+ references: features.id
2458
+ nullable: false
2459
+ - column: domain_model_id
2460
+ references: domain_models.id
2461
+ nullable: false
2462
+ persona_journey:
2463
+ primary_key: id
2464
+ columns:
2465
+ - name: id
2466
+ type: string
2467
+ nullable: false
2468
+ - name: persona_id
2469
+ type: string
2470
+ nullable: false
2471
+ - name: journey_id
2472
+ type: string
2473
+ nullable: false
2474
+ - name: role
2475
+ type: string
2476
+ nullable: false
2477
+ description: primary | handoff | supporting.
2478
+ description: "Edge: persona participates in journey. Roles: primary | handoff | supporting."
2479
+ foreign_keys:
2480
+ - column: persona_id
2481
+ references: personas.id
2482
+ nullable: false
2483
+ - column: journey_id
2484
+ references: user_journeys.id
2485
+ nullable: false
2486
+ column_enums:
2487
+ role: enums.journey_participation
2488
+ persona_c4system:
2489
+ primary_key: id
2490
+ columns:
2491
+ - name: id
2492
+ type: string
2493
+ nullable: false
2494
+ description: "{persona_id}__{c4_system_id}."
2495
+ - name: persona_id
2496
+ type: string
2497
+ nullable: false
2498
+ - name: c4_system_id
2499
+ type: string
2500
+ nullable: false
2501
+ - name: interaction
2502
+ type: string
2503
+ nullable: true
2504
+ description: Optional interaction label from the Rel(...) line, e.g. 'Web browser' / 'Mobile app'.
2505
+ description: "Edge: persona (C4 Person) uses a C4 system. Captures the L1 context 'Person uses System' relationship, extracted from Person(...) macros on the L1 context diagram and matched to personas rows. Per M-ADR 0155. Added in schema 2.10.0."
2506
+ foreign_keys:
2507
+ - column: persona_id
2508
+ references: personas.id
2509
+ nullable: false
2510
+ - column: c4_system_id
2511
+ references: c4_systems.id
2512
+ nullable: false
2513
+ persona_container:
2514
+ primary_key: id
2515
+ columns:
2516
+ - name: id
2517
+ type: string
2518
+ nullable: false
2519
+ description: "{persona_id}__{container_id}."
2520
+ - name: persona_id
2521
+ type: string
2522
+ nullable: false
2523
+ - name: container_id
2524
+ type: string
2525
+ nullable: false
2526
+ - name: interaction
2527
+ type: string
2528
+ nullable: true
2529
+ description: Optional interaction label from the Rel(...) line. May hold multiple '; '-joined labels (F25).
2530
+ description: |
2531
+ Edge: a persona uses a C4 container — the L2-granularity companion to persona_c4system (M-ADR 0189 F26 §3, ratified 2026-07-10). Eleven of one estate's L2 diagrams and the bulk of another's 81 unroutable Rels drew Person→Container relationships that had no catalogue and, until F26, no finding. Harvested at member tier from Rel(...) lines whose endpoints resolve to a file-local Person and a local container (either direction; the row is normalised persona→container). A Person that matches no persona row is a coverage finding, never a silent skip. Both authoring directions feed from the same diagram surface (M-ADR 0157 parity). Added in schema 2.34.0.
2532
+ foreign_keys:
2533
+ - column: persona_id
2534
+ references: personas.id
2535
+ nullable: false
2536
+ - column: container_id
2537
+ references: c4_containers.id
2538
+ nullable: false
2539
+ system_external_dependency:
2540
+ primary_key: id
2541
+ columns:
2542
+ - name: id
2543
+ type: string
2544
+ nullable: false
2545
+ description: "{c4_system_id}__{external_system_id}."
2546
+ - name: c4_system_id
2547
+ type: string
2548
+ nullable: false
2549
+ - name: external_system_id
2550
+ type: string
2551
+ nullable: false
2552
+ - name: interaction
2553
+ type: string
2554
+ nullable: true
2555
+ description: Optional integration label/protocol from the Rel(...) line. May hold multiple '; '-joined labels when one pair is declared with distinct labels (F25, 2.33.2).
2556
+ - name: from_container_id
2557
+ type: string
2558
+ nullable: true
2559
+ description: The Rel's non-external endpoint resolved to a local container at member tier, when it is one (F17, 2.33.0) — the datum that lets adjudication rewrite this edge onto container_dependency instead of destroying it. Empty when the endpoint is the system itself or unresolvable.
2560
+ description: "Edge: a C4 system integrates with an external software system. Captures the L1 context 'System integrates with External System' relationship, extracted from System_Ext(...) + Rel(...) on L1/L2 diagrams. Per M-ADR 0155. Container-level external dependencies are out of scope (system-level only). Added in schema 2.10.0. From 2.30.0 (M-ADR 0189 §4.4): edges whose external endpoint the aggregator adjudicates as an INTERNAL system are rewritten onto system_system_dependency and removed from this catalogue."
2561
+ foreign_keys:
2562
+ - column: c4_system_id
2563
+ references: c4_systems.id
2564
+ nullable: false
2565
+ - column: external_system_id
2566
+ references: c4_external_systems.id
2567
+ nullable: false
2568
+ - column: from_container_id
2569
+ references: c4_containers.id
2570
+ nullable: true
2571
+ container_dependency:
2572
+ primary_key: id
2573
+ columns:
2574
+ - name: id
2575
+ type: string
2576
+ nullable: false
2577
+ description: "{from_container_id}__{to_container_id}."
2578
+ - name: from_container_id
2579
+ type: string
2580
+ nullable: false
2581
+ - name: to_container_id
2582
+ type: string
2583
+ nullable: false
2584
+ - name: interaction
2585
+ type: string
2586
+ nullable: true
2587
+ description: Label carried over from the originating Rel(...) line.
2588
+ - name: source_sdd_id
2589
+ type: string
2590
+ nullable: true
2591
+ description: SDD whose diagram declared the originating reference. Member-emitted rows set it directly (F19); adjudication-derived rows are stamped by the aggregator.
2592
+ - name: platform_sdd_id
2593
+ type: string
2594
+ nullable: true
2595
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2596
+ description: |
2597
+ Edge: a C4 container depends on another INTERNAL container (adopter finding F17 — F6 exactly one tier down: "no edge for internal" at L2). Derived by the aggregator at adjudication: an external-system candidate that resolves to an internal container was never external — each of its dependency edges whose member-resolved `from_container_id` is known is rewritten here, and a candidate with no remaining edges is dropped (it was a phantom duplicate of the container). A candidate with unconvertible edges is kept with the tier-contradiction finding, so no edge is ever destroyed to make a build quieter — the measured cost that stopped an adopter remediating 22 contradictions was eight real edges. ALSO emitted at member tier (F19, 2.33.1): the C4-correct authoring — Rel(container_a, container_b) between two Container(...) nodes — emits its edge directly; adjudication merges into a catalogue that already has content rather than being its only source, so the metamodel no longer rewards mis-declaration over correct authoring. Added in schema 2.33.0.
2598
+ foreign_keys:
2599
+ - column: from_container_id
2600
+ references: c4_containers.id
2601
+ nullable: false
2602
+ - column: to_container_id
2603
+ references: c4_containers.id
2604
+ nullable: false
2605
+ system_system_dependency:
2606
+ primary_key: id
2607
+ columns:
2608
+ - name: id
2609
+ type: string
2610
+ nullable: false
2611
+ description: "{from_system_id}__{to_system_id}."
2612
+ - name: from_system_id
2613
+ type: string
2614
+ nullable: false
2615
+ - name: to_system_id
2616
+ type: string
2617
+ nullable: false
2618
+ - name: interaction
2619
+ type: string
2620
+ nullable: true
2621
+ description: Optional label/protocol carried over from the originating Rel(...) line.
2622
+ - name: source_sdd_id
2623
+ type: string
2624
+ nullable: true
2625
+ description: SDD whose diagram declared the originating reference. Populated by the aggregator.
2626
+ - name: platform_sdd_id
2627
+ type: string
2628
+ nullable: true
2629
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2630
+ description: |
2631
+ Edge: a C4 system depends on another INTERNAL system (M-ADR 0189 §4.3). Derived by the aggregator at adjudication (§4.4): an external-system candidate whose declared identity resolves to an internal system was never external — its Rel(...) dependency edges are rewritten onto this catalogue and the candidate row is dropped. Not emitted at member tier (a member cannot see sibling systems); headers-only there, like cross_sdd_platform_capability. Both authoring directions feed it from the same diagram surface (M-ADR 0157 parity). Added in schema 2.30.0.
2632
+ foreign_keys:
2633
+ - column: from_system_id
2634
+ references: c4_systems.id
2635
+ nullable: false
2636
+ - column: to_system_id
2637
+ references: c4_systems.id
2638
+ nullable: false
2639
+ c4_container_entity:
2640
+ primary_key: id
2641
+ columns:
2642
+ - name: id
2643
+ type: string
2644
+ nullable: false
2645
+ description: "Composite PK: {container_id}__{entity_id}."
2646
+ - name: container_id
2647
+ type: string
2648
+ nullable: false
2649
+ - name: entity_id
2650
+ type: string
2651
+ nullable: false
2652
+ - name: relation
2653
+ type: string
2654
+ nullable: false
2655
+ description: Inherits from upstream service_entity.relation when derived.
2656
+ - name: source_sdd_id
2657
+ type: string
2658
+ nullable: true
2659
+ - name: platform_sdd_id
2660
+ type: string
2661
+ nullable: true
2662
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2663
+ description: "Derived edge: C4 container is responsible for data-model entity. Added in schema 2.13.0 per M-ADR 0159 §4.8. Pure transitive derivation: `service_entity ⋈ c4_containers.service_id`. Only the subset of containers with `service_id` populated contribute edges (per M-ADR 0155 the container ↔ service cardinality is o-or-1; data-store containers and infra-umbrella containers without a service mapping legitimately emit no rows)."
2664
+ foreign_keys:
2665
+ - column: container_id
2666
+ references: c4_containers.id
2667
+ nullable: false
2668
+ - column: entity_id
2669
+ references: entities.id
2670
+ nullable: false
2671
+ c4_system_entity:
2672
+ primary_key: id
2673
+ columns:
2674
+ - name: id
2675
+ type: string
2676
+ nullable: false
2677
+ description: "Composite PK: {system_id}__{entity_id}."
2678
+ - name: system_id
2679
+ type: string
2680
+ nullable: false
2681
+ - name: entity_id
2682
+ type: string
2683
+ nullable: false
2684
+ - name: container_count
2685
+ type: integer
2686
+ nullable: false
2687
+ description: Number of the system's containers that touch this entity. Aggregated from c4_container_entity.
2688
+ - name: source_sdd_id
2689
+ type: string
2690
+ nullable: true
2691
+ - name: platform_sdd_id
2692
+ type: string
2693
+ nullable: true
2694
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2695
+ description: "Derived edge: C4 system is responsible for data-model entity. Added in schema 2.13.0 per M-ADR 0159 §4.8. Pure aggregation roll-up: `c4_container_entity ⋈ c4_containers.system_id`, with container_count recording how many of the system's containers touch the entity (governance signal for cross-container concerns)."
2696
+ foreign_keys:
2697
+ - column: system_id
2698
+ references: c4_systems.id
2699
+ nullable: false
2700
+ - column: entity_id
2701
+ references: entities.id
2702
+ nullable: false
2703
+ capability_adr:
2704
+ primary_key: id
2705
+ columns:
2706
+ - name: id
2707
+ type: string
2708
+ nullable: false
2709
+ - name: capability_id
2710
+ type: string
2711
+ nullable: false
2712
+ - name: adr_id
2713
+ type: string
2714
+ nullable: false
2715
+ - name: confidence
2716
+ type: string
2717
+ nullable: false
2718
+ description: spec | high | medium.
2719
+ description: "Edge: ADR informs capability. Forward: declared in capability spec Architecture Decisions. Reverse: same plus heuristic match supplements with confidence."
2720
+ foreign_keys:
2721
+ - column: capability_id
2722
+ references: capabilities.id
2723
+ nullable: false
2724
+ - column: adr_id
2725
+ references: adrs.id
2726
+ nullable: false
2727
+ column_enums:
2728
+ confidence: enums.capability_adr_confidence
2729
+ adr_supersedes:
2730
+ primary_key: id
2731
+ columns:
2732
+ - name: id
2733
+ type: string
2734
+ nullable: false
2735
+ - name: superseding_adr_id
2736
+ type: string
2737
+ nullable: false
2738
+ - name: superseded_adr_id
2739
+ type: string
2740
+ nullable: false
2741
+ description: "Edge: superseding ADR → superseded ADR. Parsed from Supersedes bullets where prose references a known ADR id."
2742
+ foreign_keys:
2743
+ - column: superseding_adr_id
2744
+ references: adrs.id
2745
+ nullable: false
2746
+ - column: superseded_adr_id
2747
+ references: adrs.id
2748
+ nullable: false
2749
+ product_platform_dependencies:
2750
+ primary_key: id
2751
+ columns:
2752
+ - name: id
2753
+ type: string
2754
+ nullable: false
2755
+ description: "{product_id}__{target_capability_id}__{target_service_id}, EXCEPT for async shared-stream rows (M-ADR 0192) where there is no realiser service: the third component falls back to the stream contract_path, i.e. {product_id}__{target_capability_id}__{contract_path}. For OFF-PLATFORM rows (M-ADR 0204, target_locus external|legacy) there is no platform capability either: id = {product_id}__{target_locus}__{target_external_system_id}, falling back to contract_path as the third component when no external-system id is named. This keeps the PK stable and collision-free when a product depends on the same capability via two distinct streams."
2756
+ - name: product_id
2757
+ type: string
2758
+ nullable: false
2759
+ description: Consuming product (this SDD's product id).
2760
+ - name: target_capability_id
2761
+ type: string
2762
+ nullable: true
2763
+ description: "Capability the consuming product depends on. Resolves at aggregation against a sibling SDD's capabilities.id; external by definition. Conditionally nullable (M-ADR 0204 §4.3): EMPTY when target_locus is external|legacy — there is no platform capability to name on an off-platform row, and demanding a value is what put a product's own feature slug in this column. A platform-locus row still requires it."
2764
+ - name: target_locus
2765
+ type: string
2766
+ nullable: true
2767
+ description: platform | external | legacy (M-ADR 0204; closed enum, absent/empty = platform). A statement about the TARGET only — never about the consuming product, and never a stability, lifecycle or quality claim. platform rows behave exactly as before this column existed. external/legacy rows carry empty target_capability_id and target_service_id and name their target in target_external_system_id; they skip platform resolution and the F18 realiser-join, with every skip named.
2768
+ - name: target_external_system_id
2769
+ type: string
2770
+ nullable: true
2771
+ description: "For target_locus external|legacy rows only: the M-ADR 0189 external-system entry id the dependency targets (authored in the source file's service_id slot; the builder routes it here so the FK columns stay clean). Deliberately NOT a declared FK: corroboration against c4_external_systems is WARNING-severity at aggregation (M-ADR 0204 §4.2), because the C4 surface may legitimately lag discovery, and a declared FK can only fail."
2772
+ - name: target_service_id
2773
+ type: string
2774
+ nullable: true
2775
+ description: "Service identifier the consuming product depends on. Resolves at aggregation against a sibling SDD's services.id; external by definition. The join key the aggregator uses to derive cross_sdd_platform_capability for SYNCHRONOUS dependencies. Conditionally nullable (M-ADR 0192): for an async shared-stream dependency (contract_type in the async set — `event`/`event-stream`/`stream`) there is no single realiser service, so this is empty and the dependency binds to the stream contract_path + target_capability_id instead. A synchronous contract_type still requires it. Made nullable in schema 2.36.0."
2776
+ - name: target_domain
2777
+ type: string
2778
+ nullable: true
2779
+ description: Domain hint as declared in the consuming SDD's evidence (free-form; reviewer-facing annotation). May be a comma-separated list when the target spans multiple domains.
2780
+ - name: contract_type
2781
+ type: string
2782
+ nullable: true
2783
+ description: rest | graphql | openapi | grpc | event | event-stream | stream | other. Optional; reflects what the consuming SDD declares. The async set (`event`/`event-stream`/`stream`) marks a shared-stream subscription that binds to a stream contract rather than a realiser service (M-ADR 0192) — such rows skip the F18 synchronous realiser-join at aggregation.
2784
+ - name: required_stability
2785
+ type: string
2786
+ nullable: true
2787
+ description: "provisional | locked | unknown. Optional; the consuming SDD's expectation of contract stability — and only that: where the target lives and what lifecycle its implementation is in are separate concerns that do not belong in this field. Not a bound enum: an out-of-vocabulary value is carried, not rejected, and is reported by validate-app-dependencies.sh."
2788
+ - name: contract_path
2789
+ type: string
2790
+ nullable: true
2791
+ description: Path to the contract file the dependency is against, as declared in the consuming SDD's evidence. External — resolution happens at aggregation if it happens at all.
2792
+ - name: consumed_by_services
2793
+ type: string
2794
+ nullable: true
2795
+ description: Comma-separated list of service names within the consuming product that consume the dependency. Free-text; not FK-validated (services are within-product and resolution is owner-side concern).
2796
+ - name: source_sdd_id
2797
+ type: string
2798
+ nullable: true
2799
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
2800
+ - name: platform_sdd_id
2801
+ type: string
2802
+ nullable: true
2803
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2804
+ description: |
2805
+ Per-SDD edge: an application-side or integration-side SDD declares that its product depends on a platform-side capability + service pair. Built from `reverse-evidence/feature-grounding-evidence.yaml` `platform_dependencies:` block (product-level — the cohort source shape carries product-scoped dependency rows with a `consumed_by:` list naming which services within the consuming product depend on the target). Each row records one (consuming product, target capability, target service) triple. The aggregator then joins these rows against platform-side `capability_service` to emit `cross_sdd_platform_capability` edges at aggregation time. Cross- SDD references (target_capability_id, target_service_id) are external — they're not expected to resolve in the per-SDD build, only at aggregation. Added in schema 2.9.0; see `content/plans/v0-9-0-cohort-sweep-derived-bundle.md` §"Cross-SDD platform-capability-edge".
2806
+ foreign_keys:
2807
+ - column: product_id
2808
+ references: products.id
2809
+ nullable: false
2810
+ - column: target_capability_id
2811
+ references: capabilities.id
2812
+ nullable: true
2813
+ external: true
2814
+ - column: target_service_id
2815
+ references: services.id
2816
+ nullable: true
2817
+ external: true
2818
+ column_enums:
2819
+ required_stability: enums.required_stability
2820
+ target_locus: enums.target_locus
2821
+ contract_type: enums.dependency_contract_type
2822
+ cross_sdd_platform_capability:
2823
+ primary_key: id
2824
+ columns:
2825
+ - name: id
2826
+ type: string
2827
+ nullable: false
2828
+ description: "{consuming_sdd_id}__{consuming_product_id}__{platform_sdd_id}__{platform_capability_id}__{service_id}. Composite encoding so the same (consuming product, platform capability) pair can appear once per resolving service when a product depends on multiple services owned by the same capability."
2829
+ - name: consuming_sdd_id
2830
+ type: string
2831
+ nullable: false
2832
+ description: SDD slug of the consuming side (application-product or integration-product SDD).
2833
+ - name: consuming_product_id
2834
+ type: string
2835
+ nullable: false
2836
+ description: Product in the consuming SDD that declares the platform_dependencies entry.
2837
+ - name: platform_sdd_id
2838
+ type: string
2839
+ nullable: false
2840
+ description: SDD slug of the platform side that owns the resolved capability.
2841
+ - name: platform_capability_id
2842
+ type: string
2843
+ nullable: false
2844
+ description: Capability in the platform SDD whose capability_service includes the resolved service.
2845
+ - name: service_id
2846
+ type: string
2847
+ nullable: false
2848
+ description: Service identifier the consuming SDD references and the platform SDD owns. The join key.
2849
+ description: |
2850
+ Federated edge: an application-side or integration-side SDD's `product_platform_dependencies` reference resolves against a platform-side SDD's capability spec via the platform capability's `capability_service` roster. Surfaces ecosystem-wide platform- consumer relationships at product → capability granularity. Built **only at aggregation time** — `sdd-cli catalogue aggregate` joins each consuming SDD's `product_platform_dependencies` rows against every other SDD's `capability_service` rows on `target_service_id == service_id`, emitting one row per resolved (consuming-product, platform-capability) pair. Per-SDD builders emit nothing for this catalogue; the aggregator owns it entirely. A platform-dependency whose target_service_id doesn't resolve to any platform-side capability_service row is logged as an `orphan` finding and produces no row. Cross-SDD references are external by definition. Added in schema 2.9.0; see `content/plans/v0-9-0-cohort-sweep-derived-bundle.md` §"Cross-SDD platform-capability-edge" and M-ADR 0134.
2851
+ foreign_keys:
2852
+ - column: consuming_product_id
2853
+ references: products.id
2854
+ nullable: false
2855
+ external: true
2856
+ - column: platform_capability_id
2857
+ references: capabilities.id
2858
+ nullable: false
2859
+ external: true
2860
+ - column: service_id
2861
+ references: services.id
2862
+ nullable: false
2863
+ external: true
2864
+ application_data_plane_bindings:
2865
+ primary_key: id
2866
+ columns:
2867
+ - name: id
2868
+ type: string
2869
+ nullable: false
2870
+ description: "{product_id}__{pattern}__{locality}__{target} (empty components collapse to blanks). A duplicate emits a divergence finding and is dropped. `direction` is NOT a component — it is derived from `pattern`, so it adds nothing to identity."
2871
+ - name: product_id
2872
+ type: string
2873
+ nullable: false
2874
+ description: The application-product declaring this binding (this SDD's product id).
2875
+ - name: pattern
2876
+ type: string
2877
+ nullable: false
2878
+ description: "Closed method-tier enum: retrieve | own-store | stream-ingest | project (inbound, data-sourcing) | generate | publish (output-side, per M-ADR 0193 §4.7). How the data relates to the service (§4.1)."
2879
+ - name: direction
2880
+ type: string
2881
+ nullable: false
2882
+ description: "inbound | output. DERIVED from `pattern` by a single method-tier mapping — not authored, and not a manifest field, so it cannot disagree with `pattern`. Materialises the output-side sub-set §4.7 declares (generate/publish => output; everything else => inbound). Exists because three §4.7 rules branch on direction: platform-dep reconciliation is inbound-only, the archetype WARN must compare like with like, and the M-ADR 0187 convergence reasoning differs by direction. Added in 2.40.0."
2883
+ - name: locality
2884
+ type: string
2885
+ nullable: true
2886
+ description: "Closed enum: internal-platform | internal-domain | external-vendor. Where the other end sits. REQUIRED on the inbound data-sourcing patterns (retrieve/stream-ingest/project); may be empty for own-store (a self-binding with no other end) and for the output-side patterns (generate/publish), which may carry one but do not require it (M-ADR 0193 §4.7)."
2887
+ - name: transport
2888
+ type: string
2889
+ nullable: true
2890
+ description: Open string — the wire (rest | graphql | grpc | appsync | kinesis | kafka | eventhub | cdc | ...). Values outside the recommended set emit a convention finding.
2891
+ - name: runtime
2892
+ type: string
2893
+ nullable: true
2894
+ description: Free adopter-tier field — backend-compute runtime (e.g. java | node). Only on compute-bearing patterns (stream-ingest | project | generate — `generate` is compute-bearing per M-ADR 0193 §4.7); empty otherwise. A runtime on retrieve/own-store/publish is malformed and FAILs at manifest load.
2895
+ - name: target
2896
+ type: string
2897
+ nullable: true
2898
+ description: Free adopter-tier field — the specific counterpart (a platform service id, an upstream domain service, a named vendor). Instance identity; keeps locality a small class enum.
2899
+ - name: notes
2900
+ type: string
2901
+ nullable: true
2902
+ description: Optional free-text annotation.
2903
+ - name: source_sdd_id
2904
+ type: string
2905
+ nullable: true
2906
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
2907
+ - name: platform_sdd_id
2908
+ type: string
2909
+ nullable: true
2910
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2911
+ description: |
2912
+ Application-product edge (M-ADR 0193): one row per declared data-plane binding — a typed way the service sources, holds, produces or exposes data. The data-plane is a COMPOSITION of these bindings, a second axis orthogonal to `application_archetype` (0191). Built per-SDD from the manifest's `data_plane.bindings` block (application-product only; other profiles emit headers-only). The `pattern` vocabulary splits by DIRECTION (§4.7): an INBOUND data-sourcing sub-set (retrieve | own-store | stream-ingest | project) and an OUTPUT-side sub-set (generate | publish), materialised as the derived `direction` column. An INBOUND binding whose `target` is a platform capability/service reconciles with `product_platform_dependencies` — a `retrieve@internal` binding is a synchronous platform dependency and a `stream-ingest@internal` binding is the M-ADR 0192 `contract_type: event` async dependency; the genuinely new inbound rows are `own-store` (a self-binding) and any `external-vendor` binding. OUTPUT-side rows do NOT participate in that reconciliation (§4.7 rule 1): `publish` is a contract the service PROVIDES, not one it consumes, so it has no inbound counterpart to cross-check — consumers must filter on `direction` before reconciling, which is what the column is for. The archetype-default-vs-declared WARN keys on the bare `pattern` token and so spans both directions (§4.7 rule 2). Added in schema 2.37.0; `direction` added in 2.40.0.
2913
+ foreign_keys:
2914
+ - column: product_id
2915
+ references: products.id
2916
+ nullable: false
2917
+ column_enums:
2918
+ pattern: enums.data_plane_pattern
2919
+ direction: enums.data_plane_direction
2920
+ locality: enums.data_plane_locality
2921
+ application_data_plane_deviations:
2922
+ primary_key: id
2923
+ columns:
2924
+ - name: id
2925
+ type: string
2926
+ nullable: false
2927
+ description: "{product_id}__{expectation}. A duplicate emits a divergence finding and is dropped."
2928
+ - name: product_id
2929
+ type: string
2930
+ nullable: false
2931
+ description: The application-product declaring this deviation (this SDD's product id).
2932
+ - name: expectation
2933
+ type: string
2934
+ nullable: false
2935
+ description: The bare data-plane pattern token the product diverges from (retrieve | own-store | stream-ingest | project | generate | publish). Must match the WARN's pattern key. Spans both directions per M-ADR 0193 §4.7 rule 2.
2936
+ - name: rationale
2937
+ type: string
2938
+ nullable: false
2939
+ description: Why the deviation is correct. Non-empty (enforced at manifest load).
2940
+ - name: source_sdd_id
2941
+ type: string
2942
+ nullable: true
2943
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
2944
+ - name: platform_sdd_id
2945
+ type: string
2946
+ nullable: true
2947
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2948
+ description: |
2949
+ Application-product annotation (M-ADR 0191 §4.3 overlay): one row per declared departure from the archetype's default data-plane composition. Built per-SDD from the manifest's `data_plane.deviations` block so the overlay WARN — which runs at AGGREGATION tier, where the reference- architecture bundle (and its `expected_bindings`) resolves — can suppress a mismatch it is told is sanctioned variance. The `expectation` value is the **bare pattern token** (`retrieve` | `own-store` | `stream-ingest` | `project` | `generate` | `publish`) that the product knowingly diverges from; it must match the pattern the WARN keys on. The token set spans both directions — the WARN keys on the bare pattern, so an output-side expectation is deviated exactly like an inbound one (M-ADR 0193 §4.7 rule 2). Added in schema 2.38.0; output-side tokens documented in 2.40.0.
2950
+ foreign_keys:
2951
+ - column: product_id
2952
+ references: products.id
2953
+ nullable: false
2954
+ column_enums:
2955
+ expectation: enums.data_plane_pattern
2956
+ application_conformance_coverage:
2957
+ primary_key: id
2958
+ columns:
2959
+ - name: id
2960
+ type: string
2961
+ nullable: false
2962
+ description: "{product_id}__{tag}. A duplicate emits a divergence finding and is dropped."
2963
+ - name: product_id
2964
+ type: string
2965
+ nullable: false
2966
+ description: The application-product declaring this coverage (this SDD's product id).
2967
+ - name: tag
2968
+ type: string
2969
+ nullable: false
2970
+ description: The conformance-expectation tag (opaque; matches an archetype's `conformance` tag in the reference-architecture vocabulary).
2971
+ - name: status
2972
+ type: string
2973
+ nullable: false
2974
+ description: covered (the product's suite exercises it) | deviated (deliberately not covered, with a rationale).
2975
+ - name: rationale
2976
+ type: string
2977
+ nullable: true
2978
+ description: Why the tag is deviated. Present (non-empty) only when status=deviated.
2979
+ - name: source_sdd_id
2980
+ type: string
2981
+ nullable: true
2982
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
2983
+ - name: platform_sdd_id
2984
+ type: string
2985
+ nullable: true
2986
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
2987
+ description: |
2988
+ Application-product annotation (M-ADR 0191 §4.3 overlay, second element — WS4): one row per conformance tag the product asserts about its archetype's conformance expectations. Built per-SDD from the manifest's `conformance` block so the AGGREGATION-tier conformance GATE can read it. `status=covered` means the product's own conformance suite exercises the tag; `status=deviated` means the product declares (with a rationale) that it deliberately does not. At aggregation, an archetype-expected conformance tag that is neither covered nor deviated raises a deviation-visible WARN. The method gates the DECLARATION — it does not run the adopter's conformance suite. Added in schema 2.39.0.
2989
+ foreign_keys:
2990
+ - column: product_id
2991
+ references: products.id
2992
+ nullable: false
2993
+ screens:
2994
+ primary_key: id
2995
+ columns:
2996
+ - name: id
2997
+ type: string
2998
+ nullable: false
2999
+ description: "Slugged PK: {product_id}-{screen-slug}."
3000
+ - name: name
3001
+ type: string
3002
+ nullable: false
3003
+ description: Screen slug / display name.
3004
+ - name: product_id
3005
+ type: string
3006
+ nullable: false
3007
+ description: Owning application-product.
3008
+ - name: route
3009
+ type: string
3010
+ nullable: true
3011
+ description: Route path the screen is mounted at, when applicable.
3012
+ - name: status
3013
+ type: string
3014
+ nullable: true
3015
+ description: Maturity marker; uses the standard working | provisional | unknown | absent vocabulary (per M-ADR 0165) where applicable.
3016
+ - name: source
3017
+ type: string
3018
+ nullable: false
3019
+ description: screen-spec (forward) | screen-extraction (reverse).
3020
+ - name: domain
3021
+ type: string
3022
+ nullable: true
3023
+ description: Authored owning-domain hint from frontmatter `domain:` (a docs/domains/<domain>/ slug). Organisational grouping for multi-domain (platform-profile) SDDs; the authoritative screen->domain relationship is still derived via realises -> feature -> capability.domain_id (screen_feature). Empty when unauthored.
3024
+ - name: group
3025
+ type: string
3026
+ nullable: true
3027
+ description: Authored sub-grouping hint from frontmatter `group:` — a finer organisational axis within (or orthogonal to) domain, e.g. shell | shell-embed | identity. Free-form adopter label; not an FK. Empty when unauthored.
3028
+ - name: context
3029
+ type: string
3030
+ nullable: true
3031
+ description: Bounded-context membership from frontmatter `context:` (per M-ADR 0170 §4.6). Free-form adopter label, orthogonal to domain/group — the consumed bounded context for a surface that spans several. Not an FK. Empty when unauthored. Added in schema 2.19.0.
3032
+ - name: evidence_class
3033
+ type: string
3034
+ nullable: true
3035
+ description: "Evidence class of the screen's claims, from frontmatter `evidence_class:` (alias `evidence-class:`). Free-form; conventional values code-reverse | vendor-doc | operational (M-ADR 0175). Empty when undeclared. Completes the evidence-class dimension for the packaged-SaaS case: a packaged-SaaS SDD catalogues the vendor's STANDARD screens (documentation-reversed from vendor publications, `vendor-doc`) alongside the organisation's CUSTOMISED screens (code-reversed, `code-reverse`) per M-ADR 0175 §3.1 — without this column the two are indistinguishable, and doc-derived UI claims masquerade as code-verified. Orthogonal to `source` (`screen-spec` | `screen-extraction`), which records the authoring DIRECTION, not the evidence's strength: a `screen-extraction` screen can be either class, since a vendor's documented UI is extracted-but-not-code-verified. Added in schema 2.42.0."
3036
+ - name: source_sdd_id
3037
+ type: string
3038
+ nullable: true
3039
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
3040
+ - name: platform_sdd_id
3041
+ type: string
3042
+ nullable: true
3043
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
3044
+ description: "UI screen specified in the OpenUI Lang grammar (per M-ADR 0166). One row per screen / coherent screen group. Application-product profile (other profiles emit headers-only). Source: authored `screens/*.md` (frontmatter + ```openui-lang block); the reverse toolkit produces these from a router + component-tree projection."
3045
+ foreign_keys:
3046
+ - column: product_id
3047
+ references: products.id
3048
+ nullable: false
3049
+ column_enums:
3050
+ status: enums.artefact_maturity
3051
+ ui_components:
3052
+ primary_key: id
3053
+ columns:
3054
+ - name: id
3055
+ type: string
3056
+ nullable: false
3057
+ description: "Slugged PK: {product_id}-{component-slug}."
3058
+ - name: name
3059
+ type: string
3060
+ nullable: false
3061
+ description: Component identifier as used in the grammar.
3062
+ - name: product_id
3063
+ type: string
3064
+ nullable: false
3065
+ description: Owning application-product.
3066
+ - name: kind
3067
+ type: string
3068
+ nullable: true
3069
+ description: "Optional classification: layout | display | input | chart | element | composite | remote | remote-iframe | remote-webcomponent. A `remote*` kind marks a micro-frontend federation seam (M-ADR 0166 §4.7)."
3070
+ - name: source
3071
+ type: string
3072
+ nullable: false
3073
+ description: screen-spec (forward) | design-system-import (reverse).
3074
+ - name: source_sdd_id
3075
+ type: string
3076
+ nullable: true
3077
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
3078
+ - name: platform_sdd_id
3079
+ type: string
3080
+ nullable: true
3081
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
3082
+ description: "An entry in the adopter-owned component registry that screens compose against (per M-ADR 0166) — the UI-structure contract. A screen composes registry components but never defines one. Application-product profile. Source: components referenced across the SDD's screen-spec ```openui-lang blocks (registry projection); the reverse toolkit discovers the authoritative registry from the design-system import surface."
3083
+ foreign_keys:
3084
+ - column: product_id
3085
+ references: products.id
3086
+ nullable: false
3087
+ column_enums:
3088
+ kind: enums.ui_component_kind
3089
+ screen_component:
3090
+ primary_key: id
3091
+ columns:
3092
+ - name: id
3093
+ type: string
3094
+ nullable: false
3095
+ description: "Composite PK: {screen_id}__{component_id}."
3096
+ - name: screen_id
3097
+ type: string
3098
+ nullable: false
3099
+ - name: component_id
3100
+ type: string
3101
+ nullable: false
3102
+ - name: source_sdd_id
3103
+ type: string
3104
+ nullable: true
3105
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
3106
+ - name: platform_sdd_id
3107
+ type: string
3108
+ nullable: true
3109
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
3110
+ description: "Edge: screen composes a UI component. Parsed from the screen-spec ```openui-lang block's component references (per M-ADR 0166)."
3111
+ foreign_keys:
3112
+ - column: screen_id
3113
+ references: screens.id
3114
+ nullable: false
3115
+ - column: component_id
3116
+ references: ui_components.id
3117
+ nullable: false
3118
+ screen_feature:
3119
+ primary_key: id
3120
+ columns:
3121
+ - name: id
3122
+ type: string
3123
+ nullable: false
3124
+ description: "Composite PK: {screen_id}__{feature_id}. For app/integration builds the feature_id may be a bare realises slug until the aggregator resolves it to the platform feature id (then the PK is regenerated)."
3125
+ - name: screen_id
3126
+ type: string
3127
+ nullable: false
3128
+ - name: feature_id
3129
+ type: string
3130
+ nullable: false
3131
+ - name: source_sdd_id
3132
+ type: string
3133
+ nullable: true
3134
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
3135
+ - name: platform_sdd_id
3136
+ type: string
3137
+ nullable: true
3138
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
3139
+ description: "Edge: screen realises a feature (traceability). Forward: `realises:` frontmatter on the screen-spec. Reverse: route → feature mapping. Per M-ADR 0166."
3140
+ foreign_keys:
3141
+ - column: screen_id
3142
+ references: screens.id
3143
+ nullable: false
3144
+ - column: feature_id
3145
+ references: features.id
3146
+ nullable: false
3147
+ external_for_profiles:
3148
+ - application-product
3149
+ - integration-product
3150
+ persona_screen:
3151
+ primary_key: id
3152
+ columns:
3153
+ - name: id
3154
+ type: string
3155
+ nullable: false
3156
+ description: "Composite PK: {persona_id}__{screen_id}."
3157
+ - name: persona_id
3158
+ type: string
3159
+ nullable: false
3160
+ - name: screen_id
3161
+ type: string
3162
+ nullable: false
3163
+ - name: source_sdd_id
3164
+ type: string
3165
+ nullable: true
3166
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
3167
+ - name: platform_sdd_id
3168
+ type: string
3169
+ nullable: true
3170
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
3171
+ description: "Edge: persona can access a screen. Forward: `persona_access:` frontmatter. Reverse: route persona-access guards, permission/feature-flag config, or a host shell's per-persona menu (where the backend pre-filters visible screens). Per M-ADR 0166."
3172
+ foreign_keys:
3173
+ - column: persona_id
3174
+ references: personas.id
3175
+ nullable: false
3176
+ - column: screen_id
3177
+ references: screens.id
3178
+ nullable: false
3179
+ screen_action:
3180
+ primary_key: id
3181
+ columns:
3182
+ - name: id
3183
+ type: string
3184
+ nullable: false
3185
+ description: "Composite PK: {screen_id}__{action-slug}."
3186
+ - name: screen_id
3187
+ type: string
3188
+ nullable: false
3189
+ - name: action
3190
+ type: string
3191
+ nullable: false
3192
+ description: Declared action label emitted by the screen.
3193
+ - name: event_id
3194
+ type: string
3195
+ nullable: true
3196
+ description: Catalogued event the action maps to (per M-ADR 0156). External-capable; empty when the action does not resolve to a domain event.
3197
+ - name: source_sdd_id
3198
+ type: string
3199
+ nullable: true
3200
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
3201
+ - name: platform_sdd_id
3202
+ type: string
3203
+ nullable: true
3204
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
3205
+ description: "Edge: screen emits an action, optionally resolved to a catalogued event. The behavioural MFE seam — inter-bundle communication as a catalogued contract, not an ad-hoc string. Forward: `action=` declarations in the ```openui-lang block. Reverse: emitted custom-event / event-bus wiring. event_id is external-capable (the event may live in the platform SDD). Per M-ADR 0166 + M-ADR 0156."
3206
+ foreign_keys:
3207
+ - column: screen_id
3208
+ references: screens.id
3209
+ nullable: false
3210
+ - column: event_id
3211
+ references: events.id
3212
+ nullable: true
3213
+ external: true
3214
+ conformance_finding:
3215
+ primary_key: id
3216
+ columns:
3217
+ - name: id
3218
+ type: string
3219
+ nullable: false
3220
+ description: Check id (unique within the SDD; source_sdd_id disambiguates across the federation).
3221
+ - name: check_id
3222
+ type: string
3223
+ nullable: false
3224
+ - name: target
3225
+ type: string
3226
+ nullable: false
3227
+ description: code-vs-contract | binding-vs-reality (M-ADR 0180 §2.5).
3228
+ - name: implementation_repo
3229
+ type: string
3230
+ nullable: true
3231
+ description: The implementation member the check is about (M-ADR 0181). Empty when checks were not binding-derived.
3232
+ - name: role
3233
+ type: string
3234
+ nullable: true
3235
+ description: as-is | to-be (M-ADR 0181). Empty when not binding-derived.
3236
+ - name: lifecycle
3237
+ type: string
3238
+ nullable: true
3239
+ description: planned | migrating | active | legacy-active | deprecated | decommissioned (M-ADR 0181).
3240
+ - name: declared
3241
+ type: number
3242
+ nullable: false
3243
+ description: Count of the declared surface (spec/binding/contract).
3244
+ - name: observed
3245
+ type: number
3246
+ nullable: false
3247
+ description: Count of the observed surface (code).
3248
+ - name: matched
3249
+ type: number
3250
+ nullable: false
3251
+ - name: conformance_pct
3252
+ type: number
3253
+ nullable: false
3254
+ description: matched / denom * 100 (denom per the check).
3255
+ - name: declared_not_observed
3256
+ type: number
3257
+ nullable: false
3258
+ description: "Count declared but not observed (candidate: spec-stale / unimplemented / dangling)."
3259
+ - name: observed_not_declared
3260
+ type: number
3261
+ nullable: false
3262
+ description: "Count observed but not declared (candidate: binding-stale / code-defect)."
3263
+ - name: needs_triage
3264
+ type: boolean
3265
+ nullable: false
3266
+ description: True when any asymmetry exists. Triage, not auto-fail (M-ADR 0180 §2.3).
3267
+ - name: run_date
3268
+ type: string
3269
+ nullable: false
3270
+ description: ISO date of the conformance run — the snapshot stamp enabling trend over time.
3271
+ - name: source_sdd_id
3272
+ type: string
3273
+ nullable: true
3274
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
3275
+ - name: platform_sdd_id
3276
+ type: string
3277
+ nullable: true
3278
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
3279
+ description: "Conformance-reverse drift summary, one row per check (method M-ADR 0180). NOT produced by `catalogue build` (it reads the spec repo) — produced by `sdd-cli conformance --emit-finding` (which has the code repo) and federated here by the aggregator. Each row is a run-dated snapshot of declared-vs-observed drift for an implementation member (M-ADR 0181 role/lifecycle), so estate-wide conformance is queryable (aggregate union) and trendable (snapshot diff across runs/commits). Verdicts are PROVISIONAL — disposition (code-defect | spec-stale | divergence) is triage, recorded elsewhere. No enforced FK on implementation_repo: the code repo is frequently cross-repo and not in this SDD's repositories.csv. Added in schema 2.25.0."
3280
+ column_enums:
3281
+ target: enums.conformance_target
3282
+ role: enums.conformance_role
3283
+ lifecycle: enums.conformance_lifecycle
3284
+ quality_scores:
3285
+ primary_key: id
3286
+ columns:
3287
+ - name: id
3288
+ type: string
3289
+ nullable: false
3290
+ description: "PK: {rubric_id}__{target_kind}__{target_ref}. Composite in one slug because the natural key is a triple and the rest of this schema keys on a single `id`."
3291
+ - name: rubric_id
3292
+ type: string
3293
+ nullable: false
3294
+ description: The rubric that produced the assessment, e.g. adr-quality, contract-quality. From the registry's `registry_type` when declared, else the filename stem minus `-scores`. A `registry_type` disagreeing with its filename is a convention finding, never a silent preference.
3295
+ - name: scoring_form
3296
+ type: string
3297
+ nullable: false
3298
+ description: Scoring shape — see the scoring_form enum. `weighted` for every row the current builder emits.
3299
+ - name: target_kind
3300
+ type: string
3301
+ nullable: false
3302
+ description: "What kind of thing was scored: adr | contract | c4_diagram | capability | domain | feature | product | repository | persona | screen | glossary | integration | user_story | work_order | strategic_doc. Polymorphic because scored units span catalogue entities and non-catalogued artefacts (M-ADR 0205 §4.5)."
3303
+ - name: target_ref
3304
+ type: string
3305
+ nullable: false
3306
+ description: Identifier of the scored target, in the vocabulary of its kind. For ADRs this is the prefix-stripped catalogue id (M-ADR 0186 §4.4), matching `adrs.id`.
3307
+ - name: target_path
3308
+ type: string
3309
+ nullable: true
3310
+ description: Repo-relative path to the scored artefact, from the entry's `file_path` where authored (7 of 15 registry shapes carry it). Doubles as the resolution anchor for `scored_at`-basis staleness — which is why its absence downgrades a row's staleness_basis to `none` rather than being cosmetic. Empty when the registry does not author it.
3311
+ - name: gate
3312
+ type: string
3313
+ nullable: true
3314
+ description: Verdict — see the quality_gate enum, which is deliberately UNBOUND. An out-of-vocabulary value leaves this cell EMPTY and raises a convention finding naming the file, entry and value (the products.synthesis_band precedent). Empty therefore means either unauthored or out-of-vocabulary, and the finding distinguishes them.
3315
+ - name: weighted_score
3316
+ type: number
3317
+ nullable: true
3318
+ description: The rubric's rolled-up weighted score. Empty for an unscored entry — which is a real state the registries author deliberately, not a gap.
3319
+ - name: score_denominator
3320
+ type: number
3321
+ nullable: true
3322
+ description: Denominator the weighted_score was computed against, where the rubric records one (contract-quality does). Present so a score is never reported without its basis.
3323
+ - name: band
3324
+ type: string
3325
+ nullable: true
3326
+ description: "Named band for a `banded` row; empty for a weighted one. DELIBERATELY UNBOUND, and for the same reason `dimension_key` is not normalised: the vocabulary belongs to the rubric, not to the method. Measured across the reverse estate at 3.3.0 — `reverseability` uses easy | moderate | hard | very-hard (a DIFFICULTY scale, where a higher band is worse), while `repo_doc_quality`, `product_synthesis_quality`, `reverse_platform_evidence_quality` and `artifact_quality` use strong | working (a QUALITY scale). One closed enum over both would assert that `hard` and `working` are comparable, which they are not. A consumer comparing bands must therefore group by rubric_id first."
3327
+ - name: band_total
3328
+ type: int
3329
+ nullable: true
3330
+ description: "Integer total a `banded` rubric summed its dimensions to, before mapping to `band`; empty for a weighted row. Kept SEPARATE from weighted_score rather than sharing it: the scales are incompatible (a banded total ranges 0-13 against a weighted 1-5), and a single column holding both would make any average over it silently wrong. Separation makes an aggregate over weighted_score correct by construction rather than by the caller remembering to filter on scoring_form."
3331
+ - name: scored_at
3332
+ type: date
3333
+ nullable: true
3334
+ description: "Date of the effective assessment, from `scored_at` (the forward house form's field name — NOT `assessed_at`, which is the reverse family's file-level field). Date-typed: per the M-ADR 0205 §4.1 engine's TRY_CAST semantics, a prose value here is reported as a type nonconformance rather than aborting the load or being smoothed away — the `adrs.decision_date` case, which reverse practice already exercises."
3335
+ - name: corpus_ref
3336
+ type: string
3337
+ nullable: true
3338
+ description: "The commit the assessment read — the precise staleness anchor. NEW AUTHORING introduced by this change-set: no score written before it carries one, so this column is empty across both estates at introduction and fills forward as registries are rewritten. The reverse family already has the idea under a different name (`snapshot.source_revision`)."
3339
+ - name: staleness_basis
3340
+ type: string
3341
+ nullable: false
3342
+ description: Which anchor this row's staleness can be computed from — see the staleness_basis enum. Emitted by the builder, never authored. Exists so no consumer can state a staleness verdict without its basis.
3343
+ - name: review_run_id
3344
+ type: string
3345
+ nullable: true
3346
+ description: Identifier of the effective review run. Empty in the flat dialect, which records no run ids.
3347
+ - name: selection_method
3348
+ type: string
3349
+ nullable: true
3350
+ description: "How the effective review was chosen — see the score_selection_method enum. Empty in the flat dialect, which carries no selection_policy: absence means 'the only review', not 'policy unknown'."
3351
+ - name: scorer_provider
3352
+ type: string
3353
+ nullable: true
3354
+ description: Provider of the scoring agent (e.g. anthropic), from `current.scorer.provider`. Every score in this method is agent-produced, so which agent produced a judgment is part of the judgment, not metadata about it.
3355
+ - name: scorer_tool
3356
+ type: string
3357
+ nullable: true
3358
+ description: Tool the scoring agent ran in, from `current.scorer.tool`.
3359
+ - name: scorer_model
3360
+ type: string
3361
+ nullable: true
3362
+ description: Model that produced the assessment, from `current.scorer.model`. In the flat dialect the whole provenance block collapses to a free-text `scored_by:`, which lands here — so a value like 'intent-quality-review — rfms-connector-library' is expected and correct for flat-dialect rows, not a parse defect.
3363
+ - name: scorer_model_family
3364
+ type: string
3365
+ nullable: true
3366
+ description: Optional grouping field from `current.scorer.model_family`.
3367
+ - name: scorer_prompt_version
3368
+ type: string
3369
+ nullable: true
3370
+ description: Optional prompt-wrapper version from `current.scorer.prompt_version` — the input that makes a score reproducible.
3371
+ - name: flag_count
3372
+ type: int
3373
+ nullable: false
3374
+ description: "Number of heuristic flags raised. Normalises two authored dialects: `flags: {name: bool}` (count the true ones) and `flags_raised: [names]` (count the list). A per-flag child catalogue is deliberately NOT built — it arrives when a named query needs to filter by flag name, not by accretion."
3375
+ - name: hard_gate_triggered
3376
+ type: boolean
3377
+ nullable: false
3378
+ description: "Whether any hard gate fired. Normalises `hard_gates: {triggered, reasons}` and `hard_gates_triggered: [reasons]`."
3379
+ - name: required_actions_count
3380
+ type: int
3381
+ nullable: false
3382
+ description: Number of remediation actions the assessment recorded.
3383
+ - name: sdd_id
3384
+ type: string
3385
+ nullable: true
3386
+ description: SDD whose gate-registry authored this row. Soft FK to products.id — nullable because a registry can score targets in an SDD that emits no product row.
3387
+ - name: source_sdd_id
3388
+ type: string
3389
+ nullable: true
3390
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134; left empty by per-SDD builders.
3391
+ - name: platform_sdd_id
3392
+ type: string
3393
+ nullable: true
3394
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
3395
+ description: |
3396
+ Rubric assessment of a target artefact, one row per (target, rubric), per M-ADR 0205 §4.5. Source: `orchestration/gate-registry/<rubric>-scores.yaml` — the authored surface stays YAML because a score is a judgment, authored where it asserts intent; these rows are DERIVED and never edited.
3397
+ Models the EFFECTIVE score only — `current`, as chosen by the registry's `selection_policy`. The authored `reviews[]` history is deliberately not catalogued: variable-length history in a fixed-grain catalogue would give two answers to "what is the score". `review_run_id` and `selection_method` make each row name which review it is.
3398
+ THE BUILDER MUST READ TWO AUTHORED DIALECTS. All fifteen method-side templates specify a nested shape (`selection_policy` / `current` / `reviews`), but the live forward-estate data is overwhelmingly FLAT — `gate`/`weighted_score`/`scored_at`/`scored_by`/`scores`/`flags` directly on the entry. Measured 2026-08-06: reading only the template shape would catalogue 6 entries out of 204. The templates were modernised; the data was not migrated, and both are legitimate.
3399
+ `rubric_id` comes from the file's `registry_type` when declared, else the filename stem minus `-scores` — NEVER the container key, which is unreliable (4 of 10 forward registries drift from the method template) and non-unique (`domains` names both domain-architecture and intent-quality; `capabilities` names both feature-grounding and traceability-manifest).
3400
+ Scope: the weighted house form only. The banded reverse family is additive later via `scoring_form` (see that enum).
3401
+ foreign_keys:
3402
+ - column: sdd_id
3403
+ references: products.id
3404
+ nullable: true
3405
+ quality_score_dimensions:
3406
+ primary_key: id
3407
+ columns:
3408
+ - name: id
3409
+ type: string
3410
+ nullable: false
3411
+ description: "PK: {quality_score_id}__{dimension_key}."
3412
+ - name: quality_score_id
3413
+ type: string
3414
+ nullable: false
3415
+ description: The assessment this dimension belongs to.
3416
+ - name: rubric_id
3417
+ type: string
3418
+ nullable: false
3419
+ description: Denormalised from the parent so per-rubric dimension queries need no join.
3420
+ - name: target_kind
3421
+ type: string
3422
+ nullable: false
3423
+ description: Denormalised from the parent.
3424
+ - name: target_ref
3425
+ type: string
3426
+ nullable: false
3427
+ description: Denormalised from the parent.
3428
+ - name: dimension_key
3429
+ type: string
3430
+ nullable: false
3431
+ description: "The rubric's own dimension identifier, verbatim — `A1` where the rubric uses codes, `definition_precision` where it uses names. NOT normalised into a method-wide vocabulary: the key is how the rubric and its registry refer to the dimension, and rewriting it here would make the row untraceable to the rubric that produced it."
3432
+ - name: dimension_score
3433
+ type: number
3434
+ nullable: true
3435
+ description: Score on that dimension. Empty for an unscored entry (the templates author explicit nulls).
3436
+ - name: dimension_weight
3437
+ type: number
3438
+ nullable: true
3439
+ description: "Weight the rubric assigns the dimension, where discoverable. Usually EMPTY: weights live in the rubric document and the registry header comment, not per entry — so this column is honest about the fact that a weighted_score cannot currently be recomputed from these rows alone."
3440
+ - name: source_sdd_id
3441
+ type: string
3442
+ nullable: true
3443
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
3444
+ - name: platform_sdd_id
3445
+ type: string
3446
+ nullable: true
3447
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
3448
+ description: |
3449
+ One row per (target, rubric, dimension) — the per-dimension detail behind a `quality_scores` row, per M-ADR 0205 §4.5.
3450
+ A child catalogue rather than columns, and this is forced rather than stylistic: the fifteen rubrics carry FIFTEEN DISJOINT dimension vocabularies (`A1`-`A8`, `C1`-`C8`, `G1`-`G7`, `T1`-`T7`, `D1`-`D6`, `S1`-`S6`, `I1`-`I6`, plus five fully-named sets such as `definition_precision` and `intent_fidelity`) — 45 distinct keys measured in one estate alone. No fixed column set can hold them; serialised JSON in a cell would be unjoinable and break the relational metamodel; generic `d1..d8` columns would be lossy and re-create the positional-index failure class. A child table is what this metamodel already does for every one-to-many, and it joins natively on the M-ADR 0205 §4.1 engine.
3451
+ foreign_keys:
3452
+ - column: quality_score_id
3453
+ references: quality_scores.id
3454
+ nullable: false
3455
+ scaffolds:
3456
+ primary_key: id
3457
+ columns:
3458
+ - name: id
3459
+ type: string
3460
+ nullable: false
3461
+ description: "PK: the manifest's declared unit id (kebab-case slug). Unique per SDD; the aggregator namespaces cross-SDD ids exactly as for every other catalogue."
3462
+ - name: name
3463
+ type: string
3464
+ nullable: false
3465
+ description: Human-readable name of the unit of work, from the manifest.
3466
+ - name: status
3467
+ type: string
3468
+ nullable: false
3469
+ description: Authored lifecycle — see the scaffold_status enum. `closed` is a recorded act of the author (M-ADR 0207 §4.3); the delta instrument reports a closed scaffold whose delta is not zero, it never closes one.
3470
+ - name: source_path
3471
+ type: string
3472
+ nullable: false
3473
+ description: Repo-relative path of the manifest this row derives from, e.g. orchestration/scaffolds/payments-settlement.yaml.
3474
+ - name: corpus_ref
3475
+ type: string
3476
+ nullable: false
3477
+ description: "The commit the scaffold was declared against — the staleness anchor, mirroring quality_scores.corpus_ref (M-ADR 0207 §4.6: one staleness idiom, not two). Required: a manifest without one fails validation rather than emitting an unanchorable row."
3478
+ - name: manifest_schema
3479
+ type: string
3480
+ nullable: false
3481
+ description: The scaffold manifest format version the file declared (scaffold_schema field), so format evolution is diffable and a future migration can state its denominator.
3482
+ - name: sdd_id
3483
+ type: string
3484
+ nullable: true
3485
+ description: SDD whose manifest authored this row. Soft FK to products.id — nullable because a scaffold can be declared in an SDD that emits no product row.
3486
+ - name: source_sdd_id
3487
+ type: string
3488
+ nullable: true
3489
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134; left empty by per-SDD builders.
3490
+ - name: platform_sdd_id
3491
+ type: string
3492
+ nullable: true
3493
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
3494
+ description: |
3495
+ Forward scaffold declaration, one row per unit of work, per M-ADR 0207 §4.1. Source: `orchestration/scaffolds/*.yaml` — the authored surface stays YAML because a scaffold is a declaration of intent, authored where the work is scoped; these rows are DERIVED and never edited (M-ADR 0205 §4.0 governs unchanged).
3496
+ The scaffold states the catalogue shape a unit of work will comprise — its items are `scaffold_items` rows — and the declared-vs-derived delta against the built catalogues is the unit's definition of done: delta zero (structural) AND every realised artefact score-current (content, via `quality_scores`), per M-ADR 0207 §4.5. The unit is the change-set's declared delta; estate-level scaffold totality is an explicit non-goal (M-ADR 0207 §4.4), so an estate region no scaffold covers produces no finding.
3497
+ `corpus_ref` is REQUIRED — a scaffold without an anchor cannot carry a staleness verdict, and M-ADR 0207 §4.6 makes the anchor part of the declaration, not an optional refinement. Staleness itself is computed at coverage time (the scores idiom), never stored here.
3498
+ foreign_keys:
3499
+ - column: sdd_id
3500
+ references: products.id
3501
+ nullable: true
3502
+ column_enums:
3503
+ status: enums.scaffold_status
3504
+ scaffold_items:
3505
+ primary_key: id
3506
+ columns:
3507
+ - name: id
3508
+ type: string
3509
+ nullable: false
3510
+ description: "PK: {scaffold_id}__{item_kind}__{target_kind}__{target_ref}. Composite in one slug because the natural key is a quadruple and the rest of this schema keys on a single `id`."
3511
+ - name: scaffold_id
3512
+ type: string
3513
+ nullable: false
3514
+ description: The scaffold this item belongs to.
3515
+ - name: item_kind
3516
+ type: string
3517
+ nullable: false
3518
+ description: Grain of the declaration — see the scaffold_item_kind enum.
3519
+ - name: target_kind
3520
+ type: string
3521
+ nullable: false
3522
+ description: Catalogue the target should appear in, in the schema's own catalogue vocabulary. Validated against the schema by the builder; unknown values are convention findings carrying file, item and value.
3523
+ - name: target_ref
3524
+ type: string
3525
+ nullable: false
3526
+ description: "Identifier of the declared target in the vocabulary of its catalogue: the declared id for entity items, the repo-relative spec path for contract items (matching contracts.spec_path), the builder-computed {source}__{target} endpoint slug for edge items."
3527
+ - name: edge_source_ref
3528
+ type: string
3529
+ nullable: true
3530
+ description: "For edge items: the declared source endpoint, in the vocabulary of the edge catalogue's first FK column (schema declaration order). Empty for entity and contract items."
3531
+ - name: edge_target_ref
3532
+ type: string
3533
+ nullable: true
3534
+ description: "For edge items: the declared target endpoint, second FK column. Empty for entity and contract items."
3535
+ - name: state
3536
+ type: string
3537
+ nullable: false
3538
+ description: Resolution verdict — see the scaffold_item_state enum. Derived, never authored; recomputed on every build, so realisation flips rows exactly when the target lands.
3539
+ - name: source_sdd_id
3540
+ type: string
3541
+ nullable: true
3542
+ description: Originating SDD slug. Populated by the aggregator per M-ADR 0134.
3543
+ - name: platform_sdd_id
3544
+ type: string
3545
+ nullable: true
3546
+ description: The platform this row belongs to — sdd_id of its platform-root. Stamped by the aggregator per M-ADR 0208 §4.4 (preserve-if-set, fill rule by pull path); left empty by per-SDD builders. Added in 3.7.0.
3547
+ description: |
3548
+ One declared item of a scaffold — an entity, edge, or contract the unit of work promises — per M-ADR 0207 §4.1. Derived from the manifest's item list; `state` is the builder's resolution verdict against the same build's catalogue rows.
3549
+ THE POLYMORPHIC TARGET DECLARES NO FOREIGN KEY, by design (the quality_scores.target_ref precedent, taken further): a scaffold exists to reference targets BEFORE they exist. FK truth here is CONDITIONAL ON STATE — a `declared` item's (target_kind, target_ref) MUST NOT resolve in the built catalogues, a `realised` item's MUST — and the builder's resolution pass is what enforces it: it computes `state` FROM resolution, so a disagreement between state and resolution cannot be emitted by a conforming builder. The M-ADR 0207 §4.8 delta instrument re-derives the same verdict on the engine as its self-check.
3550
+ `target_kind` is the CATALOGUE NAME the target should appear in (services, capabilities, repo_contract, contracts, …) — bound to the schema's own catalogue list by the builder: an unknown target_kind is a loud convention finding, never a silently-dropped item (M-ADR 0207 §4.1). For `edge` items the endpoints are declared in edge_source_ref/edge_target_ref, mapped to the edge catalogue's FK columns in schema declaration order; target_ref then carries the builder-computed endpoint slug so the PK stays single-column.
3551
+ foreign_keys:
3552
+ - column: scaffold_id
3553
+ references: scaffolds.id
3554
+ nullable: false
3555
+ column_enums:
3556
+ item_kind: enums.scaffold_item_kind
3557
+ state: enums.scaffold_item_state