Appendix B - 8. Domain registries
The Structure of Domain registries — its shape at a glance:
Each registry is one frozen typed record set. Tools read it for the fact; a doc generator emits the presentation surface from it; a parity lint fails when a consumer or generated doc diverges.
erDiagram
REGISTRY ||--o{ ENTRY : "holds"
REGISTRY {
string slice PK
}
ENTRY {
string key PK
string slice FK
string value
}
Accessible description: a registry is keyed by its domain slice and holds many entries, each a key-value fact within that slice. Tools read the entries and a doc generator emits from them, with a parity lint holding both to the registry.
Projected from the catalogue entry system-models / Domain registries.
On this page: Intent · Motivation · Applicability · Structure · Sample Code · Consequences · Example use within DocAble · Related Patterns
Intent
Intent — A set of frozen, typed registries for the system's domain facts (the supported filetypes, the WCAG coverage gaps, the periodic-GC cron entries, the UX write-authority surfaces, the competitor set, the CLAUDE.md rule metadata), each the single source of truth for its slice.
Motivation
Domain facts get restated in code, docs, and dashboards: "which four filetypes do we support," "which WCAG SCs are coverage-gaps," "which cron entries run," "who may write UX surface X," "who are our competitors," "what metadata does each CLAUDE.md rule carry." Restated, they drift: a filetype list diverges, a rule's metadata goes stale, a competitor doc is out of date. Each is a small correctness or a stale-doc failure, multiplied across many domain slices.
Applicability
- A typed registry per domain fact with the fields its consumers need.
- Consumers that read it (dispatch/checkers/generators) rather than hardcoding.
- A coverage/parity lint + a doc-derived pin per registry.
Structure
The Structure diagram appears at the top of this page.
Sample Code
Each registry is a frozen set of typed entries. Consumers query it and a doc is generated from it, so the fact has one home; a parity check fails the build when a consumer's copy diverges from the registry.
from dataclasses import dataclass
import sys
@dataclass(frozen=True)
class Filetype:
ext: str
label: str
SUPPORTED = frozenset({Filetype("pdf", "PDF"), Filetype("docx", "Word")})
def is_supported(ext: str) -> bool:
return any(f.ext == ext for f in SUPPORTED) # consumers query, never hardcode
def parity(doc_listed: set[str]) -> list[str]:
"""A generated doc's listed set must equal the registry (neither may drift)."""
reg = {f.ext for f in SUPPORTED}
findings = [f"doc lists '{e}' not in registry" for e in sorted(doc_listed - reg)]
findings += [f"registry has '{e}' the doc omits" for e in sorted(reg - doc_listed)]
return findings
if __name__ == "__main__":
# `read_doc_listed` parses the generated doc's presented set.
findings = parity(read_doc_listed())
for f in findings:
print(f"REGISTRY-DRIFT: {f}")
sys.exit(1 if findings else 0)
Consequences
- Many small registries to maintain — the cost is breadth, not depth; each is simple but each is a surface.
- Frozen sets resist expedient edits — changing "the supported four" is a deliberate model change.
Example use within DocAble
- The supported-filetypes, WCAG-gap, periodic-GC-cron, UX-write-authority, competitor, and rule-metadata registries.
- Their generators (e.g. the competitor-catalog generator) and coverage/parity lints.
Related Patterns
- Bridge — agents/checkers read these facts (agent side) ◀──▶ they govern & generate product surfaces (WCAG scope, competitor docs, cron behaviour) (product side).
- Consumer — the rule-metadata registry feeds the rule-index; the WCAG-gap registry feeds the standards rule-engine.
- Counterpart — drift-parity-gates: each registry's coverage/parity lint.