# Canonical Records

Canonical records are the framework-independent data contracts for VyDex Entries, Topic Trails, Methodology versions, About content, publication events, Entry snapshots, and release descriptors. This page is for maintainers, technical users, and coding agents that need to validate records or change the domain model safely.

## Purpose and Ownership

The canonical-record system gives stored and singleton content a stable shape that loaders, publication workflows, release construction, rendering, and exports can share. It owns:

- Stable machine values and their TypeScript and Zod representations.
- UUIDv7 identities, public slugs, dates, timestamps, and Methodology version primitives.
- Strict schemas for current durable records and Stage 1 singleton content.
- Entry-local source citations and their evidence metadata.
- Safe prose profiles for plain text and Markdown fields.
- Record-local validation and aggregate validation across record collections.
- Structured diagnostics that callers can retain or format.

It does not own:

- Reading or writing record files.
- Choosing record storage locations.
- Generating IDs, slugs, revision numbers, snapshots, changelog events, or releases.
- Comparing revisions or deciding material activity.
- Rendering pages, routes, canonical URLs, or exports.
- Terminal output, filesystem logging, telemetry, or process exit behavior.

## Record Family

`EntryV1` is the immutable legacy contract for the original authored claim, evidence assessment, review state, Entry State, dates, Frontier Delta, details, significance, caveats, and embedded sources. `EntryV2` is the current strict contract: it keeps the shared identity, assessment, relationship, date, and source fields, adds `entry_schema_version: "2.0.0"`, and replaces the v1 editorial groups with `summary`, `reality_check`, `context`, `takeaway`, `claim_status_rationale`, and `evidence_strength_rationale`. The exported `Entry` type and `entrySchema` refer to v2; `EntryLike` is the explicit v1-or-v2 boundary used by history and publication code.

A `TopicTrail` provides a durable identity, public name, description, current slug, and historical aliases. Entries point to Topic Trails by UUID; trails do not store Entry membership or derived activity counts.

A `Methodology` stores a public version and complete public content in named sections. Its structure owns lists, examples, definitions, and hierarchy, while each Markdown leaf supplies prose only.

An `AboutRecord` stores the complete structured Stage 1 About content. It is a singleton without its own UUID because other records do not reference or version it. Its related-link fields contain titles and descriptions; [Release Construction](../release-lifecycle/release-construction.md) supplies their canonical destinations.

A `MethodologyPublicationEvent` records a separately authored Methodology Changelog event. Each event references one canonical Methodology version by UUID and requires a genuine RFC 3339 UTC `published_at` timestamp. Production validation requires exactly one resolved publication event for every retained Methodology version, including historical `1.0.0` and current `2.0.0`. The public calendar date is derived later from the timestamp, while Methodology `effective_date` remains a separate value describing when the rules apply.

An `EntryPublicationSnapshot` stores revision metadata with a complete validated Entry payload. Legacy v1 snapshots intentionally have no discriminator and retain their original bytes. New v2 snapshots require `snapshot_schema_version: "2.0.0"` and `publication_state`, whose values are `public` or `removed`. The parser selects the v1 or v2 snapshot schema from that discriminator; for a legacy snapshot, publication state is derived from its embedded v1 `entry_state`. The separate [Publication Revisions](./publication-revisions.md) system validates history, constructs snapshots, and derives activity without changing the canonical contract.

`ReleaseMetadata` contains a durable release ID and generation timestamp. The release constructor validates these explicit caller-supplied values and uses them unchanged; descriptor creation and persistence remain outside the canonical-record system.

Sources remain embedded in their parent Entry. A citation ID is unique within that Entry, but it is not a global durable identity and does not create a normalized evidence graph.

## Validation Flow

1. A caller passes an unknown value and may attach a filename for diagnostic context.
2. The record-specific validator checks the strict schema, controlled values, text profiles, dates, identifiers, required fields, and record-local conditional rules.
3. Successful parsing returns a typed record. Leading and trailing text whitespace may be trimmed, but meaningful internal Markdown structure is preserved.
4. Aggregate validation receives collections of locally valid durable records and checks global UUID uniqueness, Entry and Topic Trail slug namespaces, relationships, and snapshot consistency.
5. The caller must select either authoring validation or Stage 1 production validation. Production validation applies the current release boundary to the newest snapshot; legacy v1 Entry State remains a compatibility field, while v2 publication visibility is carried by snapshot `publication_state`.
6. Release construction separately validates singleton cardinality and cross-record rules for About content and the Methodology publication event.
7. Any blocking issue returns a structured diagnostic instead of writing to the terminal or filesystem.

Validation continues across independent records where it is safe to do so, allowing one run to report unrelated failures together. Invalid records are not silently repaired, and unknown object fields are rejected rather than discarded.

## Text and Markdown Boundaries

Plain-text fields are trimmed, non-empty, single-line values and cannot contain Markdown, HTML, or MDX formatting.

Entry claims and Caveats use inline Markdown. They may contain ordinary inline formatting, links, and inline code, but they cannot introduce headings, lists, tables, blockquotes, fenced code, images, HTML, or MDX. Claims must remain on one line; their one-sentence rule is editorial rather than heuristic validation.

Entry detail, Frontier Delta, and Significance fields accept block Markdown for paragraphs, lists, tables, blockquotes, links, and code. Headings remain forbidden because the record structure owns page hierarchy.

Methodology and About paragraph Markdown accepts one or more prose paragraphs with safe inline formatting. Lists, tables, headings, examples, and definition rows come from the surrounding structured fields and cannot be recreated inside a Markdown leaf.

All Markdown profiles reject images, raw HTML, executable MDX constructs, and unsafe link protocols. Literal HTML or JSX inside inline code or fenced code remains text and does not trigger a false failure.

## Failure Behavior

Validation diagnostics identify the record type, field path, violated rule, and invalid value when one is available. They preserve a caller-supplied filename, include a record ID when one can be read, and may identify a related record for collisions or broken relationships.

Every rule implemented today emits a blocking `error`. The diagnostic type reserves `warning` for future editorial or release checks, but the canonical-record system does not currently produce warnings.

## Internal Edge Cases

- Calendar dates must use `YYYY-MM-DD` and represent real dates; matching the text pattern alone is not enough.
- Snapshot, Methodology publication-event, and release timestamps must be RFC 3339 UTC values using `Z`.
- Current slugs and aliases share one collision-free namespace within Entries and another within Topic Trails. The two route families do not share a namespace.
- Domain, alias, secondary Topic Trail, citation ID, and per-source Evidence Type duplicates are rejected where their contracts require uniqueness.
- Review reasons are required only while follow-up is active and must be `null` for stable reviews.
- Potential Significance becomes required when specified Claim Status, Evidence Strength, or source Evidence Type conditions apply.
- Evidence Strength scores come from one stable mapping and cannot be authored separately in an Entry or Methodology.
- Topic Trail and claim sentence requirements remain editorial because automated sentence segmentation would reject valid technical prose.

## Cross-System Edge Cases

- Durable UUIDv7 IDs share one global namespace across current Entries, Topic Trails, Methodologies, snapshot revisions, and release descriptors. Entry-local citation IDs are excluded.
- `AboutRecord` has no durable ID, and a Methodology publication event references an existing Methodology ID rather than introducing another durable identity.
- The Methodology `1.0.0` publication timestamp is a one-time migration value derived from its existing stable UUIDv7. Future publication events must author and persist their genuine timestamp when publication occurs; UUID decoding is not the publication workflow.
- Entry relationships use UUIDs, never titles, filenames, names, or slugs.
- Every primary and secondary Topic Trail reference and every Methodology reference must resolve during aggregate validation.
- A snapshot’s outer Entry and Methodology IDs must match its embedded Entry, and its stored Methodology public version must match the referenced Methodology record.
- `EntryV1` recognizes `removed` for durable compatibility. `EntryV2` has no authored Entry State; v2 snapshot `publication_state` carries public/removal lifecycle state, including historical removal snapshots.
- The canonical loader retains filenames and raw invalid JSON for preview diagnostics, but filesystem access stays in the adapter boundary.
- Release construction may combine valid canonical records into resolved public data, but it must not repair or widen the stored contracts. [Dataset Generation](../release-lifecycle/dataset-generation.md) narrows current Entry v2 state into the separate public Dataset `2.0.0` contract; the v1 generator remains available for legacy releases and archived output.
- The [Entry Preview](../public-interface/entry-preview.md) consumes validated current Entry fields and the exhaustive public-label maps. It displays the first authored Domain as preview priority, includes the Entry v2 Summary, and does not expose v1 Review Status or Entry State.
- The [Stage 1 Topic Trail Page](../public-interface/stage-1-topic-trail-page.md) consumes resolved Trail Names, descriptions, slugs, and Entry relationships. It does not load canonical records directly or derive membership from filenames.

## Invariants

- Stable machine values remain lowercase `snake_case`; Claim Status, Evidence Strength, Review Status, Domain, Evidence Type, and Source Role public labels come from exhaustive framework-independent maps rather than presentation-layer string conversion.
- Evidence Strength is not probability, confidence, importance, quality, or ranking.
- Review Status describes maintenance need, not claim truth.
- Entry State remains separate from Claim Status in v1; v2 publication visibility is a snapshot lifecycle concern rather than an authored Entry field.
- Caveats remain separate from status, strength, Frontier Delta, and Significance.
- Sources remain embedded in Entries during Stage 1.
- Structured relationships use durable IDs, while slugs remain public routing identifiers.
- Every Domain attached to an Entry remains ordered authored data. Entry Preview uses the first value only as display priority, not as a semantic primary Domain, while Dataset generation applies its controlled public ordering without changing the canonical record.
- Domain validation does not depend on Astro, filesystem access, or logging.

## Implementation Landmarks

- `src/domain/canonical-records/` — Stable values, primitives, prose profiles, and record schemas.
- `src/domain/cross-record-validation/` — Diagnostic conversion and aggregate invariants.
- `src/domain/index.ts` — Public framework-independent domain entry point.
- `tests/domain/` — Valid fixtures, schema checks, Markdown safety, singleton content, and aggregate validation tests.

Publication behavior belongs to `src/domain/publication-revisions/` and `src/domain/material-activity/`. Resolved public data belongs to `src/domain/release-construction/`. See [Publication Revisions](./publication-revisions.md) before changing snapshot history and [Release Construction](../release-lifecycle/release-construction.md) before changing derived release values.

## Before Changing Canonical Records

Check:

- Whether a field belongs to the authored record or should be derived by publication, release, routing, or export code.
- Whether a new relationship uses a durable UUID rather than a public label or slug.
- Whether a controlled value change also requires exhaustive label maps, Methodology definition keys, conditional rules, and tests to change.
- Whether an Entry Preview change preserves authored Domain order and full Entry and Dataset Domain output.
- Whether a prose change preserves the distinction between plain text, inline Markdown, Entry block Markdown, and Methodology Markdown.
- Whether an aggregate rule can report the record, path, invalid value, violated rule, and related identity without filesystem access.
- Whether singleton content should remain outside the durable UUID namespace.
- Whether a Methodology publication event keeps `published_at` separate from the referenced Methodology's `effective_date` and avoids inferring future timestamps from UUIDs or repository metadata.
- Whether compatibility behavior for aliases, snapshots, or removed Entries would be broken.

Read [Static Application Foundation](../static-application-foundation.md) before changing dependency direction, root tooling, or the Astro/domain boundary.
