- La sesión se abre en `G:\bussines\datekeys`, la raíz, que es la que tiene la memoria y el `CLAUDE.md`.
- Comprueba que corre en Opus. Una sesión del 1-10 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.
- Comprueba cada repo con `git status` y `git log`: todo lo de abajo estaba subido al cerrar.
| `datekeys-go` | `v0.15` en `c49c67c`; `main` en `fe50885` | `spec-v0.15` en `fe50885`, y los de las versiones anteriores | Spec v0.15 aprobada, implementación de referencia, `testdata` compartido; `c49c67c` añade las palabras al azar |
| `App` (`datekeys-ts`) | `v0.10` y `main` en `7650418` | `v0.4.0` en `7650418`, `v0.3.0`, `v0.2.0`, `v0.1.0` | Librería TypeScript 0.4.0, de la spec 0.15, y páginas `/inspect` y `/create` |
| `datekeys-dart` | `v0.15` en `faa2c4c` | ninguno | Librería Dart completa, de la spec 0.15; las ramas `v0.11` a `v0.14` se quedan atrás |
- **Spec:** la v0.15 está aprobada desde el 7-10, con SHA-256 `45105e693be4187af4dd30f4d254402612587b6427c746f5d29f07a541c1e3f3`. Es la recuperación a largo plazo: el objeto release, los archivos y servicios de caché que guardan todas las rondas, el release en la mano en el paso 9.c (opción B: no se compara con el reloj) y el anexo de recuperación del §79. No cambia ningún formato de `.dkc` ni de `.dkk`. No hay ningún borrador abierto. Las versiones aprobadas y sus SHA-256 están en `datekeys-go/spec/README.md`.
- **El fichero `.dkr` se descartó** antes de aprobar (7-10). El autor no lo había aprobado conscientemente, y no tiene sentido: al crear la cápsula no hay release que guardar, y cuando llega la ronda la cápsula ya se abre. El objeto release no tiene extensión propia; sale de un archivo o de un servicio de caché. El §76 lo registra.
- **Las tres implementaciones** coinciden en todos los vectores compartidos de `datekeys-go/testdata` en `fe50885`, 142 ficheros. Gates el 7-10:
- Go: `scripts/check.sh` entero en `fe50885`, con el anexo de recuperación abriendo fixtures sin código de DateKeys, y `scripts/fuzz.sh 20s` en `fe50885` con sus 27 objetivos, sin fallos;
- TypeScript: `npm run verify` en `7650418`, con 8 106 pruebas;
- Dart: `tool/check.sh` en `faa2c4c`, con 2 211 pruebas en la VM y 694 en Node.
- **Palabras al azar (7-10, después de cerrar la v0.15):** `datekeys-go``c49c67c` añade `wordkey.Generate`, `List` y `CheckList`, y `datekeys encrypt -new-words FICHERO [-dic es] [-word-count 7]`. Es el SHOULD de §38.1 de ofrecer palabras generadas; no cambia ningún formato ni la derivación. `scripts/check.sh` pasa entero. La lista española, `wordkey/lists/es.txt` (7 776 palabras, SHA-256 `ff77b487…34fe`), es un **borrador sin revisar**, CC BY-SA 4.0, sacado de las frecuencias de subtítulos de FrequencyWords filtradas con el diccionario de LibreOffice; el método está en `wordkey/lists/README.md` y el script en [wordlists/build_es.py](wordlists/build_es.py).
- **La revisión externa:** el paquete de [revision_externa/](revision_externa/NOTA_PARA_EL_AUTOR.md) está al día con la v0.15. Su nota dice qué decidió el autor y qué falta: elegir revisor, alcance y presupuesto, el NDA, los bundles y el envío.
La recuperación a largo plazo quedó hecha con la v0.15 (7-10). **Para empezar mañana**, la recomendación de la sesión del 7-10: llevar las palabras al azar a TypeScript y a `/create` (Librerías, primer punto), y, si la web de Leipzig ha vuelto, rehacer la lista española con su corpus.
1.**La revisión externa.** El paquete está listo; lo que falta es del autor. Al recibir el informe, se abre la versión siguiente con sus hallazgos, el párrafo de idioma y precedencia del final del §1, las etiquetas del §76 que hoy llaman independientes a revisiones de IA, y el registro de la revisión (§75, punto 10). Todo eso lo aprobó el autor el 6-10; ver [revision_externa/precedence_and_language.md](revision_externa/precedence_and_language.md).
Con ellos, dos retoques editoriales que el texto no puede llevar tras su tag: los de K17 del paquete (la cabecera «prevista», el §1 con la Release API y la Release Cache, el punto y coma del §74), y el §79, que nombra solo `drand/kyber-bls12381` cuando `scripts/recovery` usa también las interfaces de `drand/kyber`.
2.**Un archivo o servicio de caché de releases** (§50). El protocolo ya lo admite y las librerías leen un archivo local, pero nadie aloja uno todavía. Es decisión del autor: dónde, quién lo mantiene y si DateKeys ofrece el suyo.
3.**Medir el área de 32 KiB y cerrar el perfil CMS** (§74; §75, punto 13), con firmas reales con certificado de varios países y sellos de autoridades reales. Necesita firmas del autor o permiso para pedir sellos a una autoridad pública.
4.**Lo que el §74 aún llama provisional:** los esquemas de bytes de la cabecera, el control y la `.dkk`, los límites de los campos y los vectores definitivos del perfil. Conviene congelarlo con el informe de la revisión delante.
5.**El registro de perfiles firmado** (§71), que no existe.
6.**Más adelante:** un tipo de acceso post-cuántico, y quizá una derivación más dura que PBKDF2 para la llave de palabras.
- **Las palabras al azar en el resto** (§38.1). Go ya las tiene (`c49c67c`). Falta:
-`Generate` en TypeScript y Dart, con la misma lista, su SHA-256 y `CheckList`; los dos copian la lista de `datekeys-go`, como el `testdata`;
- que `/create` ofrezca por defecto palabras generadas, con su aviso de que las elegidas son más débiles;
- la lista inglesa de la EFF (7 776 palabras, CC BY): descargarla necesita permiso del autor. Con ella, `-dic` pasa a `en` por defecto, como decidió el autor;
- la lista española definitiva: el autor espera a que vuelva la web de la Universidad de Leipzig (el 7-10 daba un error de servidor), cuyos corpus de unos 256 idiomas se descargan con CC BY. El script sirve cambiando la fuente de frecuencias. Su web bloquea a los agentes (Anubis): descarga el autor. Cada lista la revisa alguien que hable el idioma antes de fijar su hash;
- el servicio `words.datekeys.com`, cuando haya sitio propio: ver las decisiones.
- **la app no se fía de ninguna lista, tampoco de las de DateKeys** (el autor, 7-10: un empleado malicioso podría servir una lista con las mismas 6 palabras). `CheckList` ya rechaza menos de 2 048 palabras, repetidas tras normalizar, invisibles y cortas. Falta: un alfabeto por idioma (para el español, a–z con tildes, ü y ñ), porque una palabra con letras cirílicas que parecen latinas pasa y deja la cápsula sin abrir; la misma validación en TypeScript, Dart y la app; y que la app enseñe la fuerza calculada con la lista cargada. Quizá como regla del SDK en la versión siguiente del spec (§38.1). El riesgo de fondo es la app misma, que puede cambiar el generador: §59, builds reproducibles y releases firmadas.
- **La página web, cuando se publique** (§59): builds reproducibles con sus hashes, Subresource Integrity y un cliente sin conexión.
- **El localizador en las páginas:** las tres librerías lo tienen, pero `/create` no crea sobres e `/inspect` no descarga el resto.
- **Go no tiene ninguna release del módulo**; la primera, cuando haya un repo accesible desde fuera para `go get`. govulncheck avisa de GO-2026-6443 en grpc, que el código no alcanza: subir grpc cuando salga la 1.85.0.
- **Dart:** sin versión ni tag. Medir los tiempos en un móvil espera a la app.
- listas de 7 776 palabras por idioma y 7 palabras por defecto; BIP-39 (2 048) se le queda pequeña al autor;
- la app descarga la lista del idioma del usuario; la CLI las lleva dentro, inglés por defecto, y otra con `-dic es`, `-dic fr`;
- **las palabras se sortean siempre en el dispositivo y nunca viajan**: el servidor no las genera ni las ve, ni cifradas. El autor propuso un servicio que las mandara cifradas con la clave de DateKeys y aceptó esto en su lugar;
-`words.datekeys.com` solo servirá las listas públicas: ficheros estáticos con el hash en la URL, el SHA-256 fijado en la app o un índice firmado por DateKeys. La clave de DateKeys firma; no cifra nada.
- **La app será auditable** (7-10): código publicado de todo lo que toca las llaves, builds reproducibles, releases firmadas y una auditoría externa (§59). Con eso, las palabras generadas por la app son la opción por defecto; los dados (diceware, lista numerada del 11111 al 66666 y publicada con su hash) quedan como opción para quien desconfíe, y las palabras propias con su aviso. Límite: en iOS la App Store vuelve a firmar y cifrar, y no se puede comprobar el binario; en Android sí (F-Droid). Dónde se publica el código está por decidir: ni GitHub ni el Gitea.
- **`locator.Open` sigue leyendo como mucho 1 MiB** del localizador (6-10).
- **El cifrado tlock queda en `BigInt`, sin tiempo constante**, documentado en Dart y TypeScript («continúa», 6-10).
- **El reporte del posible fallo de dart2js** al equipo de Dart, solo con permiso del autor. Está documentado en el README de `datekeys-dart`.
- **Mostrar Q1 y Q10 de la revisión al equipo de drand** antes de pagar una revisión es decisión del autor, porque supone enseñar el proyecto fuera.
- **El diseño de las páginas:** nunca un fondo oscuro, nada del estilo de la landing, usar la skill `frontend-design` sobre la página real y no gastar en maquetas. Ver la memoria.
- **Subir al Gitea.** El nombre `g.activething.com` a veces resuelve a 89.46.247.16, que no responde. Entonces se sube a la IP de la red local, sin tocar el remoto:
y después `git -C <repo> update-ref refs/remotes/origin/<rama> <rama>`. Los remotos son `go/DateKeys`, `go/DateKeys-App`, `go/dateKeys-dart` y `go/datekeys-doc`. El servidor no es del autor: no se propone ningún cambio en él.
1. en Go, la cabecera del spec con «aprobado por su autor ese día» y nada más del texto;
2.`SpecVersion`;
3.`go run ./internal/testkit/genfixtures -out testdata`, y el campo `spec` a mano en los dos congelados, `security_cms.json` y `locator.json`;
4. el SHA-256 en `spec/README.md`, y los README, `SECURITY.md`, la trazabilidad, `testdata/README.md` y el CHANGELOG;
5.`scripts/check.sh`, con el árbol limpio tras el commit;
6. el tag anotado `spec-vX.Y` y `main` avanzado sin fusión (`git fetch . <rama>:main`);
7. en TypeScript y Dart, la versión del spec, `testdata` sincronizado con sus scripts, `mutation-texts.json` regenerado con Go en un módulo temporal (`G:\tmp\mutgo`), y el campo `spec` de los vectores propios que salen de Go.
Tras aprobar no se añade texto normativo sin enseñarlo: fue el fallo E1 de la v0.11.
- **Encargos a agentes:**
- con `model: "opus"`;
- en worktrees junto a los repos, para que `../datekeys-go` resuelva;
- nunca dos agentes en los mismos ficheros;
- solo ficheros nuevos, y los comunes en un último commit;
- la sesión revisa contra Go antes de integrar.
- **Herramientas de esta máquina:**
- los heredocs de Bash rompen las barras invertidas, `\n` incluido;
- la herramienta Write quita los espacios de final de línea (los saltos de Markdown del §77) y convierte `\uXXXX` en caracteres;
- para cambios con barras o espacios exactos, un script de Python escrito con Write que use `chr(92)`, o la herramienta Edit;
-`cd` en Bash mueve el directorio de la sesión: usa `( cd … )` o `git -C`.
- **Vista previa de la página:** la configuración `inspector-dev-app` de `.claude/launch.json` arranca `App`, mientras la carpeta no se renombre. No pares el servidor mientras el autor lo usa. `vite.config.ts` prepara las dependencias que se cargan bajo demanda (`optimizeDeps.include`), para que la primera apertura no recargue la página.
- **Fuzzing:** usa `FUZZ_PARALLEL=4`. Un «context deadline exceeded» sin entrada que falle es del motor de Go, no del código; se vuelve a pasar.
- **Disco:** C: está casi lleno con las cachés de Go y Dart; los temporales van en `G:\tmp`, y nunca se borra con comodines.
- [spec_v0.15/decisiones.md](spec_v0.15/decisiones.md): las decisiones de la última versión, y [diseno_recuperacion.md](diseno_recuperacion.md), su diseño.