Files
alexmandClaude a09d158e16 feat: minted keys, VRF seeds, RFC 9162 proofs, history roots, tag URIs and a transparency log
Keys (spec/02 §2.4), the rule paperstack settled on:
- A work key is a Scholar-style citation key, a hyphen and the first four
  Crockford base32 characters of SHA-256("scienting-key/1:" + identity),
  where the identity is the first of doi, arxiv, isbn, pmid, pmcid and
  openalex in same_as, else the folded title, year and family name. A
  collision lengthens the later key by two characters; a key is minted
  once and never recomputed. A document key adds .si, .v<seq> or .<type>
  for versions other than the version of record.
- Every fixture key is now minted (hale2026harmonic-damb,
  okafor2025solvent-acth, writer2027fixed-ynr7.v3, tiny2026tiny-j4qm), so
  every node and record ID was re-minted and the docs rewritten to match.
  The validator checks the document key against the work key and version
  (doc.key.work) and the hash part against the identifier (doc.key.suffix).
  vectors/keys.jsonl pins the cases paperstack's tests pin.

Review:
- Spot-check seeds are ECVRF-EDWARDS25519-SHA512-TAI proofs (RFC 9381),
  implemented in tools/oracle/vrf.py in plain Python and reproduced
  against the RFC's Example 16; the sample ranks by the VRF output. The
  earlier Ed25519 seed could be ground by a dishonest checker.
- RFC 9162 inclusion and consistency proofs (crypto.inclusion_path,
  verify_inclusion, consistency_proof, verify_consistency) with
  scienting-proof/1, vectors/proofs.jsonl and two fixture records.
- document.json carries `history`, the root over the corrections, with
  the empty-tree hash for none (spec/11 §11.5, rule doc.history).
- A provisional transparency log (spec/23): log entries, signed-note
  checkpoints with key hashes as transparency logs share them, the rule
  that a logged revocation beats a self-asserted time, and vectors.
- Reserved signature schemes cose and ml-dsa-65 (spec/08 §8.4).

Identifiers and text:
- urn:scienting: becomes tag:scient.ing,2026: (RFC 4151), since the URN
  namespace was never registered.
- Unicode 16.0 is pinned for normalization and categories (spec/01 §1.4);
  the checker refuses another version.

Checking:
- check.py: keys, proofs, VRF and checkpoint vectors; the proof and
  checkpoint records; a check that every ID and hash the prose quotes
  exists in the fixtures or vectors; three more broken packages
  (history-wrong, key-suffix, key-work).
- stress.py: key, VRF, proof and checkpoint properties.
- Docs: a keys section in the concepts and FAQ, rationale entries for
  keys, VRF, proofs, tag URIs and the Unicode pin, a "Looking ahead"
  section, media-type registration and OCI distribution notes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-14 23:21:57 -04:00

96 lines
7.5 KiB
Markdown

# 2. Works, versions, witnesses and documents
## 2.1 Four objects
| Object | Is | Identified by |
| --- | --- | --- |
| Work | The intellectual work, across all its versions. | A work key ([2.4](#24-work-and-document-keys)), and `same_as` identifiers: `doi:`, `arxiv:`, `isbn:`, `pmid:`, `pmcid:`, `openalex:`, `url:` or `lode:`. |
| Version | One expression of the work: a preprint, an accepted manuscript, the version of record, an erratum, Supporting Information, a draft. | The work's key and a version type, with an optional sequence number and date. |
| Witness | One file of a version: a PDF, JATS XML, a LaTeX source archive, an HTML page, an EPUB, a Typst project. | The SHA-256 of its bytes. |
| Document | The text established for one version from one or more witnesses. | A key, and a root hash per revision. |
A document's key is its work's key, with a suffix for anything other than the version of record: `cornell1995second-saqk`, `cornell1995second-saqk.si`, `dong2026machine-1ard.v2`.
Supporting Information is its own document, with its own pages, numbering and references, related to its article by `supplement-of`.
A textbook is a work whose chapters are documents related by `part-of`.
A draft is a document of kind `draft`.
Keys are immutable once a document is shared.
A renamed document keeps its old keys in `aliases`.
## 2.2 `document.json`
| Property | Required | Holds |
| --- | --- | --- |
| `format` | Yes | `scienting-doc/1`. |
| `key` | Yes | The document key. |
| `store` | No | The store that holds it, when the package says so. |
| `aliases` | No | Earlier keys. |
| `kind` | Yes | `article`, `supplement`, `chapter`, `book`, `thesis`, `report`, `draft`, `course-material` or `other`. |
| `work` | Yes | `{key, same_as}`. |
| `version` | Yes | `{type, seq?, date?}`, where `type` is `preprint`, `submitted`, `accepted`, `version-of-record`, `erratum`, `retraction`, `supplement`, `draft` or `other`. |
| `relations` | Yes | A list of `{type, target}`; `type` is `supplement-of`, `part-of`, `version-of`, `erratum-of`, `retraction-of` or `translation-of`, and `target` a key, optionally store-qualified. |
| `meta` | Yes | The version's bibliographic record, as one CSL-JSON item. |
| `language` | Yes | A BCP 47 tag. |
| `license` | No | The document's license as stated: `{spdx?, text?, url?}`. Rights are per witness ([14](14-rights.md)). |
| `policy` | Yes | The text policy: `full`, or `checks-only` ([12.5](12-package.md#125-text-policies)). |
| `hashing` | Yes | How content values are computed: `{scheme: "plain"}`, a team HMAC or a page-derived key ([5.8](05-hashes.md#58-keyed-hashes)). |
| `root` | Yes | The root node's `node_hash`. |
| `meta_hash` | Yes | The metadata hash ([5.9](05-hashes.md#59-the-metadata-hash)). |
| `history` | Yes | The history root: the root of the tree over the package's corrections ([11.5](11-corrections.md#115-the-history-root)). |
| `rev` | Yes | The revision: the index of the last correction applied, or 0. |
| `counts` | Yes | `{nodes, leaves}`. |
| `fidelity` | Yes | `{lowest, counts}`: the lowest level among leaves, or null when there are none, and the number of leaves at each level, computed as [8.2](08-fidelity.md#82-levels) defines. |
The schema is `document.schema.json`.
## 2.3 `witnesses.json`
`witnesses.json` is an object with one property, `witnesses`, a non-empty list in which each witness is:
| Property | Required | Holds |
| --- | --- | --- |
| `id` | Yes | The witness ID: seven letter-first base32 characters encoding the SHA-256, as [4.6](04-identity.md#46-record-ids) defines. |
| `sha256` | Yes | The SHA-256 of the file. |
| `size` | Yes | Its size in bytes. |
| `kind` | Yes | `pdf`, `jats`, `latex`, `html`, `epub`, `typst`, `xml`, `image` or `other`. |
| `media_type` | Yes | Its media type. |
| `pages` | No | The number of pages, for a witness that has pages. |
| `text_layer` | No | Whether a PDF has a text layer; a scan has none. |
| `version_label` | No | The version as the witness labels it. |
| `origin` | Yes | `{source, url?, doi?, retrieved_at?, note?}`, where `source` is `publisher`, `repository`, `preprint-server`, `author`, `team`, `licensed-delivery`, `library` or `other`. |
| `rights` | Yes | The rights record, `scienting-rights/1` ([14](14-rights.md)). |
The witness's bytes are not part of the package; they live in the team's asset store, by SHA-256.
The SHA-256 is the exact identity of one file.
Because publishers stamp each download, two copies of one paper rarely share it; page fingerprints identify their pages instead ([7](07-geometry.md)).
## 2.4 Work and document keys
A work key names a work the way a reader would, and never collides: a Scholar-style citation key, a hyphen, and the first characters of a hash of the work's identity.
```text
vaswani2017attention-a241
└─── Scholar part ──┘ └hash┘
```
**The Scholar part** is built as Google Scholar builds its BibTeX keys, from the CSL-JSON `meta` of the version:
1. the first author's family name: `family`, or the part of a `literal` name before a comma, else its last word that is not a suffix such as Jr. or III; folded to ASCII with NFKD, lower-cased, letters only, so `Müller` gives `muller` and `O'Brien` gives `obrien`; no author, or a name with no Latin letters, gives `anon`;
2. the year of `issued`, when it has four digits, else nothing;
3. the first word of `title` that is not a stop word, folded the same way, letters and digits only, with apostrophes removed and other punctuation splitting words; no such word gives nothing.
The stop words are `a an the of on in for to and or at by with from as into onto about toward towards via is are be its it this that these those`.
**The identity** is the work's first identifier among `doi`, `arxiv`, `isbn`, `pmid`, `pmcid` and `openalex` in `same_as`, in that order, written `<kind>:<value>` with a DOI's ASCII letters lower-cased.
A work with none has the identity `meta:<title words>|<year>|<family>` from the same folded parts.
`url:` and `lode:` identifiers name copies and claims, not the work, and never enter the identity.
**The hash part** is the leading bits of SHA-256 of `scienting-key/1:` followed by the identity, in UTF-8, written in lowercase Crockford base32, five bits a character: four characters, or, when another work in the store already holds that key, six, eight and so on until the key is free.
A key is minted once, when the work enters a store, and never recomputed: a corrected title or a year revised later leaves it alone, while the hash of an identifier still shows which work the key names.
A work key matches `^[a-z][a-z0-9]*-[0-9a-hjkmnp-tv-z]{4,51}$`.
**The document key** is the work key for the version of record, and the work key with a suffix for any other version: `.si` for Supporting Information, `.v<seq>` for a preprint, submitted, accepted or draft version with a sequence number, else a dot and the version type: `cornell1995second-saqk`, `cornell1995second-saqk.si`, `dong2026machine-1ard.v2`.
A validator checks that the document key is the work key with the version's suffix (`doc.key.work`), and that a key whose identity is an identifier carries that identifier's hash (`doc.key.suffix`); a metadata identity may have been corrected since the key was minted, so it is not held to the key.
Store, project and source keys keep the form `^[a-z0-9][a-z0-9._-]*$`, as do legacy document keys kept in `aliases`.
`keys.jsonl` pins the Scholar parts, identities, hashes and document keys, with accented names, name suffixes, missing years and authors, and the lengthening that settles a collision.