Experimental review draft · 8 November 2026
Independent implementer guide
Implement the proposed reference and status format in your own language. Compare exact signed bytes, signatures and expected outcomes without RefPassport, a database or a network service.
Profile: workreferences-experimental-draft-1
Inside the pack
The full draft specification, this guide, failure cases, a separate strict v1 specification and compatibility notes, 16 experimental message vectors, 26 expected-outcome cases, binary and hex signed bytes, an optional independent Python checker and verification evidence.
Recorded checks passed 173 Node tests and independent Python byte, signature and outcome checks. These checks cover the supplied corpus, not exhaustive security or arbitrary-input interoperability certification. The checker requires Python 3.10+ and the cryptography library; it installs nothing and makes no network calls.
The archive includes a SHA-256 manifest. Hashes detect accidental changes; an unsigned manifest does not authenticate its publisher. Review DRAFT-SPEC.md, FAILURE-CASES.md and VERIFICATION.md before any integration.
1. Select an explicit profile
Only process the requested profile. Experimental envelopes require exactly profile, kind, payload, publicKey and signature. The experimental profile string and kind are included in signed bytes. V1 is separately labelled and signs only its canonical payload, with no experimental prefix. Do not try v1 automatically when an experimental signature fails. Do not strip extra signed fields or insert service-provided issuer fields into old signed data.
2. Parse raw input without ambiguity
Strictly decode UTF-8; reject malformed byte sequences instead of replacing them. Permit at most one leading BOM for this local transport profile. Reject duplicate decoded object member names at every depth, including Unicode-escaped aliases. Reject unsupported JSON tokens and non-JSON whitespace. Enforce the 128-KiB per-envelope and 32-level nesting limits before unbounded parsing. The conformance bundle is a multi-message test container, not a wire envelope; some bundle files legitimately exceed the per-envelope limit.
Once JSON has been parsed with last-member-wins semantics, lost duplicate-name evidence cannot be reconstructed. Your parser, not a later object validator, must address that. Snapshot data before asynchronous operations and ensure the displayed authenticated values are those actually signed.
3. Validate complete schemas
DRAFT-SPEC.md defines every experimental field and bound. Reference text fields follow the included V1-SPEC.md: string lengths are UTF-16 code units, not Unicode scalar counts or UTF-8 bytes. Reject unpaired surrogates. Preserve all accepted whitespace, newlines, letter case and Unicode normalization forms. A human-visible similarity is not byte equality.
All experimental payload values are strings except the ordered revokedIds string array. Reject extra/missing fields, nested objects and numeric substitutes for sequence. Check sorted unique IDs, 2,048-entry cap and timestamp interval semantics. Do not rely on a signature to establish schema validity: capacity2049 has an intentionally valid signature but an invalid payload shape.
4. Build the exact signed bytes
For experimental messages, concatenate UTF-8 of the literal profile, LF, literal kind, LF, and canonical payload JSON. There is no extra final LF. The payload object keys are sorted by the fixed ASCII names. JSON is compact; strings use ECMAScript JSON.stringify escaping. Do not escape a plain slash unnecessarily, normalize Unicode, replace CRLF with LF or add indentation. Array order is meaningful and preserved.
Start with vectors/reference.json and vectors/bytes/reference.bin. The .bin file is exactly the message passed to Ed25519, not a PDF, envelope or hex string. The companion .hex is a text rendering of those bytes with a convenience terminal newline. Compare byte count, hex and SHA-256 before investigating cryptography. Each vector records its message hash.
The included V1 canonicalization vectors cover quotes/backslashes, TAB/CRLF, emoji, U+2028/U+2029, composed versus decomposed accents, case and whitespace. General JSON-number interoperability is avoided by the schemas, not solved by these examples.
5. Verify Ed25519
Decode public key and signature using strict canonical padded standard base64. Public key is 32 raw bytes, signature 64 bytes. Use plain Ed25519, not Ed25519ph, a hash of the payload, or an arbitrary signing context. APIs may need a wrapper such as SPKI; that wrapper is an API adapter, not part of signed data.
Keep raw cryptographic validity separate from message/profile validity. conformance.json has both expectedCryptoValid and expectedMessageValid. Invalid crypto examples are tamperedReference, tamperedStatus and swappedKeyReference. capacity2049 is crypto-valid but message-invalid. A valid key/signature pair alone does not prove issuer identity.
6. Evaluate independently supplied policy
Callers must supply a trustworthy current UTC timestamp and maxStatusAgeSeconds. The examples use 604800 to exercise the provisional seven-day proposal and 86400 to prove configurability. Never infer a permanent standard default from those fixtures.
For a valid signed reference, calculate not-yet-valid, within-signed-window or expired using the half-open interval [notBefore, expiresAt). The issuedAt field is the issuer's assertion, not independent historical time evidence.
Validate a supplied status envelope, then bind all three: its signing public key equals signed statusPublicKey; its issuerDomain equals the reference domain exactly; and statusListId matches. Do not accept a newly rotated status key merely because it can produce a valid signature.
If retained earlier status is supplied, authenticate and bind it too. Reject lower sequence/earlier issuedAt, same-sequence different canonical payload, and removal of previously revoked IDs. Then reject future-issued evidence, and compute freshUntil as the minimum of signed nextUpdate and issuedAt plus the relying-party age cap. Exact equality now == freshUntil is stale. Only fresh evidence yields revoked or not-listed-as-revoked; missing/stale evidence stays unknown.
The order matters: the fixtures may report rollback before stale if both apply. Compare the specified result fields, not prose error strings or local logging. An expired reference may have independently fresh status; do not collapse those dimensions into one green label.
7. Do not invent missing trust
No experimental fixture includes a trusted DNS response, DNSSEC chain, historical domain evidence, issuer credential or secure clock. issuerBinding must remain not-checked in these tests. A fresh status result cannot upgrade that.
Retained history supports local anti-rollback checks only. Stateless clients and new devices may accept an older still-fresh snapshot. Durable authenticated history, multi-device synchronization and global equivocation detection are outside this draft prototype. Similarly, status-key recovery/succession and capacity rollover are unimplemented, not automatic success paths.
Conformance checklist
- Match every provided .bin/.hex/hash before signature checks.
- Match both cryptographic and complete-message validity for all 16 vectors.
- Match all five expected outcome dimensions for each of the 26 cases, including with-history/without-history contrasts.
- Match original v1 signature/bytes without changing it.
- Add your own parser, Unicode, duplicate-member, maximum-size, time-boundary and async-mutation tests; the corpus is illustrative, not exhaustive certification.
- Document unsupported legacy formats and all unimplemented trust/recovery features. Review the draft's open decisions before integration or issuing real data.