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.

21 KiB

Handoff DateKeys, 26 de septiembre de 2026 (actualizado el 29 por la noche, al cerrar la fase 3)

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). Sirve para retomar sin contexto previo, sea una persona o una sesión de Claude.


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.

1. Repositorios

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 7e2d83c Spec v0.9 cerrada, con el tag anotado spec-v0.9 en 7e2d83c; SHA-256 del spec 36189e1e62f0f835b7665219aa63df7200cd89ac4e4e924f2705f970fa7c40a9. Implementa el formato 2 (f24a280): lo escribe y lee los formatos 1 y 2. scripts/check.sh 60s limpio. La v0.8.2 sigue en su tag, spec-v0.8.2 (9ac9cd9).
v0.8.2 9ac9cd9 El commit del tag; ya no hace falta.
v0.9 7e2d83c Igual que main; ya no hace falta.
datekeys-ts, antes App (go/DateKeys-App) main 0118890 Desde 5ee8813, sin docs/ y con el paquete datekeys-ts (§0). Versión 0.1.0-dev, que implementa el spec 0.9 desde 0118890 (VERSION y SPEC_VERSION, también en el pie de la página). 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. 5 425 tests, ninguno saltado; npm run verify en verde.
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);
  • 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 (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).
  • 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.

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.8.2.md, el borrador spec/DateKeys_Protocol_Specification_v0.9.md (rama v0.9), 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.