@ -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)
### 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.
- **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.
- **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.
- **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 |
| 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) |
| 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 |
| 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.
`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.
`.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/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/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/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) |
| `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>.dkr` | the release object of each published round of the tests: 1000, 1001, 1004 and 2000 | §47.1 (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) |
| `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/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 |
| `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/`
## `vectors/release.json` and `releases/`
The release object of spec v0.15, §47.1: the release of a round as a file,
The release object of spec v0.15, §47.1: the release of a round as data,
`.dkr`, that a person keeps next to the capsule. It is deterministic CBOR with
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:
the profile of §58, a map of five keys, all required:
```text
```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)
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 a round above 255 measures 111 bytes. `releases/<round>.cbor`
the object of each published round the fixtures use, 1000, 1001, 1004 and
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
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:
`release.json` has three lists:
@ -364,7 +366,7 @@ file.
each round, one after another; a round the archive lacks is 48 zero bytes.
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
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
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.
`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
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
cases only, is the chain the release object names when it is not the
Quicknet chain.
Quicknet chain.
- `source` (v0.15): what kind of source answers, spec v0.15 §63 step 9:
- `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
The reader is given the release object of `release`, with the Quicknet
chain hash unless `chain_hash` says another, and decodes and verifies it
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.
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`
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`.
`supplied`.
- `network`: a network source, such as a drand relay. It is never asked
- `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
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.
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
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
1000 and a clock one nanosecond before its round time, was
`ERR_RELEASE_UNAVAILABLE` at step 9 and now opens (`ok`, step 0, with
`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
`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.",