You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

53 KiB

Handoff DateKeys, 26 de septiembre de 2026 (actualizado al cerrar la sesión del 5 de octubre: Go y TypeScript al día con el borrador v0.12, y las etapas 0 y 1 de Dart)

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 5 de octubre)

Qué pasó. Una sesión en Opus, abierta otra vez en App, hizo los puntos 2, 3 y 4 de la lista del 2-10: lo que faltaba de Go, la segunda parte del TypeScript y las etapas 0 y 1 de Dart. El autor decidió además una ampliación del borrador v0.12. El trabajo grande se repartió entre agentes Opus en worktrees y repos aparte, y cada resultado se revisó e integró en la sesión.

datekeys-go, rama v0.12, subida:

  • da9fd2c: arreglo editorial del borrador. Faltaba una línea en blanco antes de cinco ---, y dos párrafos, el final del §70 y el del §72, se veían como títulos. La v0.11 etiquetada tiene el mismo fallo y no se toca.

  • ea5c6eb: locator.json con los casos del §64 de la v0.11 y la v0.12:

    • 217 direcciones: la primera y la última de cada bloque IPv4, con sus vecinas públicas; los bloques IPv6; los nombres locales; los caracteres fuera de RFC 3986; los segmentos ..; y los CID que no decodifican;
    • mixed: un localizador con una dirección http y otra de NAT64, que se rechazan, y una tercera que se usa;
    • rest_cases, extension_cases, con el localizador de otra ronda, y plaintext_cases, con el caso del cambio 7;
    • las bases de relleno 3837, 4070, 4094 y 4095 y las del múltiplo siguiente: la spec pide ocho, y la lista del 2-10 daba seis.

    El generador pasa a internal/testkit/genfixtures/locatorvectors.go y comprueba cada caso contra Go.

  • e22d358: testdata/README.md al día, y sin marcas pending en docs/traceability.md ni en el CHANGELOG. El README decía que el release de la ronda 1000 estaba en quicknet_rounds.json, y no estaba.

  • 601e6d2, con la decisión del autor del 5-10 («sí, aplícalo así»): el §44.1 escribe lo que Go ya rechazaba y el texto no decía, y el cambio 6 del §76 y el §64 lo recogen:

    • segmentos de 1 a 63 caracteres, sin guion en los extremos;
    • el esquema en minúsculas, y 0x y los nombres locales sin distinguir mayúsculas;
    • IPv4 sin ceros a la izquierda y CID en su forma canónica;
    • el puerto sin ceros a la izquierda: Go aceptaba :0443 y :00443, y checkPort ahora los rechaza.

    locator.json pasa a 247 direcciones.

  • Verificación: scripts/check.sh 60s completo sobre e22d358, y sobre 601e6d2 check.sh sin fuzzing y fuzz.sh 60s, los 25 objetivos: todo limpio. Cobertura de capsule, 92,2 %. govulncheck da los dos avisos de siempre, sin llamada alcanzable.

App (datekeys-ts), rama v0.10, subida (fc5fb24..289fe71):

  • 997f331: la regla de los codificadores del §72 (checkWrite en extension.ts, con NOTE_ID y CAPSULE_ID), que aplican el escritor de cápsulas y el de .dkk con los textos de Go; checkNoteData y unusableNote. Comprobado también contra el testdata de spec-v0.11.

  • 95329ee, el borrador v0.12, en un solo commit porque nada pasaba por separado:

    • testdata en 601e6d2; SPEC_VERSION sigue en 0.11;
    • el lector de certificados campo a campo, los OID por bytes, los SET OF con repetidos y los casos límite: T2, T6, T7, T8 y lo de TypeScript de E7, E8 y E9;
    • los textos de los veredictos de la v0.12: E2, E3 y E4;
    • security.json y los 135 casos de security_cms.json, comparados campo a campo, con sus líneas;
    • los textos de las 218 mutaciones y los vectores IBE de los fixtures nuevos;
    • note.json, y la nota pública en inspect, que la lee bajo demanda.

    El port del CMS lo hizo un agente: un diferencial suyo de 63 623 áreas no dio ninguna diferencia con Go, y el código anterior difería en 13 296 de 42 986.

  • 289fe71: README y CHANGELOG.

  • Verificación: npm run verify (7 759 pruebas, cobertura y build con sus guardas) y testdata:check contra Go.

datekeys-dart, rama v0.11, solo local (no tiene remoto):

  • 5aa5eed, etapa 0:

    • el paquete datekeys, Dart 3.13, sin publicar;
    • testdata en spec-v0.11, 124 ficheros, con el mismo SOURCE.json que escribe el TypeScript;
    • tool/sync_testdata.dart, pruebas de integridad y de versión, y tool/check.sh como gate;
    • licencia Apache-2.0;
    • dependencias: crypto en ejecución y test en desarrollo, aprobado por el autor el 5-10.
  • da63bc3 a 10b0895, etapa 1, también de un agente:

    • errores del §69;
    • bytes: UTF-8 estricto propio, porque el Utf8Decoder de Dart quita un U+FEFF inicial; y el %q de Go con su tabla IsPrint;
    • el códec CBOR de codec.go;
    • el DER de la v0.12.

    Los enteros son exactos en la VM y en la web: un int hasta 2^53 − 1 y un BigInt por encima. Hay 169 pruebas en la VM y 56 también en Node, y una comparación con Go de 263 611 casos no dio ninguna diferencia.

Siguiente, en orden

  1. El autor aprueba el borrador v0.12: §76, cambios 1 a 9, con el 6 ampliado el 5-10. Sigue abierto si se mide antes el área de 32 KiB con firmas reales. 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. Antes, dos decisiones suyas:
    • «Con texto» en el §29.7. El texto pide givenName y surname «si tiene uno de cada», y el organizationName del emisor «si no tiene» commonName. Go exige además que tengan texto, y trata un commonName sin texto o repetido como si faltara; el TypeScript sigue a Go. Recomendado: escribirlo en el borrador.
    • dart test -p node en el gate de Dart. Comprobaría en cada commit que los enteros son exactos en la web; añade unos 12 s, y Node, que ya hace falta para el TypeScript. Recomendado: sí.
  2. Dart, etapa 2: las primitivas, según PLAN_dart.md.
  3. TypeScript, sin urgencia: el localizador, que aún no está portado; que la página muestre la nota pública, que ya lee inspect; y lo pendiente del §2.5.

Observaciones del 5-10, sin decisión:

  • El error de una nota pública con un tabulador dice «in the declared author», porque la nota usa las reglas del autor declarado. Está en note.json y el TypeScript lo copia: cambiarlo exige tocar los dos lados.
  • testdata no tiene vectores compartidos de la llave de palabras. El §64 de la v0.11 los pide, y solo están en las pruebas de Go (wordkey.TestKeyVector). TypeScript y Dart los van a necesitar.
  • A G: le quedan 1,5 GB libres.
  • Flutter está instalado en C:\dev\flutter, y su Dart 3.13.0 es el dart del PATH.
  • La carpeta sigue llamándose App, y enquiry.php sigue en la raíz (§0).

Para trabajar: lo del apartado del 2-10, y además:

  • Un worktree en el scratchpad permite trabajar mientras check.sh corre en la copia principal.
  • Dos fuzzings a la vez no deben solaparse, porque comparten la caché de fuzzing de GOCACHE.

Estado al cerrar la sesión del 2 de octubre (histórico: lo actual está arriba)

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.

  • 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. 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, 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 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".

0. Reorganización del espacio de trabajo (29-09, mediodía)

G:\bussines\datekeys se reorganizó el 29-09. El mapa de carpetas y las reglas del proyecto están ahora en el README de este repo. Los cambios:

  • Documentos: los del proyecto, este incluido, pasaron de App/docs a este repo, docs, que es privado y no tiene remoto. Su primer commit es 6e8d6c6. Los papeles de trabajo de la v0.9, que solo estaban en una carpeta temporal, están en spec_v0.9/.
  • App: quitó docs/, y el paquete, el README y el aviso de licencias del sitio pasan a llamarse datekeys-ts (5ee8813, subido). npm run verify sigue en verde, con 2 611 tests.
  • Archivo y logos:
    • AppOld pasó a archive/prototype, sin cambios;
    • los borradores v0.1 a v0.8.1, que estaban en Descargas, pasaron a archive/spec-drafts, con los hashes comprobados;
    • los logos pasaron a brand/.
  • Claude:
    • la memoria de Claude es ahora la de la raíz. La de App queda congelada, con una nota que remite a la nueva;
    • en la raíz hay un CLAUDE.md, que carga el README, y un .claude/launch.json para las vistas previas.
  • Nombres: en las secciones siguientes, App es el repo que ahora se llama datekeys-ts. Su remoto sigue siendo go/DateKeys-App.

Pendiente del autor, antes de seguir:

  1. Cerrar la sesión abierta en App y renombrar la carpeta a datekeys-ts. Windows no deja renombrar una carpeta en uso.
  2. Abrir las sesiones siguientes en G:\bussines\datekeys. La primera comprueba npm run verify y npm run testdata:check en datekeys-ts.
  3. Borrar G:\bussines\datekeys\enquiry.php, que es una copia idéntica de web/static/api/enquiry.php. Claude no tiene permiso para borrarlo.
  4. docs y web solo existen en esta máquina. Para tener una copia fuera de ella, hay que darles un remoto.

El 30-09 a mediodía seguían pendientes los cuatro: la carpeta se llama todavía App, y la sesión de ese día también se abrió en ella.


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.

Repo Rama Commit Estado
datekeys-go (go/DateKeys) main cc35d2c Spec v0.10, entrega 1 del formato 3, aprobada por el autor el 30-09 y cerrada con el tag anotado spec-v0.10 en cc35d2c; SHA-256 del spec 7f26419a444aa3e89a3aa8afbbba9d952af69e048aee1e93cd70732c2d1d99d1. Implementa el formato 3: lo escribe y lee los formatos 1 a 3, con SpecVersion 0.10. scripts/check.sh 60s limpio. La v0.9 sigue en su tag, spec-v0.9 (7e2d83c), y la v0.8.2 en el suyo, spec-v0.8.2 (9ac9cd9).
v0.8.2 9ac9cd9 El commit del tag; ya no hace falta.
v0.9 7e2d83c El commit del tag spec-v0.9; ya no hace falta.
v0.10 cc35d2c Igual que main; ya no hace falta.
datekeys-ts, antes App (go/DateKeys-App) main da26862 Desde 5ee8813, sin docs/ y con el paquete datekeys-ts (§0). Versión 0.2.0-dev desde 8c08c97, con v0.1.0 cerrada en d577283; implementa el spec 0.9 desde 0118890 (VERSION y SPEC_VERSION, también en el pie de la página). Escribe el formato 2 y tiene la página /create (fase 3, §2.5). Librería TypeScript con la inspección (pasos 1 a 8) y la apertura (pasos 9 a 18) de los formatos 1 y 2, en memoria o desde un Blob hacia un stream de salida, como un fichero OPFS. Página /inspect con la acción "abrir", que muestra el formato y avisa del 1. testdata sincronizado a 7e2d83c (spec-v0.9). Fase 2 completa (pasos 2 a 8), incluidos el cifrado tlock y la interoperabilidad de TypeScript a Go. Los 125 casos del corpus pasan por open con el código, el paso y el texto de Go. En 0118890, 5 425 tests, ninguno saltado; la fase 3 añadió los suyos, con npm run verify en verde en cada paso (§2.5).
docs (solo local) main Este repo: handoff, planes, revisiones y reglas.
web (solo local) main f2b8a38 Landing de datekeys.com.
archive/prototype, antes AppOld (solo local) master 4d2b0a1 Prototipo antiguo. No se toca.

Verificación ya hecha sobre datekeys-go:

  • fuzzing de 30 min en cada uno de los 15 objetivos sobre 3820066, limpio;
  • diferencial Go/TypeScript de 407 196 entradas contra f6f2e9f, con cero diferencias, textos de error incluidos;
  • scripts/check.sh 60s sobre 9ac9cd9, el commit del tag, limpio (28-09), y sobre el estado de 6fa2b54, con tres objetivos de fuzzing nuevos del formato 3, limpio (30-09);
  • govulncheck no encuentra nada alcanzable. Avisa, sin llamada alcanzable, de dos problemas:
    • GO-2026-6443, en google.golang.org/grpc 1.84.0, arreglado solo en una versión -dev. Hay que subir grpc cuando salga la 1.85.0.
    • GO-2026-5932, en golang.org/x/crypto/openpgp, sin arreglo. No lo importamos.

2. Qué queda, en orden

2.1 Hecho el 28-09: cierre de la v0.8.2

  • Los 9 retoques de la 2.ª revisión están en 9ac9cd9, un solo commit sobre c57ed48 que absorbe el WIP 69a3342. La rama WIP está borrada.
  • §76 los recoge como correcciones 4 a 6:
    • un encoder MUST NOT escribir una extensión fuera de su registro;
    • §17 y §51 dan los códigos del paso 10 solo para un release suministrado directamente;
    • en el paso 9, cualquier fallo de la fuente es ERR_RELEASE_UNAVAILABLE y ningún otro código.
  • La regla del encoder no se comprueba en la librería: capsule.Encrypt y accesskey.Encode no reciben Registry, y la aplica la aplicación. Está documentado en extension.Placement.
  • El autor aprobó el texto el 28-09. El spec lleva esa fecha, y el SHA-256 de sus bytes LF, 5cfa3203…, está en spec/README.md y en el mensaje del tag.
  • main avanzó por fast-forward hasta 9ac9cd9 y lleva el tag spec-v0.8.2. Los dos están subidos.
  • App sincronizó testdata con 9ac9cd9 en 71ab8fb. Solo cambia testdata/README.md.

Las reglas que siguen valiendo (testdata, textos de error y versiones cerradas del spec) están en el README.

2.2 Fase 2: abrir cápsulas en el navegador

Plan: docs/PLAN_fase2_ibe_noble2.md v2, con las decisiones confirmadas por el autor. Los pasos 2 a 8 de su sección 10:

  • hecho el 28-09 (74e1215): age-encryption 0.3.1 y noble 2.4.0 como dependencias de ejecución, con sus guardas en src/lib/dependencies.test.ts y check-build.mjs. El README de App recoge el coste medido en el bundle, 73 KB con gzip para todo, y npm audit;
  • hecho el 28-09 (35be27c): ibe.ts sobre noble 2, con vectores de Go en src/lib/dkc/testing/ibe-vectors.json (scripts/ibe-go-vectors.go) y cobertura del 100 % fijada como umbral. Los argumentos del stanza y su paso al Stanza de age-encryption, que guarda el tipo en args[0], van al paso 7;
  • hecho el 28-09 (076f3db): release.ts, con verifyRelease en el orden y con los textos de provider.Verify, ReleaseSource y suppliedRelease. Solo verifica el scheme de Quicknet: otro da ERR_UNKNOWN_PROFILE. Reproduce los 7 casos del corpus que fallan en el paso 10;
  • hecho el 28-09 (97827ae), paso 5a: open.ts, los pasos 9 a 18 con el texto en claro en memoria. Las identidades estrictas de agewrap se apoyan en x25519.ts, que abre los stanzas de uno en uno. Usa @noble/ciphers 2.4.0, dependencia directa aprobada ese día: es la copia que ya usa age-encryption. Las identidades AGE-SECRET-KEY-1… se leen con bech32.ts. index.ts no reexporta aún la apertura, que metería noble en /inspect;
  • hecho el 28-09 (a89bee5), paso 5b. open acepta un Blob del que solo lee el prefijo de los pasos 1 a 8 (prefix.ts, movido de la página a la librería), calcula el capsule_digest en streaming (digest.ts) y descifra PAYLOAD_AGE en streaming. La salida puede ser un WritableStream, que se cierra tras el paso 18 y se aborta ante cualquier fallo. Comprobado en el navegador con OPFS real: un fallo de STREAM deja intacto el fichero;
  • el paso 6 está cubierto: la enmienda de canonicidad entró en la v0.8.2;
  • hecho el 28-09 (66970cf), paso 7: encryptOnG2RFC9380 y timeRecipient. Con sigma fijo, el cifrado reproduce byte a byte los vectores de Go. Go abrió los cuerpos IBE y los ficheros age que cifró esta librería, con tlock.TimeUnlock y con agewrap.NewTimeIdentity. Todo está en src/lib/dkc/testing/tlock-vectors.json;
  • hecho el 28 y 29-09 (48d6704), paso 8: la acción "abrir" en /inspect, cargada bajo demanda, con la política aprobada por el autor el 28-09 tras revisar lo que dice el protocolo:
    • el release lo pega quien abre, o sale del registro del fixture, y la página nunca lo pide a la red;
    • el texto en claro de un fichero propio va a un fichero temporal de OPFS (§56), que se borra;
    • los avisos de licencia se publican en licenses.txt. Una revisión adversarial confirmó 15 hallazgos, todos corregidos. Los detalles y las comprobaciones en el navegador están en la fila 8 del plan.

La lectura del protocolo del 28-09 deja dos SHOULD para más adelante: §48 (varios relays) y §49 (obtener el release directamente del proveedor). Los cubrirá una fuente drand opcional del SDK, nunca activa por defecto en la página (sección 12 del plan).

El vector de GT (vectors/tlock_ibe.json) ya está cubierto en App. El paso 9 de open.ts debe seguir la corrección 6: cualquier fallo de una fuente es ERR_RELEASE_UNAVAILABLE y ningún otro código.

2.5 Sesiones del 29-09: v0.9 del spec y formato 2 en Go (retomar aquí)

Estado al parar (30-09 por la noche). Retomar por el formato 3, al final de esta sección: la spec v0.10, entrega 1 del formato 3, está aprobada, implementada en la referencia Go y cerrada con el tag spec-v0.10, todo subido en main de datekeys-go (cc35d2c). Lo siguiente es el formato 3 en datekeys-ts.

Estado al cerrar la fase 3 (29-09 por la noche):

  • Pasos 1 a 5 hechos. El spec v0.9 está cerrado con el tag spec-v0.9 (7e2d83c, en main de datekeys-go), y las dos implementaciones leen el formato 2: Go desde f24a280, que también lo escribe, y TypeScript desde 0118890.
  • Paso 6 hecho: la fase 3 está completa en datekeys-ts (pasos 0 a 7 del plan, hasta 3a9d2b1, subido). La librería escribe el formato 2, Go abre lo que escribe y la página /create cifra en el navegador. La versión 0.2.0 sigue sin publicar: cerrarla es decisión del autor (§2.3). Después, a petición del autor, /inspect muestra el contenido al abrir, debajo del veredicto, y nombra la descarga por su tipo. Las páginas explican las claves de age, y la vista previa sirve las páginas sin caché (da2000a, da26862, subidos).
  • Las 22 correcciones del repaso final (spec_v0.9/review.md) se aplicaron en 4a025d1, más cuatro sitios que repetían los mismos problemas: las reglas 1 y 4 del §62.1 y los cambios 4 y 10 del §76. Los números de la corrección 1 se recalcularon con un Padmé en BigInt.
  • La corrección 2 la decidió el autor el 29-09: se suaviza el §56.
    • El lector MUST NOT presentar el contenido como válido antes de que termine el paso 17.
    • Un lector en streaming MUST NOT escribir el relleno y MUST señalar el error para que se descarte lo escrito.
    • Así siguen valiendo Open(dst) de Go y la salida en streaming de TypeScript.
  • En este repo están PLAN_fase3_escritura.md, el plan del writer TypeScript, y REVISION_completitud_protocolo.md, la revisión del protocolo. El plan está en su v3: el autor confirmó sus 17 decisiones el 29-09.

Aprobación del 29-09. El autor aprobó el texto de la v0.9 con las respuestas recomendadas a las preguntas abiertas:

  1. L es un bstr de 8 bytes, no un uint.
  2. El lector SHOULD informar del formato.
  3. Se mantienen el objetivo 8 de §4 y el no objetivo nuevo de §5.
  4. Solo un generador de vectores de prueba MAY escribir el formato 1 (§62.1, regla 1, y §70).
  5. Los fixtures nuevos llevan el prefijo format2_.
  6. Se mantiene D1: los señuelos son identidades generadas cuya clave privada se descarta en el acto.
  7. Rechazar puntos del twist sigue siendo MAY.
  8. Se confirman las reglas añadidas: L_MAX = 2⁵³ − 2⁴⁶, el orden uniforme de los stanzas, que el SDK SHOULD mostrar el instante efectivo de la ronda y que el lector MAY comprobar la longitud de PAYLOAD_AGE.

Decisiones del autor del 29-09 para la v0.9:

  • D1: time_and_key lleva siempre exactamente 16 stanzas X25519 en INNER_ACCESS_AGE. Los que sobran son señuelos, y todos van en orden aleatorio. Como mucho hay 16 credenciales, contando la .dkk.
  • D2: el contenido se rellena siempre. El código 1 redondea al siguiente múltiplo de 256, con un mínimo de 256. El código 2, "reforzado", es max(bloque256, Padmé) y es el de por defecto. No hay opción sin relleno.
  • D3: la longitud real y el código van en CONTROL_CBOR versión 2 (claves 6 y 7). El lector entrega solo L bytes y comprueba que el relleno sea todo ceros y que siga la regla.
  • D4: el formato pasa a 2 (VERSION 2 del PRELUDE), así que un lector v0.8.2 lo rechaza en el paso 2, sin red. Un lector v0.9 sigue abriendo el formato 1.
  • D5: access_policy sigue visible.
  • D6: nueva sección de privacidad, §55.2.
  • D7: reglas normativas del escritor, §62.1:
    • I_PAYLOAD sale de un CSPRNG y no se reutiliza;
    • límites;
    • la fecha pedida tiene que ser futura;
    • el escritor se autocomprueba;
    • rechaza claves X25519 no canónicas o de orden bajo.

Hecho en Go, paso 3 (f24a280):

  • Formato 2 en la librería:
    • capsule: Format, Padding, PaddedLength, PayloadAgeLength; EncodeControl y DecodeControl reciben el formato; Open aplica los pasos 12 a 18 del formato 2.
    • agewrap: AccessSlots y CheckX25519Recipient.
  • Escritura:
    • Encrypt escribe solo el formato 2.
    • EncryptOptions.Length es obligatorio; Padding es reforzado por defecto.
    • Acepta de 1 a 16 credenciales, con señuelos, orden aleatorio y autocomprobaciones.
    • La CLI mide la entrada, acepta -padding e informa del formato.
  • testdata:
    • 7 fixtures format2_*, dos de ellos con .dkk;
    • vectors/padding.json;
    • los vectores CBOR del formato 2;
    • un corpus de mutaciones de 125 casos: 88 del §64 (33 en cada formato y los 22 de la tercera lista) y 37 más;
    • un diferencial de 4 380 casos, en el que los 1 825 anteriores no cambian.
    • Los fixtures del formato 1 se conservan byte a byte.
  • Mutaciones sin aleatoriedad: se vuelven a sellar los fixtures con sus claves y nonces conocidos (internal/testkit/reseal.go), así que se regeneran byte a byte.
  • scripts/check.sh 60s limpio:
    • cobertura: codec 100 %, capsule 94,2 %, accesskey 97,2 %, datekey 94,6 %, agewrap 92,8 %;
    • govulncheck, con los mismos dos avisos de §1;
    • 60 s de fuzzing en cada uno de los 15 objetivos.
  • Documentación: la copia del spec del repo pierde las marcas "(por implementar)". README, README.es, CHANGELOG, docs/traceability.md y testdata/README.md están al día.

Orden de trabajo:

  1. Aplicar y verificar las 22 correcciones. Hecho el 29-09 (4a025d1).

  2. El autor aprueba el texto de la v0.9. Hecho el 29-09.

  3. La referencia Go implementa el formato 2, con fixtures nuevos y mutaciones, y pasa check.sh. Hecho el 29-09 (f24a280).

  4. Se pone el tag spec-v0.9. Hecho el 29-09, con la autorización del autor:

    • 7e2d83c anota el SHA-256 del spec en spec/README.md, que también va en el mensaje del tag;
    • main avanzó hasta ese commit sin merge;
    • main, v0.9 y el tag están subidos.
  5. datekeys-ts sincroniza testdata y el lector TypeScript abre el formato 2. Hecho el 29-09 (0118890, subido):

    • testdata a 7e2d83c;
    • el prelude lee el formato; decodeControl y encodeControl reciben el formato; padding.ts con las dos reglas, exactas hasta L_MAX;
    • open exige 16 stanzas en el paso 12, calcula P en el 16 y comprueba el relleno en el 17, entregando solo los L primeros bytes; el paso 17 se registra también cuando se supera;
    • la página muestra el formato, avisa del 1 y, al abrir una cápsula del formato 2, da la regla y P;
    • ibe-vectors.json añade los siete fixtures del formato 2, calculados con scripts/ibe-go-vectors.go; los valores congelados no cambian;
    • comprobado: los 125 casos del corpus dan en TypeScript el código, el paso y el texto de error de capsule.Open, en memoria y desde un Blob.
  6. Se replantea el plan de la fase 3 y se escribe el writer TypeScript del formato 2. Hecho el 29-09. El 29-09 por la noche, PLAN_fase3_escritura.md pasó a su v2, sobre las reglas del §62.1:

    • 16 huecos con señuelos y orden uniforme;
    • relleno reforzado por defecto;
    • L conocida de antemano;
    • autocomprobaciones;
    • recipients canónicos y no de orden bajo, como Go;
    • SEALED_CONTROL_LEN con la fórmula del §62.1 y comprobada. Una revisión crítica con sondas no encontró nada bloqueante ni grave, y sus 12 correcciones menores están incorporadas.

    Hecho el 29-09 en datekeys-ts, todo subido y con npm run verify en verde en cada paso:

    • paso 0: el autor confirma las 17 decisiones con su recomendación, entre ellas cerrar 0.1.0 ya (D14), la fórmula del §62.1 comprobada con el sellado real (D3) y aceptar los puntos del twist, como Go (D6). El plan pasa a v3 (b97dee2 en este repo);

    • paso 1: 0.1.0 cerrada (d577283, tag v0.1.0) y 0.2.0-dev abierta (8c08c97);

    • paso 2 (8838c7d): recipient.ts, random.ts y agefile.ts, y las guardas nuevas;

    • pasos 3 y 4 (8473fdf): encrypt.ts y writer.ts. Reproducen byte a byte las secciones deterministas de los siete fixtures del formato 2 de Go, escriben en streaming y abortan la salida ante cualquier fallo. El bucle de propiedades pasa con 500 semillas;

    • paso 5 (da0b39f): Go abre con cada credencial las trece cápsulas de muestra que escribe TypeScript, y las reencodifica a los mismos bytes. Rechaza cuatro mezclas con el mismo código y paso, codifica igual 500 entradas aleatorias y da los mismos textos en 22 recipients y 21 opciones inválidas. Todo queda congelado en src/lib/dkc/testing/capsule-vectors.json.

    • paso 6: el autor confirma las decisiones de la página con cada recomendación (sección 9 del plan, «Decidido en el paso 6»): time_only por defecto, la zona del dispositivo con un selector, los avisos de §53 y §50 desde 365 días y un aviso de protocolo preliminar;

    • paso 7 (3a9d2b1): la página /create, con lengths.ts (el tamaño del .dkc antes de escribirlo), localtime.ts, create-input.ts y creator.ts. En la compilación de producción, una cápsula creada para dentro de cuatro minutos se abrió después en /inspect, con el release pegado de drand, y con datekeys decrypt de Go, con red y su .dkk, al mismo contenido. Una revisión adversarial encontró un fallo mayor y ocho menores, todos corregidos. El mayor: la .dkk que es la única credencial se podía borrar sin confirmación.

    • después, a petición del autor (da2000a): /inspect muestra el texto en claro de cualquier cápsula que se abre, si es texto, y no solo el de los fixtures. Las dos páginas explican las claves de age: qué es un destinatario age1…, cómo se consigue con age-keygen y qué se pega al abrir.

    Siguiente: que el autor decida si cierra 0.2.0 (tag v0.2.0 en datekeys-ts). Después, lo de §2.4.

Formato de cápsula 3, en diseño (30-09). El autor quiere que una cápsula guarde varios ficheros y carpetas con sus nombres, tamaños, hashes y fechas, más una firma de autor y un sello de tiempo, ambos opcionales. Hoy el nombre del fichero se pierde: §6 y §55.2 lo dejan fuera del protocolo.

  • Decisiones del autor:
    • todo va cifrado dentro de PAYLOAD_AGE, como security | head | content;
    • hash SHA-256 por fichero, sin hash global;
    • con carpetas;
    • la fecha de modificación se toma al cargar, marcada por defecto;
    • un comentario y un autor declarado, opcionales;
    • sin tipo de contenido;
    • firma Ed25519 y sello de DateKeys, con registro anclado en OpenTimestamps.
  • Un flujo de diseño con revisión adversarial produjo spec_v0.10/formato3_diseno.md: 28 objeciones, que resultaron ser 24 distintas, corregidas o aceptadas.
  • El paquete para la revisión de seguridad externa, con el contexto del protocolo, el modelo de amenazas y las preguntas, era spec_v0.10/formato3_para_revision.md (56851a9). Se borró al unificar el diseño, pero sigue en git y publicado como artefacto privado, en la versión que revisó Fable: https://claude.ai/artifact/5NY9YxBjZA6DCadZ1aT5Ln.
  • Revisión de Fable (30-09), guardada en spec_v0.10/revision_fable.md.
    • Veredicto: la parte criptográfica aguanta, y confirma la aritmética de tamaños y la necesidad del verificador Ed25519 propio. Los problemas están en los bordes.
    • Diez hallazgos, cuatro mayores y seis menores; también hay observaciones sobre el documento.
    • Valoración: coincido con todos. Comprobados de memoria: el 2 (la lista de git en core.protectHFS incluye ZWJ, ZWNJ y U+206A–206F) y el 6 (JavaScript compara en UTF-16: U+FF5E y un emoji quedan al revés que en Go).
  • Arreglos que no necesitan decisión:
    • 2. R4 por la propiedad Default_Ignorable_Code_Point, con lista blanca corta (ZWJ, ZWNJ, VS15, VS16); la clave de R7 descarta lo permitido; tags U+E0000 a U+E007F prohibidos.
    • 5. El tamaño del área de security va en la trama, fijo por versión y reservado siempre.
    • 6. TypeScript compara bytes UTF-8, con un vector en paths.json.
    • 7. En la CLI, prefijo en cada línea visual del comentario, y los veredictos repetidos al final.
    • 8. Se declara como fuga aceptada que el POST al servicio delata el sello.
    • 9. Tabla de verdad firma/sello, expresión regular de R6b y regla para una mtime negativa.
    • 10. Prefijos de dominio en control_commit y head_digest, y el nombre .datekeys-* reservado.
    • El documento: 24 objeciones en vez de 28, marcadas «corregida» o «aceptada»; un glosario (capas 2 a 4, L_MAX, la sal); un texto para un sello que el lector no sabe verificar; una sola fuente en vez de tres ficheros que repiten el texto.
  • Decisiones del autor del 30-09 sobre la revisión:
    1. Tres entregas, con el formato congelado desde la primera y security presente pero vacío:

      • 1: contenedor, varios ficheros y rutas;
      • 2: firma y claves de autor;
      • 3: el sello, cuando exista el documento «Servicio de sellado v1».

      Las entregas 2 y 3 no cambian el formato: un lector anterior muestra «no soportado» y abre igual.

    2. Origen del servicio (hallazgo 1): el autor no tiene preferencia, así que se toma la recomendación.

      • Un subdominio aparte, seal.datekeys.com, que solo sirve la API y nunca HTML, con cabeceras nosniff y CSP: sandbox de todos modos.
      • La CSP de /create añade ese origen a connect-src, solo en esa página.
      • Es de la entrega 3 y se puede revisar entonces.
    3. Vida del sello (hallazgo 3): la prueba va dentro de la cápsula.

      • El token lleva la prueba de inclusión y el checkpoint firmado, y una raíz offline, fijada desde ya, certifica las claves anuales. Así el sello se verifica sin red para siempre, y la auditoría del anclaje queda como comprobación online opcional.
      • Esto agranda el área de security: con el arreglo del hallazgo 5, la entrega 3 define una versión de security con un área fija mayor.
    4. Abuso (hallazgo 4): prueba de trabajo SHA-256 en cada petición, de un segundo en el navegador, sin guardar estado sobre quién pide.

  • Hecho el 30-09 a mediodía (57dc659), sin flujo y con un único revisor adversarial:
    • formato3_diseno.md es la única fuente del diseño. Se borraron formato3_revision_intro.md y formato3_para_revision.md, que repetían su texto.
    • Estructura: una parte 0 de contexto, con glosario, decisiones y modelo de amenazas; una parte por entrega, cada una con sus pruebas y sus preguntas abiertas; y tres anexos con las revisiones. El de Fable dice dónde se resuelve cada hallazgo, el de la revisión interna marca sus 24 objeciones como corregidas o aceptadas, y el tercero recoge la revisión adversarial de esta versión.
    • Aplicados los arreglos 2 y 5 a 10, los del documento y las cuatro decisiones.
    • La revisión adversarial no encontró nada bloqueante ni mayor. Sus 15 hallazgos menores están resueltos en el diseño (anexo C), y una segunda pasada comprobó los arreglos. Los que cambian el diseño:
      • el head va siempre en su versión 1, porque §22 exige un formato nuevo para una versión nueva;
      • las claves 2 y 3 de security van codificadas aparte, así que una firma o un sello mal formados no arrastran al otro;
      • el área depende solo de la versión del spec, nunca de -seal, y hay dos fugas nuevas declaradas: un área de 512 delata que no hay sello, y el registro publica la t de cada sello;
      • R3 limita el NFD de cada segmento a 255 unidades UTF-16, por HFS+, y R4 prohíbe U+F000–U+F0FF;
      • un sello que no verifica se descarta y ya no aborta la cápsula.
    • Interpretación que confirmar: la decisión 3 hablaba de «una versión de security con un área fija mayor». El diseño hace que el área la fije la versión del spec y deja el mapa security en su versión 1, para que un lector de la entrega 2 siga comprobando la firma en una cápsula de la entrega 3. Es la pregunta 3 de la entrega 1.
  • Hecho el 30-09 por la tarde:
    • El autor cerró las diez preguntas de la entrega 1, todas con la recomendación (afd9f76). Los límites quedan como se propusieron y congelados con el formato. Un único fichero dentro de una carpeta se descarga directamente, con el ZIP como opción, y la página ofrece cada fichero del ZIP como un corte suyo.
    • El borrador del spec v0.10 de la entrega 1 está en datekeys-go, rama v0.10, sin subir: fa7f95e lo redacta y 9d1cd2e aplica la revisión final. Lleva el spec, el CDDL y spec/README.md. La referencia sigue implementando la v0.9, y su SpecVersion no cambia.
    • La revisión final, como la de la v0.9, encontró un problema bloqueante, tres mayores y once menores, todos corregidos (spec_v0.10/revision_borrador.md). El bloqueante: R6c rechazaba «¿», porque bestfit1250 lo lleva a '?'. Ahora solo rechaza '/', '', ':' y U+0000 en una proyección. El diseño recoge los cambios que le afectan en su anexo D.
    • Pregunta del autor: la firma de autor con su clave privada está prevista, en la entrega 2. Varias firmas no hace falta decidirlas ahora: un alg futuro puede definir una lista de firmas sin cambiar el formato (pregunta 3 de la entrega 2 del diseño).
  • Siguiente:
    1. Hecho: el autor eligió Unicode 18.0.0 («no vamos a trabajar con unicodes ya pasados») y dio el visto bueno al texto. El borrador lo recoge en su rama, y el diseño, en su decisión 4.
    2. Hecho: el autor aprobó la regla de invisibles («sí a las dos»), que el spec recoge en R4b y en §29.6 (631d09c).
    3. Hecho: con su permiso se descargaron los 19 ficheros de datos, 8,25 MB, en datekeys-go/.cache/, fuera de git.
    4. Hecho: la referencia Go implementa el formato 3, con el plan y el detalle de abajo. Con la autorización del autor («sí, sube la rama y pon el tag»), la rama v0.10 y el tag anotado spec-v0.10 están en el remoto, en cc35d2c, que solo cambia textos para nombrar el tag. Después, a petición suya («sí, avanza main hasta la v0.10»), main avanzó hasta cc35d2c sin fusión y está subida.
    5. En curso: datekeys-ts lee y escribe el formato 3 con su plan. En la rama v0.10 de App, sin subir, están hechos los pasos 0 y 1 (fbb90b2, las tablas y las reglas de rutas y de texto), del paso 5 el CRC-32 y la disposición del ZIP (36096a9), el paso 2 (d9a9cf5, el códec) el paso 3 (b176ad2, la lectura del formato 3 con testdata en spec-v0.10) y el paso 4 (de 3daa1f7 a 2efc8bc: encryptFiles, encrypt solo con testVectors, /create en formato 3 con un fichero, y la interoperabilidad con Go). El paso 5, el ZIP y el sumidero de la página, está en ee82f43, el paso 6, la página /inspect con los ficheros del formato 3, en 651178a, y el paso 7, la página /create con ficheros, carpetas, rutas editables, comentario y autor, en 7dc88ef. El paso 8 está hecho (7527c35, 57e0a8a, e6cca0b y el CHANGELOG): README, testdata:check contra cc35d2c, tres revisiones adversariales con subagentes y sus correcciones, y, a petición del autor, /create rediseñado (una carta al futuro, sobre de correo aéreo, fuentes del sistema) y el sitio siempre claro. Pendiente, sin urgencia:
      • /inspect solo cambió de aspecto con los estilos globales: falta poner el resultado delante y plegar los pasos 1 a 18, como en /create.
      • El texto del paso 17 aún difiere del de Go cuando la cápsula se corta justo tras un chunk completo: age-encryption retiene ese chunk hasta ver un byte más. Igualarlo exige descifrar el STREAM como Go (código propio con @noble/ciphers).
      • Un head de 16 MiB tarda de 10 a 40 s en la página, en el hilo principal (Go tarda la mitad): open() en un worker.
      • Menores: el TypeError sin sumidero llega tras los pasos 3 a 8 con un Blob; tempfile.remove() marca borrado antes de lograrlo; measureFiles en cada tecla con 65 535 ficheros; un bundle .app no avisa (igual que la CLI).
      • Subido el 01-10 por la noche, con permiso del autor: la rama v0.10 de App, y main y v0.11 de datekeys-go.
    6. La entrega 2 abre la versión siguiente del spec, y la 3 espera al documento «Servicio de sellado DateKeys v1». En esa versión entra también la llave de palabras que pidió el autor el 01-10: palabras que elige la persona y abren la cápsula en lugar de la .dkk, ya hechas en la página y en la CLI (apartado «Retomar aquí»). Además, el 01-10 el autor pidió que /inspect pueda pedir la firma a drand: ya lo hace, con un botón (2ec7102), lo que cambia la decisión 4 del plan de la fase 2. Para otra revisión externa, el artefacto hay que volver a publicarlo desde el diseño nuevo.

Hecho el 30-09 por la noche: el formato 3 en Go. Rama v0.10 de datekeys-go, subida con el tag spec-v0.10 en cc35d2c, un commit o varios por paso del plan:

  • 631d09c, el spec con la regla de invisibles; 6fba1dd, paso 1, internal/pathrule con las tablas de Unicode 18.0.0 y best-fit generadas y su TablesDigest; 72e86b8, paso 2, el códec de BODY, security y el head.
  • 7249ef4, paso 3, el lector: capsule.Sink, ErrSinkRequired justo tras el paso 2, el paso 17 en subpasos con su precedencia, y lecturas de BODY que crecen con los bytes recibidos (§57).
  • 8955c0f, paso 4, el escritor capsule.EncryptFiles, que lee cada fichero dos veces; Encrypt solo escribe el formato 2 con EncryptOptions.TestVectors.
  • a0de80f, paso 5, el CLI: encrypt -in con ficheros y carpetas, -comment, -author y -no-mtime; decrypt -out CARPETA con os.Root; la presentación de §29.7, con el ancho del terminal pedido por syscall, sin dependencias nuevas.
  • Paso 6, datos de prueba: 3c39336 (SpecVersion 0.10 y ERR_HEAD_INVALID), e070f89 (las nueve fixtures), db862d5 (paths.json, path_fold.json, head_schema.json, security.json y el control de versión 3 en cbor.json) y 18eb3c3 (las mutaciones: 209 casos, 169 del §64, tres de los cuales se abren con su veredicto).
  • 20f9959, paso 7, la documentación; 735885c, una corrección del CLI: una carpeta de salida sin su carpeta padre falla antes de pedir el release; 6fa2b54, paso 8, tres objetivos de fuzzing nuevos (FuzzDecodeHead, FuzzEvaluateSecurity, FuzzCheckPath) y el SHA-256 del spec en spec/README.md.
  • Verificación: go test ./... y scripts/check.sh 60s limpios, cobertura de capsule 93,1 %; la prueba en vivo contra Quicknet abrió cápsulas de formato 3 de las dos políticas; los tres objetivos nuevos, cerca de un millón de ejecuciones cada uno, sin fallos.
  • Para el autor, sin urgencia:
    • un cambio editorial en el texto aprobado: §67 decía «Serán … (por implementar)» de las fixtures del formato 3, y ahora dice «Son …». El SHA-256 de spec/README.md es el del texto con ese cambio;
    • el corpus de mutaciones pasa de 168 KB a 706 KB. 476 KB son el caso de 65 536 carpetas implícitas que pide el §64, cuyo head mide 235 KB;
    • los textos del CLI que el spec no fija son de la referencia: la cabecera «Ficheros escritos en CARPETA (N):», los avisos de nombres peligrosos y los mensajes del escritor. Los que fija, los veredictos y las dos etiquetas, van literales.
  • Para datekeys-ts:
    • hecho: el generador escribe el módulo TypeScript con la bandera -ts (13910b3, en main de datekeys-go, un commit por delante de origin/main y sin subir), y el digest recalculado en TypeScript coincide con TablesDigest;
    • testdata cambia entero de "spec", y añade nueve fixtures, cuatro ficheros de vectores, mutations.json con 209 casos (version changed pone ahora VERSION 4, y hay casos con verdicts) y el diferencial con 5 110;
    • los textos de las reglas de rutas y de texto deben coincidir byte a byte: paths.json y head_schema.json los traen en result y detail.
  • Herramientas: en esta máquina los heredocs de Bash rompen apóstrofos y barras invertidas, y la herramienta Write convierte \uXXXX en caracteres literales. Funciona escribir los cambios como scripts de Python en el scratchpad.

Conclusiones de la conversación, sin decisión pendiente:

  • El protocolo no contempla un sello de tiempo de creación (§5, §55.1). Si se quiere, lo recomendado es un sello RFC 3161 u OpenTimestamps sobre el SHA-256 del .dkc completo, guardado aparte.
  • Un fichero único .dk con .dkc y .dkk juntos no conviene: con time_and_key equivaldría a time_only. Ya se envía un solo fichero con time_only o con destinatarios age1….
  • datekeys-ts cerró 0.1.0 el 29-09 (d577283, tag v0.1.0), y la fase 3 va en 0.2.0-dev.

2.3 Depende del autor

  • Crear security@datekeys.com y, si se quiere, un security.txt en la web. Después, actualizar SECURITY.md, que hoy dice info@activething.com.
  • Elegir la ruta pública del módulo Go (propuesta: datekeys.com/go/datekeys, en minúsculas) y el espejo público, que no puede ser GitHub (por ejemplo Codeberg). Publicar la página go-import en datekeys.com. Después: renombrar el módulo y poner el tag v0.1.0 cuando go get funcione desde una máquina limpia.
  • Decidir si datekeys-ts cierra 0.2.0, ahora que la fase 3 está completa.

2.4 Más adelante

Release API sobre la librería, traducción del spec al inglés y revisión externa antes de la v1.0. Opcional: escribir en OPFS en trozos de 1 MiB, que ahorra un 10 % al cifrar ficheros grandes en la página (README de datekeys-ts, «Crear»).


3. Reglas del proyecto

Están en el README de este repo, que el CLAUDE.md de la raíz carga en cada sesión.


4. Documentos

  • En este repo están los planes, la revisión del protocolo y los papeles de la v0.9. El README los lista.
  • En datekeys-go:
    • spec/DateKeys_Protocol_Specification_v0.10.md, cerrado con el tag spec-v0.10; spec/DateKeys_Protocol_Specification_v0.9.md, cerrado con el tag spec-v0.9; spec/DateKeys_Protocol_Specification_v0.8.2.md, spec/datekeys.cddl y spec/README.md;
    • testdata/README.md, que documenta los ficheros compartidos para segundas implementaciones;
    • docs/traceability.md y CHANGELOG.md.
  • Las herramientas de verificación de las sesiones del 26 al 28-09 estaban en carpetas temporales y pueden haber desaparecido: el diferencial Go/TypeScript de tsreview/ y las copias congeladas dkgo-ref-<commit>. Su descripción está en los mensajes de los commits de datekeys-ts y en su README.

Powered by TurnKey Linux.