The author approved specification v0.16 on 7 October 2026, tagged
spec-v0.16 at b6ff17a. Only the annex changes, with the SHA-256 of the
approved text, and the README of testdata; the README and the CHANGELOG
name the approved version.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3fd0e93 restores the escapes of release.json that 4f78854 had lost: the
cases "round escaped as round" and "round twice, once escaped as
round", and the surrogate pair of "a surrogate pair in a value". The
annex changes with the SHA-256 of the draft. The comment of the strict
reader had lost the same escape.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The draft v0.16 of datekeys-go at 4f78854 (branch v0.16): SPEC_VERSION
0.16, and testdata, wordlists and annex synced from that commit. The
annex is §79 of the draft, with the CC BY-ND 4.0 license of the
specification in its title and the key of words in 79.7.
A seal without accuracy proves nothing before the opening date (§29.7,
§29.11, as 7e3b810): a valid seal is S4 only when its token carries
accuracy and t plus the accuracy is before round_time; otherwise S5,
with the first reason that holds: late, no accuracy under the BTSP
policy of ETSI EN 319 421 (0.4.0.2023.1.1), or no accuracy. cms.ts reads
hasAccuracy and the policy of the token (tokenIsBTSP); securitycms.ts
gives SealReason, Detail.sealReason and SignerLine.reason; S5 has no
fixed text any more, and verdictLines writes it and the line of a signer
of F6 with the reason, the texts of Go byte for byte (sealReasonText).
encryptFiles returns the verdicts of the area it wrote in
Encrypted.security, as Result.Security of Go, so that a writer warns of
a seal without accuracy (§62.1 rule 19).
drand's JSON is read strictly (§47.1, as b570338): parseDrandJSON, as
ParseDrandJSON of Go, reads RFC 8259 JSON in valid UTF-8 whose value is
an object, with no name repeated in any object, names compared exactly
once their escapes are decoded, a lone escaped surrogate malformed, the
round a number without sign, fraction or exponent from 1 to 2^53 - 1,
and signature and randomness strings, with the error texts of Go.
ParsedRelease is now a Release: no round above 2^53 - 1 is read. The
page reads the answers of the relays with it (drand.ts), as the client
of Go does, and the pasted release with strictJSON and jsonRound
(release-input.ts), so that it never reads another round than step 10.
Tests: security_cms.json with seal_reason (143 cases), the 38 JSON
inputs of release.json, the new cases of signature2_test.go and
drandjson_test.go (with the escapes written as escapes), and the new
fixtures: format3_time_and_key_words opens with the identity that the
words of its words_text give with normalizeWords and wordKey, in the
library and in the page, and format3_full_chunk, whose PAYLOAD_AGE ends
in a full STREAM chunk, opens. check-build.mjs counts words_text among
the secrets of the fixtures.
Reference files made again with Go at 4f78854: mutation-texts.json (its
spec field only), ibe-vectors.json (the two new fixtures, the rest
unchanged) and signing-vectors.json, in an export of 4f78854 with the
same frozen samples read again: the capsules are the same, and the
tokens of the sealer, without accuracy, now give S5.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
As aefc8f6 of datekeys-go. sync-testdata.mjs also vendors annex/ of Go,
the recovery annex (§79 under a title with the version and the SHA-256 of
the specification), and testdata, wordlists and annex are at aefc8f6.
/create recommends the key to a time_only capsule more than a year ahead
(§7.6), and once the capsule is made it says what opening it later will
take: the capsule, one of its keys if it has them, and the signature of
drand for its round, which an archive or a cache service must keep if
drand no longer serves it (§62.1, rule 26); and it offers the annex for
download as <capsule>.recuperacion.txt (rule 27, annex.ts). check-build.mjs
wants the annex shipped byte for byte.
profile.ts gains ProfileStatus, PROFILE_STATUS and profileStatusOf, as
StatusOf of Go: Quicknet is active. planCapsule writes no capsule with a
profile that is not, and /inspect warns when the profile of a capsule is
compromised (buildReport takes profileStatus).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
For whoever does not trust the random numbers of a computer, as dice.go of
datekeys-go at 92e7154, with its texts: five dice for each word give a
number from 11111 to 66666, the position of the word in a list of 7776.
wordlist.ts gains DICE_LIST_SIZE, diceNumber, diceWord, diceWords and
diceList, the list numbered as the EFF publishes its own, and wordkey.ts
goFields, which splits at white space as strings.Fields of Go.
/create offers "Con dados" between the random words and the person's own:
it turns the numbers into words as they are typed, tells a number that is
not five dice or that gives a word again, and offers the list numbered for
dice, to print it, with its SHA-256. planCapsule takes dice and diceList,
and readDice reads the numbers one by one. The list loads once for random
words and dice, and an effect that finds it loaded writes no state, so it
does not run again without end.
testdata and wordlists at 92e7154, whose README of the lists records the
SHA-256 of each list numbered for dice.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
testdata and wordlists at datekeys-go e671032, with the same testdata:
wordlists/en.txt is the large wordlist of the EFF, 7776 words, CC BY 4.0,
in its order and without the dice numbers. WORD_LIST_SHA256 pins it, and
the alphabet of en is a to z and the hyphen of its four compound words.
/create still offers the Spanish list, and check-build.mjs wants the site
to ship that one alone.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scripts/sync-testdata.mjs copies wordkey/lists of the same commit of
datekeys-go into wordlists/, with its own SOURCE.json, and check verifies
both copies; the testdata test wants both from one commit. .gitattributes
keeps the bytes of wordlists/ as they are, like those of testdata/.
testdata and wordlists at datekeys-go 27a75ee, branch v0.15 after the tag
spec-v0.15: the files of testdata are those of the tag; wordlists brings the
Spanish list, 7776 words, CC BY-SA 4.0, with its README.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- SPEC_VERSION 0.15, version 0.4.0-dev; testdata synced from datekeys-go
at 3c3e737 (v0.15), which adds vectors/release.json and releases/ and
the field source of mutations.json.
- releaseobject.ts, without noble, as provider/release.go and archive.go
of Go: encodeRelease, decodeRelease with the layers of step 10 (size of
1 to 1024 bytes, type and version, schema), parseRelease, which reads
drand's JSON as encoding/json does, the ReleaseSupplier of a release in
hand (encodedRelease) and ReleaseArchive, the informative local archive,
whose failures are ERR_RELEASE_UNAVAILABLE; all with Go's texts.
- verifyRelease compares the chain hash a release names with the pinned
profile first (ERR_PROFILE_MISMATCH).
- open takes OpenOptions.release, exclusive with source: it is not compared
with the clock (step 9.c, option B), Opened.clockBehind reports a clock
behind it, and it is decoded at step 10; a network source is still never
asked before the round time. The verified release carries the chain hash
of the pinned profile.
- vectors.test.ts runs release.json and every file of releases/, and the
mutation corpus with the source of each case, as testkit's singleSource;
scripts/mutation-go-texts.go does the same, and testing/mutation-texts.json
is regenerated: the spec field, "round not reached yet" now ok, and the
four new cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- SPEC_VERSION 0.14; testdata synced from datekeys-go at 39b2033
(spec-v0.14), which adds vectors/tlock_steps.json;
testing/mutation-texts.json regenerated with Go: only its spec field
changes.
- Decision 8: validateProfile admits only bls-unchained-g1-rfc9380, with
its public key in G2, in the order and with the texts of Go's
validateDrand at c041fa3; any other drand scheme fails with
ERR_UNKNOWN_PROFILE before the key and the chain hash.
- vectors.test.ts walks tlock_steps.json value by value with the code of
ibe.ts, release.ts and bls12381.ts, with its negative checks, and the
testdata guard requires it. ibe.ts exports h3Base, h3Try and hashToG1,
which h3, the encryption and release.ts now use.
- The comment of h3 said the top bit is cleared: the first byte is
shifted one bit to the right, as kyber does.
- README and CHANGELOG.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
testdata is synced with the head of the branch v0.12 of datekeys-go
(601e6d2); SPEC_VERSION stays 0.11 until the author approves the draft.
- CMS as Go reads it at the draft v0.12 (review of 2 October, T2, T6 to T8
and the TypeScript side of E7 to E9):
- the certificate field by field with the profile of section 29.10, its
errors in CertificateError with the texts of Go; one that breaks it
decides nothing unless a SignerInfo names it, and two copies are one;
- the text of a name only from UTF8String, PrintableString, IA5String,
TeletexString in ASCII and BMPString without surrogates, never from an
attribute that appears twice; the holder by givenName and surname
before the commonName, the issuer by its commonName or its
organizationName;
- object identifiers by the bytes of their DER; a SET OF may repeat an
element; RSA with NULL parameters and an odd modulus; a key of another
scheme than its algorithm is invalid; a messageImprint of another
length is S3; the crls of a token decide nothing;
- DER: UTCTime and GeneralizedTime in their X.690 forms with a date that
exists, the restricted string types as primitive, the accuracy as
minimal INTEGERs. The test of cms.test.ts that compared a function
with itself has an expected value of its own.
- The verdicts in the texts of the draft: names between « and », shown
with at most 64 code points and no two spaces in a row, or their SHA-256;
in F6 the authority of each seal and the warning that nobody checks who
issued it; foreign signers in Spanish; times with their fraction.
- security.json in its context with lines, and the 135 cases of
security_cms.json, compared field by field, lines included.
- The 218 cases of mutations.json, with the texts of capsule.Open
regenerated by scripts/mutation-go-texts.go, and ibe-vectors.json with
the fixtures format3_note, format3_unsigned and the new
format3_seal_unsupported; its frozen values do not change.
- note.json, run with checkNoteData, publicNote and unusableNote.
- inspect reads the public note on demand, only for a header with one, so
that the Unicode tables never load with /inspect; the view of inspect
-json gives public_note and public_note_unusable, as Go.
A Go/TypeScript differential of 63,623 security areas, made from the
vectors, edited element by element and signed afresh with varied
certificates, tokens and authorities, gave no difference in verdicts,
results or lines; the code before this change differed in 13,296 of the
first 42,986.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SPEC_VERSION is 0.11. testdata brings format3_signed, format3_signed_cms and
format3_sealed, and the vectors ed25519_strict.json, security_cms.json and
locator.json; the mutation corpus has 210 cases. ibe-vectors.json adds the
three fixtures and remakes the two that Go regenerated, and
mutation-texts.json is made again with that reference.
This library still reads the security area as a reader of v0.10, so a
signature or a seal that the reference checks gives F1 or S1 here. The
Verdict type and the texts know F2 to F6 and S3 to S5, and the tests state
the gap with testing/pending.ts instead of hiding it; porting the
verification makes that file the identity. npm run verify and
testdata:check pass.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
As the spec v0.11 draft decides after its review (38.1), and as the Go
reference does from 2213b8c:
- dkc/wordkey.ts replaces inspector/wordkey.ts. The salt carries the
capsule_id too, so the same words give another key in each capsule;
the words are lowered with the new LOWERCASE table of pathrule.ts,
loaded on demand; checkWords refuses controls, invisible and
unassigned code points and counts only different words of three
letters or more, with the errors of Go. New vector of 38.1.
- encryptFiles takes the words and derives their key once it has drawn
capsule_id; the creator passes them, and the opener salts them with
the capsule_id of the capsule.
- /create asks for the words twice and shows how they are kept; the form
checks them with the tables of the platform, and the writer again with
those of Unicode 18.0.0.
- The tables, regenerated with the lower case, and testdata synced from
2213b8c; the frozen texts of Go for the invalid options, updated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Syncs testdata with datekeys-go at the tag spec-v0.10 (cc35d2c) and
moves the reader to the DateKeys Protocol Specification v0.10. The
three capsule formats are read.
- framing: FORMAT_3, and isPadded for formats 2 and 3. control: schema
version 3, with the keys 6 and 7 of version 2. SPEC_VERSION is 0.10.
- open: OpenOptions.sink receives the files of a format 3 capsule
(sink.ts: Sink with begin, create, commit and abort, as capsule.Sink,
and MemorySink). Without one, open rejects with a TypeError right
after step 2, before any request, as ErrSinkRequired. Opened gains
head, verdicts, areaLen and unusableHeadExtensions.
- open3.ts: step 17 of format 3 in its substeps 17.2 to 17.8, as
openBody of the reference: a failure of age or a plaintext whose
length is not P prevails, the first failing substep decides, and the
codes other than ERR_INTEGRITY are reported only after reading
PAYLOAD_AGE to its end. Reads grow with the bytes received, never
with the lengths BODY declares. A failure of the sink is ERR_INTEGRITY
with its text, and the sink is aborted once after begin.
- The page: opener.ts opens the fixtures of format 3 into a
MemorySink; the open panel says that it does not deliver their files
yet, and the glosses of the steps name format 3. check-build.mjs
refuses to ship the heads, salts, comments and paths of the format 3
fixtures.
Tests: the 21 fixtures, format 3 laid out byte by byte from its record
and opened into a sink with its files and verdicts; the 209 cases of
the corpus from memory and from a Blob, with the code, the step and,
new, the exact text of capsule.Open, frozen by
scripts/mutation-go-texts.go in testing/mutation-texts.json, which
replays the corpus as internal/testkit does (its extension validator
texts included); the 5110 differential cases over 14 bases; paths,
path_fold, head_schema and security vectors; the control of schema
version 3 in cbor.json; and step 17 on crafted plaintexts sealed again
to I_PAYLOAD, whose texts capsule.Open gives on the same plaintexts.
ibe-vectors.json gains the nine format 3 fixtures from
scripts/ibe-go-vectors.go; the twelve before are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Syncs testdata with datekeys-go at spec-v0.9 (7e2d83c) and moves the
reader to the DateKeys Protocol Specification v0.9. Both capsule formats
are read; a format 1 capsule keeps the verdict v0.8.2 gave it.
- framing: the VERSION of the prelude is the capsule format, 1 or 2
(Prelude.format, FORMAT_1, FORMAT_2, isFormat).
- control: decodeControl and encodeControl take the format; schema
version 2 adds payload_length (8 bytes, at most L_MAX) and padding
(1 or 2).
- padding.ts: the rules bloque256 and reforzado of spec §29.1, exact up
to L_MAX with BigInt bit lengths and ceil roundings, and the length of
PAYLOAD_AGE.
- open: exactly 16 stanzas in INNER_ACCESS_AGE of format 2 (step 12), P
at step 16, and at step 17 a plaintext of exactly P bytes whose
padding is zero; only the first L bytes are delivered, never the
padding. Step 17 is recorded when it passes, and step 18 gives the
bytes of content, as the reference does. Opened reports the format, L
and, in format 2, the rule and P.
- inspect: the JSON view carries format, as datekeys inspect -json.
- The page shows the format, warns about format 1, and gives the
padding rule and P once a format 2 capsule opens.
Tests: the twelve fixtures, the 125 mutation cases through open from
memory and from a Blob, the 4380 differential cases, padding.json, the
format 2 CBOR vectors, and padding.test.ts against a BigInt statement of
§29.1. The error texts of the 125 corpus cases were compared with
capsule.Open at spec-v0.9. ibe-vectors.json gains the seven format 2
fixtures from scripts/ibe-go-vectors.go; its frozen values are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The final commit of spec v0.8.2, tagged spec-v0.8.2 after the author's
approval. Only testdata/README.md changes: it says that the mutation
corpus registers its extensions in both arrays of every object, like a
Go Registry without extension.Placement. No fixture or vector changes,
and no Go error text of steps 1 to 8 changes: the second-round
corrections touch step 9 and the drand client, which App does not
implement yet. npm run verify is green: 2,379 tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
testdata is synced from datekeys-go c57ed48, which adds
vectors/tlock_ibe.json, the frozen H2 of the tlock IBE (spec §63 step
11). Until phase 2 brings the IBE, the harness recomputes it with the
audited @noble/curves 2.4.0 (development only): the points are canonical
for bls12381.ts, noble's pairing serialized in the order of kilic is the
vector's GT, its H2 matches, and noble's own Fp12.toBytes order gives
another hash.
The extension registry gains the optional registeredIn: a known
extension out of the objects and arrays of its registration counts as
unknown there (spec §54, §72), as Go's extension.Placement; step 4 of
inspect checks PUBLIC_HEADER with it. A test copies a CONTROL_CBOR-only
critical extension into PUBLIC_HEADER and fails if the check is removed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
testdata is synced from datekeys-go f6f2e9f: mutations.json has 65
cases, the ten new §64 ones at steps 10 and 11 (phase 2, skipped and
counted: 31 run, 34 skipped).
The reference no longer copies library error text into errors, so the
TypeScript uses its fixed texts too: every unreadable age header is
"agewrap: not an age v1 header: malformed, truncated or beyond the
parser limits", with the parser's reason in the error's cause, which the
tests still compare with age's own texts; the profile messages for an
unknown drand scheme and a non-canonical public key follow Go. Against
Go at f6f2e9f, 407,196 differential inputs agree on verdict, code, step,
error text, check details and the full inspect -json output.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
testdata is synced from datekeys-go 692cf87, where the reference stopped
replacing invalid UTF-8 in the dk1_ JSON with U+FFFD and fails step 2
with ERR_DATEKEY_INVALID, as §19 requires. parseJSON checks the bytes
first in the same way, the test that pinned the old reference behaviour
now pins the spec's, and the README drops the Go-vs-spec conflict note.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
testdata synced from datekeys-go 3820066 (verified with sync-testdata
check --against): cbor.json, mutations.json, inspect_differential.json,
the inspect goldens, testdata/README.md and the three new dk1.json
vectors. The alignment of src/lib/dkc and of the vector harness was cut
off by a usage limit halfway through a refactor: tests and typecheck
fail. Kept on this branch so that main stays green; it is finished here
and merged when every check passes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Skeleton for the TypeScript implementation of DateKeys v0.8.x: the plans
in docs/, testdata/ vendored from g.activething.com/go/DateKeys at 5719f6a
with a zero-dependency sync and check script, and the TypeScript and vitest
tooling already used by the prototype, which now lives in ../AppOld.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>