datekeys-ts 0.4.0 implements spec v0.15 (tag spec-v0.15 of datekeys-go):
the release object, release archives and a release in hand that the clock
does not stop, besides everything 0.3.0 does.
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>
datekeys-ts 0.3.0 implements spec v0.14 (tag spec-v0.14 of datekeys-go):
one drand scheme and the root of trust byte for byte, with the vectors of
tlock_steps.json, besides everything 0.2.0 does. It is the version frozen
for the external review.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
datekeys-ts 0.2.0 implements spec v0.13 (tag spec-v0.13 of datekeys-go): it
reads capsule formats 1 to 3 and writes format 3, with the author signature
of alg 1 and alg 2, the seal, the key of words, the public note and the
locator of datekeys.capsule, and the /inspect and /create pages.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
datekeys-ts 0.1.0 inspects and opens DateKeys capsules of both formats
of spec v0.9 (tag spec-v0.9 of datekeys-go), in memory or streaming,
with the /inspect page. The writer of phase 3 comes with 0.2.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The handoff, the plans and the protocol review describe the whole project,
not this implementation, so they move unchanged to the private docs
repository next to this one (../docs, commit 6e8d6c6).
The folder is being renamed from App to datekeys-ts, to match datekeys-go.
The package name, the README title and the site's licence notice follow.
The README points to the prototype's new place, ../archive/prototype.
npm run verify is green: 2,611 tests, build and build checks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
src/lib/dkc/open.ts runs steps 9 to 18 of spec §63 on top of the steps
1 to 8 of inspectWith. It follows capsule.Open of the Go reference, with
its checks, codes and texts:
- step 9: the access credentials (the .dkk as an object, then its
capsule_id and capsule_digest), then the release, never before the
round time. Any failure of the source is ERR_RELEASE_UNAVAILABLE
alone, keeping its text and its cause (correction 6);
- step 10: verifyRelease;
- steps 11 to 13: OUTER_TIME_AGE, the structure against access_policy
and INNER_ACCESS_AGE;
- steps 14 to 18: CONTROL_CBOR, header_binding, I_PAYLOAD, PAYLOAD_AGE
and the commit.
The three age files open with the Decrypter of age-encryption and
identities that apply the rules of Go's agewrap: the tlock identity on
ibe.ts, and the access and payload identities on x25519.ts. A failure of
age that no identity reports is ERR_INTEGRITY with the fixed reason of
its phase, header or STREAM, never the text of age-encryption. The
plaintext is decrypted in memory and returned only after step 18.
Streaming to OPFS is step 5b.
src/lib/dkc/x25519.ts opens one age X25519 stanza at a time, in the
order of age's X25519Identity. Step 13 must try every identity on every
stanza (spec §36), and age-encryption's Decrypter stops at the first.
Its primitives are the ones age-encryption uses: X25519 and HKDF from
noble curves and hashes, and ChaCha20-Poly1305 from @noble/ciphers
2.4.0. The author approved declaring that package as a direct
dependency on 2026-09-28; it is the copy already installed and bundled.
The guards now allow ciphers, and x25519.ts in the noble allowlist.
src/lib/dkc/bech32.ts ports age's internal/bech32, with its MIT notice,
to read AGE-SECRET-KEY-1 identities.
Tests:
- vectors.test.ts runs all 65 cases of the mutation corpus through open.
Each gives the code and the step of Go, and no case that fails without
the network requests a release. This includes the 34 cases of steps 9
to 18 that were skipped, so the suite no longer skips any test.
- open.test.ts:
- the five official fixtures open to their plaintext, with each
credential, with the checks and details of the reference;
- the unusable noncritical extensions are reported;
- the source failures and the clock;
- age failures by phase;
- CONTROL_CBOR that does not decode, and a low-order share in
INNER_ACCESS_AGE, through an OUTER_TIME_AGE resealed with the FK_TIME
of the Go vectors;
- the texts of the identities.
- x25519.test.ts checks against age-encryption both ways and against the
Go-written stanzas of the fixtures, and covers every low-order share.
- bech32.test.ts has the vectors of the reference.
x25519.ts and bech32.ts are at 100 % coverage, now thresholds. open.ts
is at 100 % of lines; the one branch left is the one for an error that
is not a DateKeysError.
index.ts does not re-export the opening yet. The page imports index.ts,
and re-exporting would pull noble into /inspect (58.7 to 84.9 KB gzip)
even unused; step 8 will load it on demand. The site does not change.
npm run verify is green: 2,490 tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- src/lib/dkc/version.ts exports VERSION (0.1.0-dev, which becomes
0.1.0 once phase 2 adds the opening of capsules) and SPEC_VERSION
(0.8.2, the tag spec-v0.8.2 of datekeys-go), from index.ts too.
- package.json and its lockfile move to 0.1.0-dev. version.test.ts ties
VERSION to both and checks it is semantic versioning. It also ties
SPEC_VERSION to the spec field of the shared vectors and fixtures.
testing/vectors.ts now takes SPEC_VERSION from version.ts, so every
vector file is checked against the version the library declares.
- The footer of the page shows both, instead of a fixed 0.8.2.
- README.md gains a "Versiones" section: the three versions (format,
specification, library) and what 0.1.0-dev covers. CHANGELOG.md is
new.
The Go reference gained datekeys.SpecVersion, datekeys.Version() and
`datekeys version` in 5b342d3.
npm run verify is green: 2,406 tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- age-encryption 0.3.1, @noble/curves 2.4.0 (moved from dev) and
@noble/hashes 2.4.0 become exact runtime dependencies (plan section 3,
decision 5). The lockfile gains six packages: age-encryption,
@noble/ciphers 2.4.0, @scure/base 2.4.0, @noble/post-quantum 0.5.4 and
its own @noble/curves and @noble/hashes 2.0.1. No file of src/ imports
them yet, so the site does not change.
- src/lib/dependencies.test.ts guards them. package.json declares exactly
these three, pinned. The lockfile has no tlock-js, drand-client or noble
1.x, and no noble 2.x copy other than 2.4.0 at the root and 2.0.1 under
@noble/post-quantum. No file of src/ imports tlock-js or drand-client.
Only ibe.ts, release.ts and the tests name @noble/, always subpaths of
@noble/curves or @noble/hashes that resolve to the root 2.4.0 copy.
Every check also runs on bad inputs. It replaces the "only tests import
@noble/curves" test of bls12381.contrast.test.ts.
- vite.config.ts records the modules of each client chunk in
.svelte-kit/output/client-modules.json. check-build.mjs fails if the
bundle holds tlock-js, drand-client or @babel/*, or a nested copy
other than noble under @noble/post-quantum. It also reports the
JavaScript each page loads: /inspect today loads 157 KB, 58.7 KB gzip.
- Measured with a probe build (Vite 8, minified, gzip 9): the Decrypter
is 48 KB gzip, with the Encrypter 56 KB, noble BLS12-381 plus SHA-256
28 KB, and all of them 73 KB. age-encryption imports its hybrid ML-KEM
recipients statically, so post-quantum and its nested noble copy are
about 99 KB of the Decrypter's 212 KB of rendered code.
- npm audit --omit=dev: no vulnerabilities. The full audit finds two low
ones in the tooling: cookie < 0.7.0 through @sveltejs/kit 2.70.3,
which is the latest version and affects only SvelteKit's server.
npm run verify is green: 2,384 tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The author confirmed the decisions of PLAN_fase2_ibe_noble2.md (v2),
with the adjustments of two reviews verified against the code, the spec
and npm: the ReleaseSource contract (a source that obtains no verified
release fails at step 9 with ERR_RELEASE_UNAVAILABLE, a caller-supplied
release at step 10 with ERR_RELEASE_INVALID, as Go's drand client);
age-encryption 0.3.1 without npm overrides, accepting the nested noble
2.0.x of @noble/post-quantum (~2.0.0) under guards that keep the BLS
code on the exact 2.4.0; streaming decryption of PAYLOAD_AGE into OPFS,
released only after age succeeds (§56), with the storage quota as the
limit; IBE test vectors generated from the Go reference; verifyRelease
in the order of provider.Verify; the canonicality spec change as an
amendment of v0.8.2.
App is now Apache-2.0, like the Go reference.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Our checkCompressedPoint stays: it matches the Go reference on every edge
case, is 1.3 KB gzip and adds no runtime dependency. Its assurance now
comes from a contrast test run on every test pass:
- 41 frozen edge-case encodings with the Go reference verdict (drand crypto
KeyGroup over kyber-bls12381 and kilic/bls12-381, as profile.Validate
uses it), reproducible with scripts/bls12381-go-verdicts.go;
- the audited @noble/curves 2.4.0 on the same edge cases and on a
fixed-seed corpus of valid points, negations, bit flips, random x and G1
points on the curve outside the subgroup.
Breaking the G1 or the G2 subgroup check makes the test fail.
@noble/curves 2.4.0 is a development dependency only; a test fails if
anything that is not a test imports it, and the build contains none of it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A prerendered static site (adapter-static) with a landing page and
/inspect, which runs spec §63 steps 1 to 8 on a .dkc chosen with the file
picker, dropped anywhere on the page, or taken from the official fixtures
bundled at build time. It shows every step, the decoded header, the unlock
date in UTC and local time, and each extension's id, version, criticality,
length and hex, with a text view and an informative CBOR diagnostic view,
all escaped and labelled as unauthenticated before step 15. Copiar JSON
copies the exact "datekeys inspect -json" view.
No network: a hash-mode Content-Security-Policy with connect-src 'self'
is the first element of every page, and scripts/check-build.mjs verifies
it, the fixtures and the absence of external URLs after every build.
Large files are read only up to what steps 1 to 8 need.
Reviewed for design and accessibility (WCAG AA contrast, keyboard,
focus, live status, 360 px), security and correctness; 262 tests pass,
svelte-check has no warnings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Canonical CBOR codec of the spec §58 profile, hand-written schema codecs
(profile, PUBLIC_HEADER, CONTROL_CBOR, .dkk, extensions), DKC1/DKK1
framing, a strict age header parser, dk1_ parsing and nanosecond date to
round resolution, and inspect (spec §63 steps 1 to 8) with the same checks
and view as "datekeys inspect -json". No runtime dependencies.
216 tests, cbor.ts at 100 % coverage, typecheck of the library without
Node types. A differential comparison with the Go reference at afb44a3
found no verdict, code or step disagreement in about 336,000 inputs. The
harness for the future Go vector files runs them when they appear.
vite 8.3.0 is declared explicitly: it is a required peer of vitest 5.0.1
that legacy-peer-deps does not install.
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>