Docs / Protocol
Protocol
The plain-language explanation is How PubPhys proves what and when. This page is
the technical summary; the normative text is protocol/SPEC.md (version 1, frozen), published with the
schemas and the verifier in the mirror repository Galitski-group/pubphys-log.
Objects
bundle.json) holds everything from the content down to the checkpoint, the inclusion proof and every OpenTimestamps proof.- Record (
pubphys.record/2): type, content hash, files, parents, author (ORCID iD or an opaque account reference, never a name), origin, a 256-bit salt and a claimed creation time.record_hash= SHA-256 of its canonical JSON (keys sorted, strings only, equal to RFC 8785). - Attested record (
pubphys.attested/1): the record hash and how identity is attested:orcid-oidc,platform(seed and platform records) ornone. - Envelope (
pubphys.envelope/1): the attested hash and an Ed25519 platform signature overpubphys.platform/1\nfollowed by it. - Bundle (
pubphys.bundle/1): one record with content, files, attested object, envelope, every OpenTimestamps proof, the inclusion proof and its checkpoint.
Transparency log
- Leaves are the canonical bytes of
{envelope_hash, record_type}; tree hashing and proofs follow RFC 9162. Leaf indexes start at 0 in insertion order. - Checkpoints are C2SP signed notes (origin
pubphys.com/log/v1, size, root), signed only when the log grew: /log/checkpoint. - Proofs:
/log/proof/inclusion?leaf=&size=and/log/proof/consistency?from=&to=. - Each checkpoint's SHA-256 is logged in Sigstore Rekor v2 (
hashedrekord, signed with a separate ECDSA P-256 submission key published in the trust file) and committed with the Rekor entry to the mirror repository. - A verifier checks a bundle's checkpoint against a witnessed checkpoint of equal or larger size from the mirror, whose digest Rekor logged (inclusion proof against a Rekor checkpoint signed by the pinned shard key). A split view is detected on comparison; nobody cosigns PubPhys checkpoints directly yet.
- A bundle uses the smallest witnessed checkpoint that covers its leaf and is not signed by a revoked key; otherwise the newest such checkpoint; otherwise the newest covering one. It is provisional (
witness: not_checked) until that checkpoint or a later covering one is witnessed. - Inclusion promise: a five-line signed note (
pubphys.com/log/v1 promise, leaf hash, index, issue time, deadline at most two hours later), inlog.promise.fetch-witnesscollects evidence: a PubPhys checkpoint covering the leaf, consistent with the bundle's, whose digest Rekor logged, the entry proven against a Rekor checkpoint signed by its shard key and cosigned (cosignature/v1) by a witness whose key the verifier pins. The verifier reportskeptif the earliest verified cosignature is no later than the deadline, otherwisenot_judged; nevermissedoffline, since the mirror could omit an earlier checkpoint. Missed promises are watched by the site's administrators.
ORCID attestation
- Human records confirmed through ORCID carry
orcid-oidcattestation. The batch of record hashes (lowercase hex, sorted, deduplicated, joined by LF) gives the noncehex(SHA-256("pubphys.attest/1\n" + hex(SHA-256(joined))))(SPEC 7.1); the author signs in at ORCID (implicit flow,prompt=login) with that nonce, and the returnedid_token(RS256, audience the PubPhys client id) is kept with the batch. The attested object holds its SHA-256. - Identity is
verifiedwhen the token's signature verifies with an ORCID key the verifier trusts, its issuer ishttps://orcid.org, its subject is the record's author, its nonce matches the batch, the audience is a pinned client id, and, if the record's earliest Bitcoin anchor is known, its issue time lies within the windows of SPEC 7.2 around it. - ORCID keys come from the verifier: ORCID's live JWKS, or captured keys (Wayback Machine captures, checked through the archive's index and raw capture), valid from 24 hours before the first to 24 hours after the last capture. PubPhys polls ORCID's keys, logs each key set in Rekor before trusting it, asks the Wayback Machine to capture it every 12 hours, and records the verified captures in
jwksrecords (fetch-orcid-keysreads them). - On account deletion the token is withheld (
id_token: null,id_token_withheld: "true"); identity then readswithheld.
Keys
- The platform signing key signs envelopes and checkpoints. Each platform key is introduced by a
platform-keyrecord: the first by the offline recovery key, later ones by the previous key or the recovery key. Revocations areplatform-key-revocationrecords, effective from their Bitcoin anchor. - A verifier pins the recovery key out of band and builds the key chain from the key records' bundles (kept in the mirror under
keys/); the trust file (/.well-known/pubphys-trust.json) is a convenience copy. See Keys. - Trust rule (
verifier/TRUST.md, verifier configuration; record validity is unchanged): a key is trusted if some introduction of it is signed by a recovery key or by a trusted, non-revoked key (least fixed point). Revocations count in rounds, together per round: a recovery-signed one always; another one only if its signer is not revoked and is trusted without the introductions signed by the key it revokes. Self-revocations and revocations of recovery keys never count; revocations pinned in the verifier count even when the mirror omits them. Descendants of a revoked key lose trust whatever the anchor order, unless introduced again cleanly. - An envelope signed by a revoked key counts when its Bitcoin anchor is earlier than the revocation's; a checkpoint signed only by revoked keys counts only as that key's pinned last good checkpoint.
Sealed records and reveal pairs
- A sealed record is a
claimor a new problem'srevisionsigned and logged while its text stays private. Its content uses version 3 (pubphys.content.claim/3,pubphys.content.revision/3, the latter only withn = "1"): the fields of version 1 plusnonce, 64 lowercase hex characters from a secure random source, socontent_sha256cannot be found by hashing guesses. Version 2 is never assigned. Files are not covered by the nonce: each is bound by the plain SHA-256 of its bytes. - A verifier released before version 3 finds no schema for such content and reports the whole structure part as
not_checked, neververified; it still checks the content digest and the identity, platform and log parts. Use a verifier release with version 3 for a sealed bundle. - A reveal (
pubphys.content.reveal/1, anote) names the sealed record's hash as itstarget. A reveal pair is the reveal's bundle with the sealed record's bundle. It isfailedif the target is not the sealed record, that record is not sealed (content version 3), the two name different ORCID iDs, or either bundle has a failed part;verifiedonly if both have structure, content, identity, platform and log verified;not_checkedotherwise, for example when the sealed content was purged. Each bundle is checked with its own copy of the trust. - A verified pair proves that the reveal's signer had the sealed content at the sealed record's earliest valid Bitcoin
anchor (of its attested or envelope hash): the seal date. A record's
createdis never a date of anything. Priority on PubPhys also depends on the seal's state on the site, which no bundle shows: a seal that lapsed before its reveal is dated by the reveal's own anchor (sealing). - Check a pair on the verify page (add the sealed record's proof under "A revealed seal"), or with
pubphys-verify reveal.json --trust trust.json --sealed sealed.json --bitcoin.
Records of the seed collection
The genesis key record, the import manifest (its content and the exact items.json bytes), one
topic record per topic and one revision record per problem, with declared parents and the
manifest among its parents. Each record page links its bundle: /records/<record hash>/bundle.json.