18 KiB
Handoff DateKeys
Estado al 7 de octubre de 2026 por la tarde. Lo que pasó hasta aquí, sesión a sesión, está en HANDOFF_historial.md.
Sirve para retomar sin contexto previo, sea una persona o una sesión de Claude.
Antes de empezar:
- La sesión se abre en
G:\bussines\datekeys, la raíz, que es la que tiene la memoria y elCLAUDE.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-Byde los commits dicen qué modelo escribió cada uno. - Comprueba cada repo con
git statusygit log: todo lo de abajo estaba subido al cerrar.
Estado
| Repo | Rama y commit | Tags | Qué es |
|---|---|---|---|
datekeys-go |
v0.15 en e671032; 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, 27a75ee el alfabeto de cada lista y la fuerza de las palabras, 96d8992 arregla TestGenerate y e671032 añade la lista inglesa de la EFF |
App (datekeys-ts) |
v0.10 en 13df99b; main en 7650418 |
v0.4.0 en 7650418, v0.3.0, v0.2.0, v0.1.0 |
Librería TypeScript 0.5.0-dev, de la spec 0.15, y páginas /inspect y /create, con las palabras al azar; la última publicada es la 0.4.0 |
datekeys-dart |
v0.15 en bf0f3d3 |
ninguno | Librería Dart completa, de la spec 0.15, con las palabras al azar; las ramas v0.11 a v0.14 se quedan atrás |
docs |
main |
— | Este repo |
web |
main en f2b8a38 |
— | Landing de datekeys.com, sin remoto |
- 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.dkcni de.dkk. No hay ningún borrador abierto. Las versiones aprobadas y sus SHA-256 están endatekeys-go/spec/README.md. - El fichero
.dkrse 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/testdataenfe50885, 142 ficheros, los mismos que ene671032, de donde TypeScript y Dart copian hoytestdataywordlists. Gates el 7-10:- Go:
scripts/check.shentero enfe50885, con el anexo de recuperación abriendo fixtures sin código de DateKeys, yscripts/fuzz.sh 20senfe50885con sus 27 objetivos, sin fallos;scripts/check.shentero otra vez en27a75ee,96d8992ye671032; - TypeScript:
npm run verifyen13df99b, con 8 120 pruebas; - Dart:
tool/check.shenbf0f3d3, con 2 231 pruebas en la VM y 705 en Node.
- Go:
- Palabras al azar (7-10, después de cerrar la v0.15): es el SHOULD de §38.1 de ofrecer palabras generadas; no cambia ningún formato ni la derivación.
- Go:
c49c67cañadewordkey.Generate,ListyCheckList, ydatekeys encrypt -new-words FICHERO [-dic es] [-word-count 7].27a75eehace queCheckList(lang, words)compruebe cada palabra contra el alfabeto de su idioma, que da el código y no la lista (paraes, de laaa laz,á,é,í,ó,ú,üyñ, en minúscula y NFC): una letra cirílica que parece latina, una mayúscula, una cifra o el retorno de carro de un fichero CRLF dejarían la cápsula sin abrir. También añadeBits, la fuerza de lo sorteado, queencryptmuestra (90 bits para 7 de 7 776).scripts/check.shpasa entero en los dos. - TypeScript (
0.5.0-dev, de012cd74a4057607):scripts/sync-testdata.mjscopia del mismo commit de Gowordkey/listsenwordlists/, con suSOURCE.json(testdataywordlistsen27a75ee, cuyotestdataes el del tag).wordlist.tshace lo de Go, con sus textos:readWordListsolo acepta una lista con el SHA-256 fijado para su idioma,checkWordList,generateWordsywordBits./createofrece palabras al azar por defecto tras una casilla, con su fuerza y «Otras palabras», y deja escribir las propias con el aviso de que son más débiles;licenses.txtlleva la licencia de la lista.npm run verifypasa con 8 119 pruebas, y el flujo se comprobó en el navegador sobre el build de producción. - En
/createapareció y se corrigió un fallo de la 0.4.0 (4057607): el efecto que comprueba las rutas se relanzaba sin fin (effect_update_depth_exceeded) en cuanto había un fichero, un comentario o un autor. wordBitsde TypeScript usaMath.log2, que puede diferir delmath.Log2de Go en el último bit; la página muestra los bits truncados, como la CLI, así que no se nota.- Dart (
a770d4dafcc7780, de un agente Opus en un worktree, revisado contra Go):tool/sync_testdata.dartcopia tambiénwordlists/, ylib/src/wordlist.darthace lo mismo que Go, exportado desdelib/datekeys.dart. Sus vectores (test/vectors/wordlist_vectors.json) los genera Go contool/wordlist_go_vectors.go:List,CheckListen 83 listas, el veredicto de cada punto de código de los planos 0, 1 y 14,Generateen 51 casos con los mismos bytes que Go, yBitsbit a bit (porta elmath.Log2de Go). - El agente de Dart vio que
TestGeneratede Go no probaba nada: su semilla solo daba dos índices, las dos llamadas acababan enEOFy el test comparaba dos resultados vacíos. Está arreglado en96d8992. - La lista inglesa (7-10 por la tarde, con permiso del autor):
wordkey/lists/en.txtes la lista grande de la EFF (Joseph Bonneau, 2016), 7 776 palabras, CC BY 4.0 según la política de copyright de eff.org, en su orden y sin los números de los dados, así que la posición de cada palabra sigue dando su número.-dicla toma por defecto, como decidió el autor. El alfabeto deenes de laaa lazy el guion ASCII de sus cuatro palabras compuestas (drop-down,felt-tip,t-shirtyyo-yo), para no quitar ninguna ni romper su numeración. Goe671032, TypeScript13df99b(la página sigue ofreciendo solo la española, ycheck-build.mjsexige que publique solo esa) y Dartbf0f3d3, con sus vectores regenerados con Go. - La lista española,
wordkey/lists/es.txt(7 776 palabras, SHA-256ff77b487…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á enwordkey/lists/README.mdy el script en wordlists/build_es.py. Cumple el alfabeto tal cual.
- Go:
- La revisión externa: el paquete de revision_externa/ 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.
Qué queda
La recuperación a largo plazo quedó hecha con la v0.15, y las palabras al azar en las tres librerías y en /create (7-10). Para empezar mañana, lo que depende del autor en ellas: si se hacen los dados como propone «Librerías y clientes», y la revisión de la lista española por alguien que hable español, o rehacerla con el corpus de Leipzig cuando su web vuelva (el 7-10 por la tarde seguía caída). Sin eso, lo siguiente es el segundo punto de «Librerías y clientes»: las recomendaciones de la v0.14 y la v0.15 al SDK oficial.
Protocolo
- 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.
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-bls12381cuandoscripts/recoveryusa también las interfaces dedrand/kyber. - 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.
- 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.
- 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. - El registro de perfiles firmado (§71), que no existe.
- 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.
Librerías y clientes
- Las palabras al azar (§38.1) están en Go, TypeScript,
/createy Dart, con el SHA-256 fijado de cada lista, el alfabeto de su idioma y la fuerza calculada con la lista cargada (ver «Estado»). Ninguna lista se da por buena, tampoco las de DateKeys (el autor, 7-10: un empleado malicioso podría servir una lista con las mismas 6 palabras). Falta:- 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. En el borrador hay nombres propios, préstamos y palabras malsonantes, como «claudia», «green», «sport» o «cojonudo»: que los mire quien la revise, con
descartes.txtdelante; - los dados de quien desconfíe (decisión del 7-10): cinco tiradas, de 11111 a 66666, son una posición de la lista ordenada, porque 7 776 = 6⁵; con la lista inglesa, el mismo número que publica la EFF. No están en ninguna librería ni en
/create. La propuesta del 7-10, pendiente del autor: en las tres librerías,DiceWord(cinco cifras del 1 al 6 a la palabra, solo con listas de 7 776) y su inversa; la lista numerada para imprimir, con su SHA-256, de la CLI y de la página; en/create, una tercera opción «Con dados» que convierte los números en palabras a medida que se escriben y pide tirar otra vez si una palabra se repite; y en la CLI,-dice. Los dados protegen de un generador trucado, no de una app que se quede con las palabras: eso solo lo cubre una app auditable (§59); - el servicio
words.datekeys.com, cuando haya sitio propio: ver las decisiones; - quizá el alfabeto por idioma 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 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. En el borrador hay nombres propios, préstamos y palabras malsonantes, como «claudia», «green», «sport» o «cojonudo»: que los mire quien la revise, con
- Las recomendaciones de la v0.14 y la v0.15 al SDK oficial, que no aplican ni
/createni la CLI de Go:- recomendar
time_and_keypara horizontes largos (§7.6); - avisar del estado de un perfil (§71);
- explicar al crear cómo se abrirá la cápsula dentro de veinte años: el anexo de recuperación (§79) y los archivos de releases (§50).
- recomendar
- 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
/createno crea sobres e/inspectno 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.
Espacio de trabajo
- Del autor: renombrar la carpeta
Appadatekeys-tsy borrarenquiry.phpde la raíz, pendientes desde el 29-09. websigue sin remoto.
Decisiones del autor que siguen vigentes
- La app Flutter está archivada «para un futuro» (6-10). No se empieza sin que lo pida.
- La revisión externa (6-10):
- primero, buscar un revisor que lea español; si no lo hay, traducir solo el núcleo normativo;
- dos niveles de alcance, con presupuesto cerrado por nivel;
- código entero en bundles de git cifrados con
age; - un NDA mutuo;
- la versión siguiente, después del informe. La v0.15 se adelantó a petición del autor (7-10).
- Las palabras al azar (7-10):
- 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.comsolo 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.
- Sin fichero
.dkr(7-10): el objeto release no se guarda junto a la cápsula ni tiene extensión propia. locator.Opensigue 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-designsobre la página real y no gastar en maquetas. Ver la memoria.
Para trabajar
-
Subir al Gitea. El nombre
g.activething.coma veces resuelve a 89.46.247.16, que no responde. Entonces se sube a la IP de la red local, sin tocar el remoto:git -C <repo> push https://192.168.18.112/go/<repo-remoto>.git <rama>y después
git -C <repo> update-ref refs/remotes/origin/<rama> <rama>. Los remotos songo/DateKeys,go/DateKeys-App,go/dateKeys-dartygo/datekeys-doc. El servidor no es del autor: no se propone ningún cambio en él. -
Cerrar una versión del spec, como la v0.12 a la v0.15:
- en Go, la cabecera del spec con «aprobado por su autor ese día» y nada más del texto;
SpecVersion;go run ./internal/testkit/genfixtures -out testdata, y el campospeca mano en los dos congelados,security_cms.jsonylocator.json;- el SHA-256 en
spec/README.md, y los README,SECURITY.md, la trazabilidad,testdata/README.mdy el CHANGELOG; scripts/check.sh, con el árbol limpio tras el commit;- el tag anotado
spec-vX.Yymainavanzado sin fusión (git fetch . <rama>:main); - en TypeScript y Dart, la versión del spec,
testdatasincronizado con sus scripts,mutation-texts.jsonregenerado con Go en un módulo temporal (G:\tmp\mutgo), y el campospecde 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-goresuelva; - 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.
- con
-
Herramientas de esta máquina:
- los heredocs de Bash rompen las barras invertidas,
\nincluido; - la herramienta Write quita los espacios de final de línea (los saltos de Markdown del §77) y convierte
\uXXXXen caracteres; - para cambios con barras o espacios exactos, un script de Python escrito con Write que use
chr(92), o la herramienta Edit; - en Windows,
write_textde Python escribe CRLF: abre connewline=''o escribe bytes, ogofmty los hashes fallan; cden Bash mueve el directorio de la sesión: usa( cd … )ogit -C.
- los heredocs de Bash rompen las barras invertidas,
-
Vista previa de la página: la configuración
inspector-dev-appde.claude/launch.jsonarrancaApp, mientras la carpeta no se renombre, einspector-preview-appsirve su build de producción (npm run buildantes, y reiniciarla tras cada build: si no, los chunks nuevos dan 404 y la página no se hidrata). No pares el servidor mientras el autor lo usa.vite.config.tsprepara 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.
Documentos
El README los lista. Para retomar, lo principal es:
- revision_externa/: el paquete y su nota;
- REVISION_completitud_v0.13.md: qué falta antes de la v1.0;
- spec_v0.15/decisiones.md: las decisiones de la última versión, y diseno_recuperacion.md, su diseño.