Appearance
Data model
The question this answers: what is a Chemical Record made of, and what is deliberately kept apart?
What follows is the spec-level model — the entities the Specification names and the rulings that fix their shape. Every term in the diagram is a glossary term; CONTEXT.md holds the definitions the rulings use, and the properties the physical schema has to satisfy are listed in Specification, Seam 1.
A physical schema exists, and not in this repository. It lives in the api gitlink under app/chemical-safety-assistant-api/prisma/models/, where seventeen Corpus models are declared, and ten migrations describe how it got there. None of those migrations has ever been applied to a live Postgres: the api's test suite runs without a database, because the snapshot serialiser is a pure function over rows. So the model below is still the one to read for shape, and the schema is the one to read for columns — and the two are kept in step by Specification, Seam 1 rather than by either document quoting the other.
The entities
Three Corpus artifacts sit outside this diagram because they belong to the Corpus rather than to any one record: the Routing Threshold, the Escalation Trigger phrase list and the Routing Fixture. They are listed in Curation and ruled on in ADR-0031.
Record identity
| Question | Ruling |
|---|---|
| Whether a record is keyed on a substance or on the document it came from | ADR-0013 — A Chemical Record is keyed on its SDS document, not on a substance (D-18) |
| What the identifying fields are, and what two revisions of the same product amount to | ADR-0013 |
| What identity becomes when the document states no revision date | ADR-0024 — An SDS with no revision date is admitted, and the absence is shown |
| Whether such a document may be refused admission instead | ADR-0024, rejected options |
| Which identifier Identification reads first, and what it falls back to | ADR-0013 (D-19), corrected by ADR-0018 (D-35) |
The ruling that made CAS Number the primary key is kept and marked dead: ADR-0004 — superseded by ADR-0030; read order preserved, ranking replaced. The three peer routes that replaced its ranking are in Identification and Routing.
Optional attributes, and absence as a value
| Question | Ruling |
|---|---|
| Whether CAS Number is required, and what a Formulated Product carries instead | ADR-0013 |
| Whether a missing revision date may be filled from the Curation date or a file timestamp | ADR-0024 |
| What a PPE field holds when the SDS names no glove material | ADR-0025 — Generic PPE text is displayed as generic, and the glossary rule is softened |
| Whether an empty safety field is an error or an answer | ADR-0002 (D-03) |
| Whether an empty device is the same value as an empty field | ADR-0032 — see The Corpus lifecycle |
| Whether a document records how many pages it has, what a document with no readable count means, and what the verification gate then checks | ADR-0074, superseding ADR-0059 |
Formulated Product, Pure Substance, Not Stated and Corpus Unavailable are all defined in CONTEXT.md, which also records that the per-item PPE definition is an aspiration rather than a guarantee.
How a row stops being displayed
A Corpus row is evidence with Provenance, so nothing in this model is deleted and a correction never rewrites what a row says (ADR-0084). A selection stops being displayed by releasing its position: the ordinal every selection row carries is nullable, and a row with none is one nothing may lay out. That is the whole of what "live" means, and it is the same filter the snapshot serialiser and the curator's record read both use.
| Question | Ruling |
|---|---|
| What a correction replaces, and why it is the attachment row rather than the Source Span | ADR-0084 (D-169) |
| How a position is freed without narrowing any unique constraint, and why a partial index lost | ADR-0084 (D-172) |
| Whether a retracted position is renumbered, and whether a gap in a sequence is a legal record | ADR-0084 (D-170) |
| What happens to a superseded span's Restriction, Translation and Reconciliations | ADR-0084 (D-171) |
| Which two mutations of a stored row the Corpus permits, and why the list is closed | ADR-0084 (D-177) |
| Why a Spill Response branch is not an attachment row at all | ADR-0086 (D-179) |
Two consequences worth stating in the model's own terms. A correction chain is linear — one predecessor has at most one replacement, enforced by a unique on the link rather than by a rule something has to remember — so a position holds exactly one live row at every instant. And because ordinal is nullable while the uniques stay as written, many released rows coexist at one position: NULLs are distinct, which is what makes a chain representable at all.
What travels with a displayed span
| Question | Ruling |
|---|---|
| Whether a safety field may exist without a Source Span | ADR-0002 |
| Whether the SDS Section reference travels with the span wherever it is shown | ADR-0002, Specification §7 |
| What laying spans out as labelled fields is permitted to change about their words | ADR-0012 |
| Whether a Curated Translation replaces its original or hangs off it | ADR-0009 (D-11) |
| Whether the stored text of a span may be an unverified extraction | ADR-0027 |
| Whether a Spill Response branch may be chosen for the user, and what its step order means | ADR-0026 |
| What Routing is allowed to attach to a span it points at | ADR-0031 (D-65) |
| In what shape the SDS Section reference crosses to the device, and why a rendered string was not enough | ADR-0072 |
| Where the sixteen Section headings themselves are held, and in which languages | ADR-0060 |
| Whether a published version's bytes may be reshaped by a later schema change | ADR-0056, read together with ADR-0072 |
What is kept apart
| Question | Ruling |
|---|---|
| Whether two suppliers' records for the same chemical may be merged, or one designated canonical | ADR-0023 — Conflicting Chemical Records are never merged; the product in hand governs (D-45) |
| What a name search matching several products presents instead | ADR-0023 (D-46) |
| Whether the Corpus may be deduplicated by chemical name | ADR-0023, "This ruling may not be re-decided" |
| Whether safety content may enter a record from any source other than its own SDS | ADR-0025 (D-53) |
| Whether a Restriction from elsewhere in the document may be attached to a span at display time | ADR-0022 — the mechanics are in Curation |
| Whether generated prose may occupy a safety field | ADR-0002, ADR-0012 |
| Whether a term may carry a second Curated Explanation, and what a curator who wrote the wrong one can do about it | ADR-0073, superseding ADR-0061 |
| Whether a stored copy of an admitted document can be removed once a span, a record or a published payload may reference it | ADR-0058 |
| Whether the Reconciliation gaps read's answer is a closed union the two repositories key off, or an implementation detail | ADR-0071, on ADR-0068 and ADR-0069 |
ADR-0023 works the case that motivated it — two suppliers, the same solvent, opposite advice about the same glove material — and states what the conservative-looking merge would have produced.
Where the shape is asserted
| Property | Where |
|---|---|
| Every Safety-Critical element carries a Source Span naming its SDS Section | Specification, Seam 1 |
| Every document has complete Provenance, and every Curated Translation a reachable original | Specification, Seam 1 |
| No record carries a revision date its document does not state | Specification, Seam 1 |
| Every record traces to exactly one SDS | Specification, Seam 1 |
| A search matching several products returns all of them rather than collapsing to one | Specification, Seam 3 |
| What a record renders when a field is silent, or a date or material is absent | Specification, Seam 2 |
| The schema the client validates on sync is the one the checker asserts against | Specification, Seam 1 |
Where the rest of this is
- How these records are produced is in Curation.
- How they reach a device is in The Corpus lifecycle.
- Where they are stored and what serves them is in System architecture.