Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,28 @@ A contribution does not create a claim to acceptance, prioritization, publicatio

Changes are routed to one of three tracks:

- **Technical review** — typos, formatting, broken links, minor metadata, `last_checked` updates, uncontested aliases, build / tooling fixes. Needs automated validation and one technical reviewer.
- **Expert review** — new works, new citation systems, new corpora, contested mappings, changes to deterministic ID inputs, status changes (`active` / `deprecated` / `withdrawn` / `blocked`). Needs technical validation, a documented rationale with sources, and at least one expert reviewer.
- **Technical review** — typos, formatting, broken links, minor metadata, `last_checked` updates, uncontested aliases, build / tooling fixes, and merging new registry data as `draft`. Needs automated validation and one technical reviewer.
- **Expert review** — new works, new citation systems, new corpora, contested mappings, changes to deterministic ID inputs, status changes (promotion `draft` → `candidate`, and `active` / `deprecated` / `withdrawn` / `blocked`). Needs technical validation, a documented rationale with sources, and at least one expert reviewer.
- **Board reservation** — takedowns, blocking, licence policy, and other legal or policy-sensitive matters. Decided by the Association Board.

```mermaid
flowchart TD
S["Contribution<br/>(issue or PR)"] --> T{Triage}
T -->|"typos, formatting, links, metadata, tooling"| TR[Technical review]
T -->|"new work / system / corpus, contested mapping, ID inputs, status change"| ER[Expert review]
T -->|"new work / system / corpus, contested mapping, ID inputs, status change / promotion"| ER[Expert review]
T -->|"takedown, blocking, licence / policy"| BR[Board reservation]
TR --> V{"Automated validation<br/>+ 1 technical reviewer"}
ER --> V2{"Validation + rationale and sources<br/>+ 1 expert reviewer"}
V -->|pass| A([Accepted / merged])
V -->|pass| A(["Accepted / merged<br/>(new data lands as draft)"])
V -->|fail| R([Rejected, with reason])
V2 -->|pass| A
V2 -->|fail| R
BR -->|decision| A
BR -->|decision| R
```

New registry records enter at `status: draft` after technical review; they stay retractable until an expert review promotes them to `candidate`, which permanently freezes their identifier (see the [versioning rules](https://textrefs.org/standard/versioning/) and governance §5).

## Local development

Prerequisites: Node 24 and npm.
Expand Down
2 changes: 1 addition & 1 deletion api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ components:
pattern: '^\d{4}-\d{2}-\d{2}$'
Status:
type: string
enum: [candidate, active, deprecated, withdrawn, blocked]
enum: [draft, candidate, active, deprecated, withdrawn, blocked]
AdminMetadata:
type: object
required: [status, created, modified]
Expand Down
72 changes: 72 additions & 0 deletions decisions/ADR-0003-draft-lifecycle-ephemeral-identity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# ADR-0003: Review lifecycle with an ephemeral `draft` state

- **Status:** Proposed
- **Date:** 2026-07-05
- **Deciders:** @maehr
- **Tags:** spec, governance

## Context and problem statement

Every published record carries the full persistence promise: IRIs are permanent once minted (identifier-syntax § Immutability, specification §11), and any identity correction requires tombstone ceremony (versioning § Tombstones). There is no state in which a record is visible in the registry but still retractable — a wrong locator cannot simply be fixed, a bad entry cannot simply vanish. Issue [#22](https://github.com/textrefs/textrefs.org/issues/22) proposes such a state.

The governance regulation defines review _tracks_ (§4: technical / expert / board) but no in-registry review _lifecycle_: nothing distinguishes freshly imported, unreviewed data from records that have passed expert review.

Since ADR-0002, identity is pure math: the reference UUID is offline-computable from `(work_key, citation_system_key, locator)`. That separates **identity** (which never mutates — a tuple always hashes to the same UUID) from **registration** (what the registry endorses and promises). It also puts governance §6.4 ("provisional or uncertain objects receive generated IDs") in conflict with the deterministic-identity model.

## Decision drivers

- Reviewers need to browse rendered records and check resolver targets _before_ the registry commits to permanence.
- Corrections during review should be cheap: fix the tuple, the wrong UUID disappears — no tombstone debt for data nobody ever relied on.
- The persistence promise must stay absolute where it applies; a promise with fuzzy edges is worse than a narrower hard one.
- ADR-0002's offline computability must hold at every lifecycle stage; re-minting ceremonies contradict it.
- The DE governance regulation is the legally binding text; the model must be expressible there in sync.

## Considered options

1. **Attach the promise at `candidate → active`** — no new status; `candidate` becomes retractable. Silently weakens what `candidate` means today and leaves no distinction between "just imported" and "proposed for acceptance".
2. **Never publish ephemeral records (PR-only review)** — everything published stays permanent. Reviewers cannot browse rendered records; long-running review branches become the de-facto ephemeral state.
3. **v4 provisional IDs, re-minted to v5 at promotion** (governance §6.4 as written) — ephemerality visible in the ID itself, but breaks offline computability for drafts and makes every promotion an ID migration.
4. **New `draft` status; promise attaches at `draft → candidate` promotion; deterministic v5 throughout.**

## Decision

We choose **Option 4**. The status ladder becomes `draft` → `candidate` → `active` → `deprecated` / `withdrawn` / `blocked`, and the identifier-persistence promise attaches at the **promotion** event (`draft → candidate`), not at publication.

**Entry.** New data enters the registry as `status: draft` after technical review (governance §4.1: schema validation, `locator_regex`, no full text). Draft records are rendered with a prominent "draft — not a persistent identifier" treatment (noindex, excluded from sitemap and search) and appear in exports with `status` as the signal — the same convention tombstones use.

**Ephemerality.** Draft records are excluded from the persistence policy. They MAY be corrected — changing an identity field mints a different id; the old UUID simply disappears — or retracted: the record is deleted, its IRI ceases to resolve, and **no tombstone** is created. Because identity is deterministic, a retracted tuple that is later re-proposed regains the same UUID by construction; there is no identity split and no way to "lose" an identity by retraction.

**Promotion.** `draft → candidate` requires expert review (governance §4.2: rationale, sources, attestation of the reference points, canonical-form check). Promotion changes `status` only — it MUST NOT change identity fields, so the IRI survives promotion unchanged. From promotion onward the record is permanent and the tombstone rules of versioning apply. `candidate → active` and the tombstone states are unchanged.

**Granularity.** References share their work's status (the compiler assigns `status` from the work record), so the promotion unit is a work together with its references; citation systems and mappings promote individually. A promoted record MUST NOT reference a draft `Work` or `CitationSystem` through its keys — systems and works are promoted before or together with the references that depend on them.

**ID policy.** All registry records carry deterministic v5 identifiers at every stage. Provisionality is expressed by `draft` status, not by the ID algorithm; governance §6.3/6.4 is amended accordingly.

## Consequences

### Positive

- The registry gains a reviewable, retractable tier without weakening any existing promise: permanence attaches at promotion and is absolute from there.
- Review-stage corrections cost nothing: no tombstone debt for data nobody ever relied on.
- One lifecycle connects the governance review tracks (§4) to the status model (§5): technical review gates entry, expert review gates permanence.
- The earlier wish to downgrade the unreviewed seed data below `candidate` becomes meaningful and lands as a follow-up.

### Negative / trade-offs

- Dump consumers MUST filter by `status` if they need only promoted records; a draft's presence in one release says nothing about the next.
- A retracted draft's IRI returns 404 rather than a tombstone page — link rot is possible for anyone who cited a draft despite the flagging.
- Re-proposal reuses the same UUID; consumers must not treat a reappearing id as continuity of curation history.
- Two texts (EN + legally binding DE governance) must be amended in sync.

### Follow-up actions

- [ ] Compiler invariant: a promoted (`candidate`+) record MUST NOT reference a draft `Work`/`CitationSystem` (extend the tombstone invariant in `scripts/compile.ts`).
- [ ] Draft rendering: banner, `noindex`, sitemap/search exclusion on record pages (extend the `Tombstone.astro` pattern).
- [ ] Downgrade the current unreviewed seed data to `draft` in `textrefs/registry`.
- [ ] Optional CI persistence check: promoted ids diffed against the previous release dump.

## Links

- Related ADRs: ADR-0002 (deterministic identity from the semantic tuple — the identity/registration separation this builds on)
- Related issues / PRs: textrefs/textrefs.org#22, textrefs/textrefs.org#15
- External references: governance regulation §4–§6 (`/association/governance/`)
12 changes: 8 additions & 4 deletions src/content/docs/association/governance.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ A technical review is usually sufficient for:
- minor metadata corrections;
- updates to `last_checked` fields;
- adding uncontested aliases;
- documentation corrections without expert implications.
- documentation corrections without expert implications;
- entry of new records as `draft` (merging validated data into the registry).

Prerequisites:

Expand All @@ -118,6 +119,7 @@ An expert review is required for:
- contested mapping statements;
- conflicting external identifiers;
- changes with significant expert or reputational impact;
- promotion of records from `draft` to `candidate` (the point at which the persistence guarantee attaches);
- status changes to `active`, `deprecated`, `withdrawn`, or `blocked`, where these are subject-matter decisions.

Prerequisites:
Expand All @@ -143,6 +145,7 @@ The Board decides or confirms:

### 5.1 General record status

- **draft:** work-in-progress record; correctable or retractable without a tombstone; excluded from the persistence guarantee;
- **candidate:** proposed record, not yet fully reviewed;
- **active:** valid and recommended;
- **deprecated:** no longer recommended, but retained for historical reasons;
Expand All @@ -151,6 +154,7 @@ The Board decides or confirms:

### 5.2 Mapping status

- **draft:** work-in-progress mapping; correctable or retractable without a tombstone;
- **candidate:** proposed mapping;
- **active:** reviewed and recommended mapping;
- **deprecated:** mapping no longer recommended;
Expand All @@ -161,7 +165,7 @@ Contested mappings remain in the appropriate schema status and carry the documen

### 5.3 Tombstone principle

Published IDs are, as a matter of principle, not hard-deleted.
Promoted IDs (status `candidate` or higher) are, as a matter of principle, not hard-deleted. Records in `draft` status may be retracted without a landing page.

In the event of withdrawal, blocking, or deprecation, a landing page is retained with:

Expand All @@ -176,8 +180,8 @@ In the event of withdrawal, blocking, or deprecation, a landing page is retained

1. Primary TextRefs IDs are independent HTTP URIs.
2. External identifiers such as CTS URNs, Wikidata IDs, DOIs, ARKs, Perseus URLs, or Scaife URLs are not primary TextRefs IDs.
3. Stable and established references may receive deterministic IDs.
4. Provisional or uncertain objects receive generated IDs.
3. All registry records carry deterministic IDs computable from their identity fields.
4. Provisional records are expressed through the `draft` status, which is excluded from the persistence guarantee; their IDs may disappear or change until promotion.
5. Once published, IDs are not changed merely because labels, titles, aliases, or external mappings are improved.
6. Human-readable citation URLs are aliases and may be redirected, changed, or deprecated; primary IDs remain authoritative.

Expand Down
12 changes: 8 additions & 4 deletions src/content/docs/de/association/governance.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ Ein technischer Review genügt in der Regel für:
- kleinere Metadatenkorrekturen;
- Aktualisierung von `last_checked`-Feldern;
- Ergänzung unstrittiger Aliase;
- Dokumentationskorrekturen ohne fachliche Tragweite.
- Dokumentationskorrekturen ohne fachliche Tragweite;
- Aufnahme neuer Datensätze als `draft` (Merge validierter Daten in das Register).

Voraussetzungen:

Expand All @@ -118,6 +119,7 @@ Ein fachlicher Review ist erforderlich für:
- strittige Mapping-Aussagen;
- widersprüchliche externe Identifikatoren;
- Änderungen mit erheblicher fachlicher oder reputationsbezogener Wirkung;
- Promotion von Datensätzen von `draft` zu `candidate` (der Zeitpunkt, an dem die Persistenzzusage beginnt);
- Statusänderungen zu `active`, `deprecated`, `withdrawn` oder `blocked`, soweit fachlich begründet.

Voraussetzungen:
Expand All @@ -143,6 +145,7 @@ Der Vorstand entscheidet oder bestätigt:

### 5.1 Allgemeine Datensatzstatus

- **draft:** Datensatz in Arbeit; ohne Tombstone korrigierbar oder zurückziehbar; von der Persistenzzusage ausgenommen;
- **candidate:** vorgeschlagener Datensatz, noch nicht vollständig geprüft;
- **active:** gültig und empfohlen;
- **deprecated:** nicht mehr empfohlen, aber aus historischen Gründen erhalten;
Expand All @@ -151,6 +154,7 @@ Der Vorstand entscheidet oder bestätigt:

### 5.2 Mapping-Status

- **draft:** Zuordnung in Arbeit; ohne Tombstone korrigierbar oder zurückziehbar;
- **candidate:** vorgeschlagene Zuordnung;
- **active:** geprüfte und empfohlene Zuordnung;
- **deprecated:** nicht mehr empfohlene Zuordnung;
Expand All @@ -161,7 +165,7 @@ Strittige Mappings behalten den passenden Schema-Status und führen Begründung,

### 5.3 Tombstone-Prinzip

Publizierte IDs werden grundsätzlich nicht hart gelöscht.
Promovierte IDs (Status `candidate` oder höher) werden grundsätzlich nicht hart gelöscht. Datensätze im Status `draft` können ohne Landing Page zurückgezogen werden.

Bei Rückzug, Sperrung oder Deprecation bleibt eine Landing Page erhalten mit:

Expand All @@ -176,8 +180,8 @@ Bei Rückzug, Sperrung oder Deprecation bleibt eine Landing Page erhalten mit:

1. Primäre TextRefs-IDs sind unabhängige HTTP-URIs.
2. Externe Identifikatoren wie CTS URNs, Wikidata-IDs, DOIs, ARKs, Perseus-URLs oder Scaife-URLs sind keine primären TextRefs-IDs.
3. Stabile und etablierte Referenzen können deterministische IDs erhalten.
4. Provisorische oder unsichere Objekte erhalten generierte IDs.
3. Alle Registereinträge tragen deterministische IDs, die aus ihren Identitätsfeldern berechenbar sind.
4. Provisorische Einträge werden über den Status `draft` ausgedrückt, der von der Persistenzzusage ausgenommen ist; ihre IDs können bis zur Promotion verschwinden oder sich ändern.
5. Einmal publizierte IDs werden nicht geändert, nur weil Labels, Titel, Aliase oder externe Mappings verbessert werden.
6. Lesbare Citation-URLs sind Aliase und können umgeleitet, geändert oder deprecated werden; primäre IDs bleiben massgeblich.

Expand Down
4 changes: 3 additions & 1 deletion src/content/docs/standard/identifier-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ The canonical URI is `https://textrefs.org/id/mapping/{uuid}`.

## Immutability

Once a deterministic identifier is published, it is permanent. If a record is found to be wrong, it MUST be marked `deprecated`, `withdrawn`, or `blocked`; the original URI MUST remain dereferenceable as a tombstone.
Once a deterministic identifier is published at status `candidate` or higher, it is permanent. If a promoted record is found to be wrong, it MUST be marked `deprecated`, `withdrawn`, or `blocked`; the original URI MUST remain dereferenceable as a tombstone.

Records at status `draft` are exempt: they MAY be corrected or retracted without a tombstone, and a retracted draft IRI simply ceases to resolve (see [Specification §11](/standard/specification/#11-identifier-policy) and [Versioning](/standard/versioning/#draft-records-and-retraction)). Because identity is deterministic, a retracted tuple that is later re-proposed regains the same UUID by construction.

See [Specification §11](/standard/specification/#11-identifier-policy) for the normative identifier policy.
7 changes: 5 additions & 2 deletions src/content/docs/standard/specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,9 @@ A `CanonicalReference` identifier MUST be generated deterministically. The ident

A `MappingAssertion` identifier MUST be generated deterministically from `subject`, `relation`, and `target.identifier`, in that order, using the `mapping` namespace (see [Identifier syntax](/standard/identifier-syntax/#mappingassertion-seed)). It MUST remain UUID-based and MUST NOT be derived from provider URLs, corpus paths, or resolver structures. Resolver-target entries do not have their own identifiers.

An implementation MUST NOT silently change the identity-defining fields of an existing `CanonicalReference`. Because those fields seed the deterministic identifier, any change produces a new `CanonicalReference` with a new identifier. The prior reference MUST be retained as a tombstone (`status` `deprecated` or `withdrawn`, [§12](#12-administrative-metadata)) and SHOULD be linked to its replacement through an `exactMatch` `MappingAssertion` ([§10](#10-mappingassertion)).
The persistence promise attaches at **promotion**: the first time a record is published at status `candidate` or higher ([§12](#12-administrative-metadata)). Promotion changes `status` only and MUST NOT change identity-defining fields, so the identifier survives promotion unchanged. Records at status `draft` are excluded from the persistence policy: they MAY be corrected (changing an identity field mints a different identifier; the previous one ceases to resolve) or retracted (the record is deleted) without a tombstone.

An implementation MUST NOT silently change the identity-defining fields of an existing **promoted** `CanonicalReference`. Because those fields seed the deterministic identifier, any change produces a new `CanonicalReference` with a new identifier. The prior reference MUST be retained as a tombstone (`status` `deprecated` or `withdrawn`, [§12](#12-administrative-metadata)) and SHOULD be linked to its replacement through an `exactMatch` `MappingAssertion` ([§10](#10-mappingassertion)).

A conforming registry SHOULD publish each `/id/{type}/{key}` IRI at two static URLs: the canonical URL itself (HTML for browsers) and a sibling with a `.json` extension carrying the JSON-LD payload. The HTML representation SHOULD advertise the JSON-LD sibling via `<link rel="alternate" type="application/json" href="…json">` in the document head. `Accept`-header content negotiation is not required.

Expand All @@ -285,7 +287,8 @@ Every registry object MUST include:

- `created` and `modified` MUST be [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) calendar dates in `YYYY-MM-DD` form.
- `status` MUST be one of:
- `candidate` — proposed but not yet accepted as stable.
- `draft` — work-in-progress record under review; **excluded from the identifier persistence policy** ([§11](#11-identifier-policy)). May be corrected or retracted without a tombstone.
- `candidate` — proposed but not yet accepted as stable. Promotion from `draft` attaches the persistence promise.
- `active` — accepted and recommended for use.
- `deprecated` — retained but no longer recommended.
- `withdrawn` — removed from active use because it was erroneous or has been superseded. If a successor exists, it is linked by an `exactMatch` `MappingAssertion`; see [Versioning](/standard/versioning/) for tombstones.
Expand Down
Loading
Loading