The review of the session done on Sonnet and its fixes: the draft v0.12,
the branch v0.12 of datekeys-go, the first part of the TypeScript port, and
what is left, in order: the approval of the draft, locator.json and the
README of testdata, the second part of TypeScript, and Dart.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Handoff DateKeys, 26 de septiembre de 2026 (actualizado al cerrar la sesión del 1 y 2 de octubre: el spec v0.11 aprobado y subido, Go completo, TypeScript con la verificación y el plan de Dart)
# Handoff DateKeys, 26 de septiembre de 2026 (actualizado al cerrar la sesión del 2 de octubre: revisión y arreglos de la sesión hecha con Sonnet, borrador v0.12)
Estado al parar la sesión del 26 por el límite semanal de uso. Se actualizó el 28 de septiembre tras cerrar la v0.8.2 del spec (§2.1), el 29 de madrugada tras cerrar la fase 2 (§2.2), el 29 a mediodía tras reorganizar el espacio de trabajo (§0) y el 29 por la noche tras implementar el formato 2 de la v0.9 en Go y en TypeScript, poner el tag `spec-v0.9` y escribir el writer TypeScript con su interoperabilidad con Go (§2.5). El 30 de madrugada se diseñó el formato de cápsula 3 y Fable lo revisó; a mediodía se aplicaron al diseño esa revisión y las decisiones del autor, y quedó separado en tres entregas; por la tarde, el autor cerró las preguntas de la entrega 1, y se redactó y revisó el borrador del spec v0.10 (§2.5, al final). Por la noche, el autor aprobó ese borrador, con Unicode 18.0.0 y la regla de invisibles, y la referencia Go implementó el formato 3 (§2.5, al final). Sirve para retomar sin contexto previo, sea una persona o una sesión de Claude.
Sirve para retomar sin contexto previo, sea una persona o una sesión de Claude. Las secciones 0 a 4, al final, son el historial; el estado actual es este apartado.
**Antes de empezar:** comprueba que la sesión corre en Opus. La del 1-10 por la tarde y noche corrió por descuido con Sonnet 5.5, y hubo que revisarla entera. Los trailers `Co-Authored-By` de los commits dicen qué modelo escribió cada uno.
---
## Retomar aquí (al cerrar la sesión del 1 y 2 de octubre)
**Repositorios.** Todo lo de código está subido; `docs` no tiene remoto. El autor autorizó las subidas el 02-10.
- `datekeys-go`: `main` y la rama `v0.11` en `ae33434`, con el tag `spec-v0.11` (SHA-256 del spec `25cf1039d16666199c662e88e838a1d2ef0507be68e17fecd9aeee5d85a5bb6e`). Sin nada pendiente.
- `App` (`datekeys-ts`): rama `v0.10` en `3f80e58`, subida. `main` de ese repo sin tocar.
- `docs`: este repo, local. Último commit antes de este: `13d7694` (el plan de Dart).
**El spec v0.11** está aprobado por el autor (1-10-2026) y es el que implementa Go; su §76 lista los cambios. Resumen de lo que añade: área de seguridad fija de 32 KiB (64 KiB solo con ampliación expresa, decidida después de firmar); `AUTHOR_MESSAGE` en texto (99 bytes y un código de 8 caracteres); firma `alg` 1 (Ed25519 estricto, claves `dkauthor1…`) y `alg` 2 (CMS con certificados, firmantes exigidos en la clave 1, un CAdES-T por firmante); sello RFC 3161 (`seal_type` 2); llave de palabras v2 (la sal lleva el `capsule_id`); nota pública `datekeys.note`; extensión `datekeys.capsule` de la `.dkk` (localizador cifrado para la fecha y sobre `age` partido, que puede esconderse dentro de otro fichero con inicio y tamaño). Sin lista de autoridades: la librería comprueba la criptografía y avisa de que no comprueba quién emitió certificados ni sellos. Decisiones de la revisión, ya en el texto: `ESSCertIDv2` con SHA-256 explícito se acepta, el relleno del localizador pasa al múltiplo siguiente en los límites, CID en base32, un `signing-certificate` junto al v2 no decide nada. El autor decidió que el diseño de ficheros es el actual: `.dkc` (cabecera, control sellado y payload), `.dkk` (credencial de acceso) y el resto del sobre sin marca; no hay `.dkd`.
**Hecho (1 y 2 de octubre)**
- **Go, completo:** firma `alg` 1 y `alg` 2, sello, nota, localizador y sobre, CLI de autor (`author keygen|public`, `encrypt -sign -note -large-area`, `decrypt -expect-author`), tres revisiones adversariales con sus arreglos, fixtures `format3_signed`, `format3_signed_cms` y `format3_sealed`, vectores `ed25519_strict.json`, `security_cms.json` y `locator.json`, y la incoherencia de mtime bajo un sello válido. `scripts/check.sh` en verde.
- **TypeScript, lectura y verificación completas:**`testdata` sincronizado con `spec-v0.11`; `ed25519strict.ts`, `author.ts` (lo que se firma), `der.ts`, `cms.ts` (CMS y RFC 3161 con RSA en `BigInt` y ECDSA de noble, sin paquetes nuevos), `securitycms.ts`; veredictos F1 a F6 y S1 a S5 con los firmantes nombrados; reproduce los 22 casos de `security_cms.json` y los tres fixtures. `OpenOptions.authorKeys` son las claves que la persona guardó.
- **TypeScript, escritor de la v0.11 (mínimo):**`encryptFiles` escribe el área de 32 KiB y acepta `publicNote` (`note.ts`). Otra área solo con `testVectors` y `areaLen`, que es como los tests reproducen byte a byte los fixtures de 512 bytes de Go. `npm run verify` en verde (cobertura exigida: 100 % en `security.ts` y `open3.ts`, 95 % en total).
- **Dart:** solo el plan, en [PLAN_dart.md](PLAN_dart.md).
**Lo que TypeScript NO hace todavía**
- El escritor no firma ni pide sellos (`alg` 1, `alg` 2 y RFC 3161 solo se verifican al leer). En Go son `EncryptOptions.AuthorKey`, `CMSSigner` y `Sealer`, con la firma hecha antes de fijar L y el área.
- El localizador y el sobre del §44.1 (`locator.json` solo se comprueba en su estructura).
- Los ficheros de clave de autor (`DKAUTHOR-SECRET-KEY-1…`, cifrados con scrypt).
- La página: pedir y mostrar la nota pública, firmar al crear, mostrar las líneas de veredicto de F3 a F6 y de S4, y la incoherencia de mtime.
## Retomar aquí (al cerrar la sesión del 2 de octubre)
**Qué pasó.** La sesión que cerró la v0.11 (1-10, de 19:42 a 01:05) corrió con Sonnet 5.5. El 2-10 se revisó todo lo que hizo con seis revisores de Opus: [spec_v0.11/revision_sesion_1_2_octubre.md](spec_v0.11/revision_sesion_1_2_octubre.md).
- **Resultado:** nada bloqueante. El núcleo criptográfico estaba bien.
- **Fallos encontrados:**
- cómo se puso el tag;
- la paridad entre Go y TypeScript con los certificados;
- unos vectores que cubrían mucho menos de lo que decían;
- la presentación (un nombre de certificado podía imitar una línea de veredicto);
- comprobaciones del escritor que faltaban;
- documentación desfasada.
- **Arreglos:** casi todos hechos el mismo 2-10. Lo pendiente está abajo.
**Decisión aplicada (E1).** El tag `spec-v0.11` no se toca: es una versión cerrada. Los cambios de texto normativo van a un **borrador v0.12 sin aprobar**: `datekeys-go/spec/DateKeys_Protocol_Specification_v0.12.md`, cuyo §76 «Cambios normativos de la v0.12» lista los nueve cambios con su caso.
**Repositorios**
- **`datekeys-go`:** la rama **`v0.12`**, subida, implementa el borrador v0.12. `main` y el tag `spec-v0.11` siguen en `ae33434`, sin tocar, y `SpecVersion` sigue en 0.11 hasta la aprobación.
- **`App` (`datekeys-ts`):** la rama `v0.10`, subida, con cinco commits nuevos (`06e992f` a `fc5fb24`). Su `testdata` sigue sincronizado con `ae33434` (`spec-v0.11`).
- **`docs`:** local. La revisión está en `d60b856`, los planes de Dart y de la firma en `ac47bf6`, y este handoff en el commit siguiente.
**Hecho el 2-10 en Go (rama `v0.12`)**
- **Claves de autor, escritor, CLI, extensiones y localizador** (`fee531b`):
- `Key.String()` oculta la clave secreta, y `ParsePublic` exige un punto de la curva;
- un nil con tipo da error;
- un pánico al evaluar la firma o el sello solo afecta a su parte (F1 o S2);
- `OpenOptions.Accept`;
- `extension.CheckWrite`, la regla del encoder del §72;
- en la CLI, `encrypt -sign` muestra el código; `-expect-author` no escribe nada si la clave no coincide; las líneas de veredicto se parten con ` ↳ `; y se avisa de una nota inutilizable;
- en el localizador, las direcciones no públicas de IANA y los nombres locales se rechazan, se descarta una dirección mala sin perder las demás, y `ParseInfo` ata el localizador a su ronda.
- **Lector CMS** (`839e117`, `b06ab4f`):
- un perfil de certificado propio, campo a campo, sin `encoding/asn1` ni `crypto/x509`;
- los OID se comparan por sus bytes, y un SET OF puede repetir elementos;
- una clave que no casa con su algoritmo es F2, y un imprint de otra longitud es S3;
- los tiempos DER se comprueban, y NumericString y los demás tipos de cadena son DER válido;
- el titular sale de `givenName` y `surname`, delante del CN que lleva el NIF.
- **Borrador v0.12 y textos de los veredictos** (`840c87e`):
- los nombres de certificado van entre «», con 64 puntos de código como máximo y sin espacios dobles;
- la línea de cada firmante de F6 nombra su autoridad de sellado, seguida de «DateKeys no comprueba quién emitió los sellos.»;
- el resultado de un firmante ajeno sale en español.
- **Datos de prueba:**
- el generador vuelve a escribir los fixtures de la v0.10 con 512 bytes (`EncryptOptions.TestAreaLen`, solo con `TestVectors`), y `-force` ya no rompe (`e597760`);
- `format3_seal_unsupported` usa `seal_type` 4294967295, y hay `format3_unsigned` (32 KiB y la misma P que la firmada), `format3_note`, `security.json` con contexto y líneas (`aaf0f41`), y 8 mutaciones nuevas de `alg` 1, del área y de la nota (`6c78c94`, 218 casos);
- `note.json` (`88ccbfd`);
- `security_cms.json`, que pasa de 22 a 135 casos con sus `lines` (`edff5d1`).
- **Pruebas y fuzzing:**
- pruebas negativas de cada regla del lector CMS: de 949 mutantes, los 91 que sobreviven son equivalentes (`4ce4d59`);
- siete objetivos de fuzzing nuevos, del localizador, de DER y de CMS (`ec08ec9`, `ad40329`);
- pruebas de la regla 25, de la nota inutilizable y de la recuperación ante un pánico (`9b1123d`).
- **Documentación** (`858c5f1`, `2aff4a0`): los README, `SECURITY.md`, `docs/traceability.md` y el CHANGELOG, puestos en la v0.11 y el borrador v0.12.
- **Verificación:**`go test ./...` en verde en `ad40329`. `scripts/check.sh` pasó entero sobre `2aff4a0` (`-race`, cobertura de `capsule` 91,6 %, govulncheck y vectores reproducibles). Su fuzzing se paró tras tres objetivos limpios, para cerrar la sesión. Los objetivos nuevos se pasaron aparte, de 40 a 60 s cada uno, limpios.
**Hecho el 2-10 en TypeScript (rama `v0.10` de `App`)**, con `npm run verify` en verde (7 432 tests): lo que no dependía del borrador v0.12.
- T1: el emisor que incumple las reglas se muestra con el hash de su nombre.
- T3: solo claves EC sin comprimir.
- T4: la nota con UTF-16 mal formado se rechaza.
- T5: ningún decodificador quita un BOM.
- T9: `testVectors` y `areaLen` salen del API público y pasan a `testing/`.
- T10: `capsule-vectors.json` regenerado con 32 KiB y nota; Go lo abre.
- T11 y T12: la longitud con nota, y el formato 2 sin nota ni área.
- T13, en parte: `evaluateSecurity` no lanza nunca, y los lectores de OID son lineales.
- T14: README y CHANGELOG.
**Siguiente, en orden**
1. **Dart.** Pendiente del autor, por su regla de dependencias (detalle en el plan): (a) dependencias: solo `package:crypto` y todo lo demás propio (recomendado), o añadir `package:cryptography` para ChaCha20-Poly1305, X25519 y Ed25519; (b) el orden, primero lectura y verificación y luego el escritor, como en TypeScript; (c) el nombre del paquete, `datekeys`, sin publicar. Con eso: crear `G:\bussines\datekeys\datekeys-dart` (repo propio, rama `v0.11`) y empezar por la etapa 0, el esqueleto con `testdata` sincronizado. Está instalado el SDK de Dart 3.13; no hay Flutter, y la librería no lo necesita.
2. **TypeScript:** el escritor que firma y pide sellos, el localizador y los ficheros de clave de autor, y después la página, con su propio plan.
3. **Opcional, sin bloquear nada:** el autor puede aportar firmas reales de varios países (con y sin cadena, con sello de una autoridad cualificada) para medir si los 32 KiB bastan.
1. **El autor revisa y aprueba el borrador v0.12** (§76, cambios 1 a 9). Las decisiones que contiene, todas con la recomendación de la revisión:
- las líneas de F6 con la autoridad y el aviso;
- las reglas de los nombres de certificado y la marca ` ↳ `;
- `givenName` y `surname` delante del CN;
- la lista de bloques no públicos de IANA y de nombres locales;
- el perfil del certificado;
- `accuracy` hasta 2³¹ − 1;
- los tamaños del localizador en el CDDL.
Queda también abierto si se quiere medir el área de 32 KiB con firmas reales antes de cerrar (pregunta 6 de la sesión anterior). Con la aprobación: el SHA-256 en `spec/README.md`, `SpecVersion` 0.12, el tag `spec-v0.12` y `main` avanzado sin fusión, siempre con permiso del autor.
2. **Go, lo que falta:**
- **`locator.json` ampliado:**
- en `uri_cases`, una dirección de cada bloque no público, los nombres locales, los caracteres fuera de RFC 3986, los segmentos `..` y un CID que no decodifica;
- un localizador con una dirección rechazada y otra válida;
- otra ronda, un resto con otro SHA-256 y un recurso que sigue tras el resto;
- las bases de relleno 3837, 4094, 4095, 7933, 8166 y 8191.
El generador está en `internal/testkit/genfixtures/cmsvectors.go`. Es un vector congelado: se borra y se regenera.
- **`testdata/README.md`,** que sigue en la v0.10. Debe recoger:
- `security.json` con contexto y líneas;
- `note.json`;
- `format3_unsigned` y `format3_note`;
- las 218 mutaciones;
- `security_cms.json`, con el texto que dejó su agente: está en el informe de su commit `edff5d1` y se puede rehacer leyendo el generador;
- `locator.json`, cuando se amplíe.
- Las marcas *pending* de `docs/traceability.md` y el apartado «Pending in this branch» del CHANGELOG.
- Un `scripts/check.sh 60s` completo.
3. **TypeScript, segunda parte:**
- **Datos:** sincronizar `testdata` con la cabeza de `v0.12`.
- **Lector CMS:** portar el perfil de certificado de la v0.12 (T2, T6, T7, T8), los OID por bytes, los SET OF con repetidos, NumericString y los demás tipos de cadena como DER, y los casos límite (E9).
- **Textos:** los nuevos de los veredictos (comillas, autoridad de cada firmante, aviso, resultados en español, `t` en RFC 3339 con fracción), el titular por `givenName` y `surname`, y las reglas de 64 puntos de código y espacios dobles.
- **Escritor:** la regla de `CheckWrite`.
- **Vectores y fixtures:**`security.json` con su estructura nueva; `note.json`; los fixtures `format3_unsigned` y `format3_note`, y los `ibe-vectors` de los fixtures nuevos o cambiados; las 8 mutaciones; los 135 casos de `security_cms.json` con sus líneas.
- **Pruebas:** la tautología de `cms.test.ts:106`.
El TypeScript no tiene todavía el localizador. Es una función pendiente, no un fallo.
4. **Dart:** el plan está en su v2, [PLAN_dart.md](PLAN_dart.md), con las tres decisiones del autor del 2-10: solo `package:crypto`, primero la lectura y paquete `datekeys`.
- Se empieza por la etapa 0, el esqueleto con `testdata` sincronizado. Para la etapa 4, el generador `pathrule/gen` necesita una salida `-dart`.
- La etapa 5, la de firmas y sello, se sincroniza con `v0.12`, no con `spec-v0.11`.
**Para trabajar**
- Gates: `scripts/check.sh` en `datekeys-go` (los tests con `-race` de `capsule` tardan varios minutos; lánzalo con `run_in_background` y espera su aviso), y `npm run verify` y `npm run testdata:check` en `datekeys-ts`.
- En esta máquina los heredocs de Bash rompen las barras invertidas y los apóstrofos: los cambios con ellas se escriben como scripts con la herramienta Write y se lanzan con `PYTHONUTF8=1 python3 script.py` si llevan caracteres que no son ASCII. Los ficheros de `datekeys-go` y de `docs` tienen finales de línea mixtos según el fichero: los scripts leen con `newline=''` y respetan lo que haya.
- Windows bloqueó una vez `testdata/vectors/mutations.json` en `datekeys-go` (algún proceso lo tenía mapeado). Se resolvió escribiéndolo vía fichero temporal y renombrado. Si vuelve, no es del código.
- Cuidado con PowerShell: una prueba mía con una ruta relativa vació `testdata/vectors/mutations.json` de `datekeys-ts` en vez del de Go. Se restauró con `git checkout` y su SHA-256 coincidía con `SOURCE.json`. Rutas absolutas siempre.
- La vista previa hay que reiniciarla tras cada build. Los secretos de prueba no se muestran en el chat. Los subagentes de revisión se lanzan con `model: "opus"`.
- **Gates:**
- `scripts/check.sh` en `datekeys-go`: los tests con `-race` de `capsule` tardan minutos. Si lo paras, mata también `fuzz.sh` y los procesos `*.test.exe`, que quedan huérfanos.
- `npm run verify` y `npm run testdata:check` en `datekeys-ts`.
- **El generador:**
- `go run ./internal/testkit/genfixtures -out testdata` no toca los fixtures que ya existen, ni sus registros.
- **No uses `-only mutations`:** regenera los 33 casos congelados del corpus. Para añadir mutaciones basta una ejecución normal.
- Los vectores congelados (`security_cms.json`, `locator.json`) se rehacen borrándolos.
- **Herramientas de esta máquina:**
- Los heredocs de Bash rompen las barras invertidas y los apóstrofos.
- La herramienta Write convierte `\uXXXX` en caracteres literales; en Go, escribe esos escapes con un script.
- `go test … | tail` esconde el código de salida: mira `$?` antes de hacer commit. Una vez se hizo commit con una prueba rota (`e597760`, arreglada en `0f51af7`).
- **Agentes:** el trabajo en paralelo en Go se hizo con agentes en clones propios del scratchpad y ficheros repartidos, integrados con `git fetch` y `cherry-pick`. Los subagentes, con `model: "opus"`.
---
@ -66,6 +151,8 @@ El 30-09 a mediodía seguían pendientes los cuatro: la carpeta se llama todaví
## 1. Repositorios
*Histórico, del 30-09: el estado actual está en «Retomar aquí».*
Los repos con remoto están en el Gitea privado `g.activething.com` (solo LAN, certificado autofirmado para `git.activething.com`; git funciona, `curl` necesita `-k`). **Ese servidor no es del autor**: no se proponen cambios en él. La integración continua es el gate local.