@ -8,7 +8,7 @@ La especificación 0.15, de la rama `v0.15` de `datekeys-go`: el objeto release,
### La especificación 0.15: el objeto release y el release en la mano (07-10-2026)
- `SPEC_VERSION` pasa a `0.15` y la versión a `0.4.0-dev`. `testdata` se sincroniza con `datekeys-go` en `3c3e737`, que añade `vectors/release.json`, los ficheros de `releases/` y el campo `source` de `mutations.json`.
- `SPEC_VERSION` pasa a `0.15` y la versión a `0.4.0-dev`. `testdata` se sincroniza con el tag `spec-v0.15` de `datekeys-go` (`fe50885`), que añade `vectors/release.json`, los ficheros de `releases/` y el campo `source` de `mutations.json`.
- **El objeto release** (§47.1). `releaseobject.ts`, sin noble, hace lo de `provider/release.go` y `provider/archive.go` de Go, con sus textos byte a byte: `encodeRelease` y `decodeRelease`, con las capas del paso 10 (el tamaño de 1 a 1024 bytes antes de decodificar, el tipo y la versión, el schema); `parseRelease`, que lee también el JSON de drand como lo lee `encoding/json` de Go, con `ERR_RELEASE_INVALID` para cualquier fallo; `ReleaseSupplier` y `encodedRelease`, el release en la mano; y `ReleaseArchive`, el archivo de releases local, formato informativo (§50), cuyos fallos son `ERR_RELEASE_UNAVAILABLE`, también una ronda a ceros.
- **La cadena en el paso 10.**`verifyRelease` compara primero la cadena que nombra el release con la del perfil fijado (`ERR_PROFILE_MISMATCH`), y después la ronda y la firma.
- **El paso 9.c, opción B.**`open` acepta `release`, un release en la mano, en lugar de `source`: no se compara con el reloj, `Opened.clockBehind` dice si el reloj iba por detrás de la fecha, y el paso 10 lo decodifica con los códigos de ese paso. A una fuente de red no se le pide nada antes de `round_time`, como antes. El release verificado lleva la cadena del perfil fijado.
@ -21,7 +21,7 @@ Hay tres números de versión, cada uno con su significado, como en la referenci
| Versión | Dónde | Cambia cuando |
|---|---|---|
| Formato | Dentro de los objetos: el formato de la cápsula, el `VERSION` del prelude de DKC1, 1, 2 o 3 al leer, que fija también la versión de schema de CONTROL_CBOR; y 1 en la trama DKK1 y en el schema de los demás objetos | Cambia el formato. Un lector rechaza una versión que no conoce (§22, §70) |
| Especificación | `SPEC_VERSION` de `src/lib/dkc/version.ts`, hoy `0.15`: la v0.15 de `datekeys-go`, en su rama `v0.15`. `testdata` está en `3c3e737`, y todos sus ficheros dicen `0.15` | Cambia el texto normativo |
| Especificación | `SPEC_VERSION` de `src/lib/dkc/version.ts`, hoy `0.15`: la del tag `spec-v0.15` de `datekeys-go`, que aprobó el autor el 7 de octubre de 2026. `testdata` está en ese tag (`fe50885`), y todos sus ficheros dicen `0.15` | Cambia el texto normativo |
| Librería | `VERSION` de `src/lib/dkc/version.ts`, igual al campo `version` de `package.json` | Cambia la API o el comportamiento. Versionado semántico, sin promesa de estabilidad antes de 1.0.0 |
`version.test.ts` comprueba que `VERSION` coincide con `package.json` y con su lockfile, y que `SPEC_VERSION` es la versión que nombran los vectores y fixtures compartidos; `vectors.test.ts` exige esa versión a cada fichero. El pie de la página muestra las dos.
@ -466,7 +466,7 @@ Comprueba que los ficheros coinciden con `SOURCE.json`, sin faltantes ni sobrant
`.gitattributes` marca `testdata/**` como binario para que git no altere ningún byte.
Copia actual: la de `testdata/SOURCE.json` (la v0.15 de `datekeys-go`, `3c3e737` de su rama `v0.15`), que se sincroniza con `node scripts/sync-testdata.mjs sync --repo ../datekeys-go --commit 3c3e737`. Añade `vectors/release.json`, los ficheros de `releases/` y el campo `source` de `mutations.json`.
Copia actual: la de `testdata/SOURCE.json` (el tag `spec-v0.15` de `datekeys-go`, `fe50885`), que se sincroniza con `node scripts/sync-testdata.mjs sync --commit spec-v0.15`. Añade `vectors/release.json`, los ficheros de `releases/` y el campo `source` de `mutations.json`.
| `vectors/dk1.json` | canonical `dk1_` strings, and rejected encodings with their code | §18, §19, §66 |
| `vectors/cbor.json` | the CBOR profile, and one block of vectors per schema, CONTROL_CBOR in the three formats | §58, CDDL |
| `vectors/tlock_ibe.json` | H2 of the tlock IBE: the serialization of an element of GT | §63 step 11 |
| `vectors/release.json` | the release object, the content of a `.dkr` file, and drand's JSON, each with the result of step 10; the lookups of a local release archive | §47.1, §50, §63 step 10 (v0.15) |
| `releases/<round>.dkr` | the release object of each published round of the tests: 1000, 1001, 1004 and 2000 | §47.1 (v0.15) |
| `vectors/release.json` | the release object and drand's JSON, each with the result of step 10; the lookups of a local release archive | §47.1, §50, §63 step 10 (v0.15) |
| `releases/<round>.cbor` | the release object of each published round of the tests: 1000, 1001, 1004 and 2000 | §47.1 (v0.15) |
| `releases/archive_1000_1004.bin` | a local release archive, the informative format of §50, of rounds 1000 to 1004, two of them missing | §50 (v0.15) |
| `vectors/tlock_steps.json` | steps 10 and 11 for Quicknet value by value: the message of a round, its hash to G1, and the decryption of a tlock stanza with H2, H4, H3 and the file key | §63 steps 10 and 11 (v0.14) |
| `vectors/padding.json` | the padding of formats 2 and 3: P for each content length L, and the length of PAYLOAD_AGE | §29.1 |
@ -320,8 +320,9 @@ writes them, give `0118eea9d5971745f71e3c94926f1717` and another FK_TIME.
## `vectors/release.json` and `releases/`
The release object of spec v0.15, §47.1: the release of a round as a file,
`.dkr`, that a person keeps next to the capsule. It is deterministic CBOR with
The release object of spec v0.15, §47.1: the release of a round as data,
the answer of the Release API, an entry of a Release Cache and a release the
caller gives from a file or from an archive. It is deterministic CBOR with
the profile of §58, a map of five keys, all required:
```text
@ -332,10 +333,11 @@ the profile of §58, a map of five keys, all required:
4 → signature (1 to 96 bytes; 48 in Quicknet)
```
The object of a round above 255 measures 111 bytes. `releases/<round>.dkr` is
the object of each published round the fixtures use, 1000, 1001, 1004 and
The object of a round above 255 measures 111 bytes. `releases/<round>.cbor`
is the object of each published round the fixtures use, 1000, 1001, 1004 and
2000, with the Quicknet chain hash: the release that opens each fixture, as a
file.
file. The protocol gives the object no file extension; `.cbor` is the generic
one of CBOR (RFC 8949).
`release.json` has three lists:
@ -364,7 +366,7 @@ file.
each round, one after another; a round the archive lacks is 48 zero bytes.
This one holds rounds 1000 to 1004, and 1002 and 1003 are zeros. Each lookup
gives a `round` and its `result`: `ok` with the `encoding` of the release
object the archive supplies, the `.dkr` of that round, or
object the archive supplies, `releases/<round>.cbor` for that round, or
`ERR_RELEASE_UNAVAILABLE` for a round the archive lacks or does not cover.
The texts are those of the reference, for an implementation that wants to
@ -848,12 +850,13 @@ reading flow (`capsule.Open`, §63) must fail.
cases only, is the chain the release object names when it is not the
Quicknet chain.
- `source` (v0.15): what kind of source answers, spec v0.15 §63 step 9:
- `supplied`: the release is in the caller's hand, as a `.dkr` would be.
- `supplied`: the release is in the caller's hand, as a release object
read from a file would be.
The reader is given the release object of `release`, with the Quicknet
chain hash unless `chain_hash` says another, and decodes and verifies it
at step 10: one that breaks a rule of step 10 gets the code of step 10.
The clock is not compared with the round time (step 9.c): with a `now`
before it, the capsule opens all the same. Every case but three is
before it, the capsule opens all the same. Every case but two is
`supplied`.
- `network`: a network source, such as a drand relay. It is never asked
before the round time (step 9.c), and it verifies its answer with the
@ -888,7 +891,7 @@ reading flow (`capsule.Open`, §63) must fail.
Every case reproduces offline: the recorded release stands in for the network.
What v0.15 changed in this file: every case gained `source`, `supplied` but
for three; the further case "round not reached yet", a valid release of round
for two; the further case "round not reached yet", a valid release of round
1000 and a clock one nanosecond before its round time, was
`ERR_RELEASE_UNAVAILABLE` at step 9 and now opens (`ok`, step 0, with
`network` true), because the release is in the caller's hand; and four cases
"description":"The release object, the content of a .dkr file (spec v0.15, §47.1), and drand's JSON as the input of the caller, each checked against the pinned Quicknet profile and the round of a DateKey as step 10 of spec §63 checks a release that the caller supplies; and the lookups of a local release archive (spec v0.15, §50). See testdata/README.md.",
"description":"The release object (spec v0.15, §47.1), and drand's JSON as the input of the caller, each checked against the pinned Quicknet profile and the round of a DateKey as step 10 of spec §63 checks a release that the caller supplies; and the lookups of a local release archive (spec v0.15, §50). See testdata/README.md.",