Skip to content
⚠ Pre-1.0 — specs and API are under active development and may change without notice. Follow announcements.

Versioning & data packaging

TextRefs versions three things that move at different speeds, and archives each independently:

Train Lives in Tag format Zenodo concept DOI
Standard + site textrefs/textrefs.org vMAJOR.MINOR.PATCH[-pre] TextRefs Standard
Registry data textrefs/registry vYYYY.MM.N TextRefs Registry
Data-package version inside datapackage.json SemVer without leading v (carried within registry deposit)

The site repository couples the spec, JSON-LD context, Zod schemas, and Astro site under a single tag because pre-1.0 the site is the spec’s reference rendering; splitting them now would create empty changelogs and confuse Zenodo metadata. Registry data is decoupled — record changes flow on their own cadence — and lives in a separate repository because the Zenodo–GitHub integration mints one concept DOI per repository. The two repositories are cross-linked via .zenodo.json related_identifiers.

The site repository includes textrefs/registry as a git submodule at data/. The registry uses main as its working branch. The site pins a specific registry main commit through the submodule pointer, and its compiler builds registry dumps from that pinned content for reproducible site releases.

Each /standard/* page carries a maturity field in its frontmatter, encoding intent alongside the SemVer tag (which encodes pre-release status):

Value Meaning
working-draft Unstable. Data model and prose may change without notice and without a version bump while the core is settled.
candidate-recommendation Stable enough to implement against. Breaking changes still require a major version bump.
recommendation Stable recommendation. Breaking changes require a major version bump and a new document.
superseded Replaced by a later version. Retained at its tagged URL for archival lookup.

Transitions:

  • 0.x releases stay working-draft regardless of any -draft suffix on the tag.
  • First 1.0.0-rc.1 enters candidate-recommendation.
  • 1.0.0 enters recommendation.
  • Breaking schema changes require a major version increment.
  • Compatible new fields require a minor version increment.
  • Corrections that do not change schema shape require a patch increment.

Generated dumps use this directory layout:

dist/dump/datapackage.json
dist/dump/works.jsonl
dist/dump/citation-systems.jsonl
dist/dump/references.jsonl
dist/dump/mappings.jsonl

Registry exports are organized by object type. This gives consumers stable file names, simple streaming imports, and one predictable place to find each record type. Resolver targets are embedded in reference records. Relationships are represented inside records through standard fields such as key, work_key, citation_system_key, subject, and target.

TextRefs Standard/site GitHub Releases are the primary distribution point for generated registry dumps. The dump is built from the data/ submodule pointer committed in that release. Each released tag in either repository is also deposited in the TextRefs Zenodo community for long-term archival preservation and DOI minting. Cite the version DOI when referring to a specific archived dump.

Each datapackage.json MUST include:

  • profile: data-package.
  • name: textrefs-registry.
  • version: SemVer package version.
  • licenses: SPDX identifier CC0-1.0 for registry data.
  • resources: one resource per JSONL file.
  • schema: field descriptors for each resource.

Records do not carry their own SemVer. The registry is append-only from promotion onward, with status transitions (draftcandidateactivedeprecated / withdrawn / blocked). The draft tier is pre-persistence: see Draft records and retraction. Consumers pin to a registry tag (or its DOI) for reproducibility. Identifier-level changes to promoted records are expressed via tombstones, below.

Records at status draft have not been promoted and carry no persistence promise (Specification §11). A draft MAY be corrected — changing an identity field mints a different id, and the previous IRI ceases to resolve — or retracted, meaning the record is deleted outright. Retraction MUST NOT create a tombstone. Because identifiers are deterministic, a retracted tuple that is later re-proposed regains the same UUID; a reappearing id does not imply continuity of curation history.

Draft records appear in exports inside the same .jsonl files as their type, with status as the signal — the same convention tombstones use. Consumers MUST NOT rely on a draft record persisting across releases and SHOULD filter on status when they need only promoted records. Rendered draft pages SHOULD be clearly flagged and excluded from search indexing.

Registry identity is permanent once promoted: the IRI of a Work, CitationSystem, CanonicalReference, or MappingAssertion MUST continue to resolve once the record has been published at status candidate or higher. Re-minting a promoted record (renaming a key, correcting a locator that changes the content-derived UUID, splitting/merging records) MUST be expressed by tombstoning the old record and minting a successor.

Tombstones use one status value plus one optional field. The old record stays in the data tree with status: withdrawn. If a successor exists, the tombstoned record carries its IRI in superseded_by (dcterms:isReplacedBy in the published context). Consumers follow superseded_by to find the successor. MappingAssertions are reserved for genuine work-level equivalence claims and MUST NOT be used for succession links.

Tombstones are full records, not deletions. The old record retains every other field unchanged; status flips to withdrawn, modified is bumped, and superseded_by is set when a successor exists. The successor is a separately authored record at the new IRI.

Old IRI HTML pages render a tombstone banner; when superseded_by is present the banner links the successor IRI. The .json JSON-LD sibling returns the withdrawn record verbatim. Old IRIs are not hard-redirected: archival consumers MUST be able to inspect the tombstone payload.

Tombstones MUST appear in monthly exports inside the same .jsonl file as their type. The status field is the signal — no separate tombstones.jsonl.

The compiler enforces: an active CanonicalReference MUST NOT reference a tombstoned Work or CitationSystem through work_key or citation_system_key. superseded_by MUST only appear on records whose status is withdrawn or blocked.

Analogously, a promoted (candidate or higher) record MUST NOT reference a draft Work or CitationSystem through its keys: systems and works are promoted before or together with the records that depend on them.

The compiler maintains a presentational alias map (multiple lookup paths — external identifiers, {work_key}/{locator} pairs — pointing at the same canonical record). Tombstones handle identity changes (the record itself is no longer canonical). These are distinct mechanisms and MUST NOT be conflated.

Exports MUST NOT contain primary full text, commentary, apparatus, or rights metadata that implies TextRefs may redistribute copyrighted text. Disputed resolver endpoints remain in exports with status: blocked.