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.

11 KiB

Plan: formato 3 en datekeys-ts (spec v0.10, entrega 1)

30 de septiembre de 2026. Implementa en datekeys-ts, rama v0.10, lo que la referencia Go ya hace con el tag spec-v0.10 (cc35d2c): leer y escribir cápsulas de formato 3, en la librería y en las páginas. Fuentes: el spec v0.10, spec_v0.10/formato3_diseno.md, cuyas decisiones de la página ya aprobó el autor (apartados 3 y 5, decisiones 8 a 11 del apartado 9), y el código Go de capsule/format3.go, open3.go, encrypt3.go e internal/pathrule.

Reglas de trabajo

  • Cada paso va en su commit, o en varios, sobre la rama v0.10, y cada commit deja npm run verify en verde. main no se toca mientras el autor no decida si cierra 0.2.0 (§2.3 del handoff).
  • Nada se sube sin la autorización del autor.
  • Sin dependencias nuevas: las tablas Unicode las genera datekeys-go (pathrule/gen -ts), y el ZIP y el CRC-32 son código propio.
  • testdata solo llega de datekeys-go, con scripts/sync-testdata.mjs y el tag spec-v0.10.
  • Los textos de error siguen los de Go byte a byte, también los de las reglas de rutas y de texto, y las líneas de los veredictos en español.
  • src/lib/dkc sigue a la referencia Go. Lo que solo tiene la página va en src/lib/inspector: el ZIP, el CRC-32 y el sumidero en OPFS.
  • Los módulos nuevos se cubren al 100 %, como los de las fases 2 y 3 (vitest.config.ts).

Pasos

Paso Contenido Resultado
0 Tablas: el generador de datekeys-go escribe src/lib/dkc/pathrule-tables.ts Hecho el 30-09: datekeys-go 13910b3, sin subir. El digest recalculado en TypeScript coincide con TablesDigest
1 pathrule.ts: NFD, pliegue, clave de R7, de R1 a R10 con R4b, R6b, R6c y R9, y las reglas de texto de §29.6 Hecho el 30-09: los casos de las pruebas Go con sus textos, y cobertura del 100 %
2 Códec del formato 3, sin tocar la trama: BODY, security y head, y ERR_HEAD_INVALID Hecho el 30-09, d9a9cf5: los casos de las pruebas Go, con los textos de Go sacados de la referencia
3 Lector y testdata en spec-v0.10: VERSION 3, control de versión 3, paso 17 en subpasos, sumidero y lectura hasta EOF Hecho el 30-09, b176ad2: los 209 casos del corpus con el texto exacto de Go, congelado en testing/mutation-texts.json
4 Escritor: encryptFiles, en dos fases y con dos lecturas; encrypt solo para vectores Hecho el 30-09, de 3daa1f7 a 2efc8bc: los cinco fixtures de EncryptFiles byte a byte, los textos de Go, /create en formato 3 con un fichero, y Go abre seis cápsulas de formato 3 de TypeScript
5 ZIP de la página y su sumidero en OPFS Hecho el 30-09, 36096a9 y ee82f43: ZipSink con escrituras posicionadas, y archive/zip de Go lee las muestras, 65 535 entradas incluidas
6 Página /inspect: veredictos, autor, comentario, rutas y descargas Hecho el 30-09, 651178a: un fichero suelto o un ZIP en OPFS, con la descarga de cada fichero; en Chromium, el ZIP de format3_tree con sus CRC-32 parcheados y el borrado del temporal
7 Página /create: ficheros y carpetas, rutas editables, exclusiones, comentario, autor y mtime Hecho el 30-09, 7dc88ef: el tamaño exacto antes de escribir, y datekeys decrypt de Go y /inspect abren una cápsula de seis ficheros escrita por la página
8 Documentación, verificación y revisión adversarial README, CHANGELOG, npm run verify y una revisión adversarial del lector, del escritor y de las páginas

Paso 1. Reglas de rutas y de texto

  • pathrule-tables.ts es código generado: no se edita a mano. Se regenera con go run ./internal/pathrule/gen -data .cache -go internal/pathrule/tables.go -ts ../App/src/lib/dkc/pathrule-tables.ts desde datekeys-go, y una prueba recalcula su digest.
  • pathrule.ts no usa normalize, toLowerCase, localeCompare, Intl ni las clases \p{...}, porque su versión de Unicode cambia con el motor. Los límites cuentan bytes de UTF-8, con el utf8Length de bytes.ts.
  • index.ts no lo reexporta: sus tablas pesan 136 KB y se cargan bajo demanda, con el lector y con el formulario de /create (pasos 6 y 7).

Paso 2. Códec

  • Módulos por esquema, como header.ts y control.ts: body.ts (la trama de §29.2, AREA_LEN, SECURITY_LEN y HEAD_LEN, y el área rellena de ceros), security.ts (el mapa exterior, la firma y el sello, los veredictos X, F0, F1, S0, S1 y S2 con sus textos, y el codificador) y head.ts (capas 2 a 4 del head, R1 y R8 en la capa 3, y la capa 4 con ERR_HEAD_INVALID).
  • ERR_HEAD_INVALID en errors.ts, que pasa a 19 códigos, y su glosa en format.ts.
  • El objeto de extensiones HEAD_CBOR en extension.ts, con sus claves 6 y 7.
  • Pruebas: los casos de format3_test.go con sus bytes y sus textos. Los vectores de head_schema.json y security.json llegan en el paso 3.

Paso 3. Lector y datos de prueba

  • npm run testdata:sync -- --commit spec-v0.10, SPEC_VERSION 0.10, y la autocomprobación del arnés con want 0.10.
  • Trama: FORMAT_3, y isFormat acepta de 1 a 3. El control de versión 3 tiene las claves del de versión 2. accessSlots da 16 en los formatos 2 y 3, y el relleno vale para los dos.
  • open:
    • Gana OpenOptions.sink: begin(head), create(i) con un WritableStream, commit() y abort(). Tiene la semántica del Sink de Go: nada se presenta como válido antes de commit.
    • Sin sumidero, un formato 3 rechaza con un TypeError justo tras el paso 2, antes de pedir nada, como ErrSinkRequired.
    • El paso 17 va en los subpasos 17.1 a 17.8, con la precedencia de Go:
      • Un fallo de age, o una longitud distinta de P, prevalece.
      • Si no, manda el primer subpaso que falle.
      • Los códigos distintos de ERR_INTEGRITY solo se dan tras leer PAYLOAD_AGE hasta EOF.
    • Opened gana head, verdicts, areaLen y unusableHeadExtensions.
  • inspect acepta el formato 3 en los pasos 1 a 8, y su vista JSON coincide con la de Go.
  • Un sumidero en memoria en opener.ts, para los fixtures y para contenidos de hasta 64 MiB. Hasta el paso 6, la página inspecciona el formato 3 y, al abrirlo, dice que aún no entrega ficheros.
  • Pruebas:
    • fixtures.test.ts con los formatos 1, 2 y 3.
    • open.test.ts: cada fixture abre, con el SHA-256 de BODY y el de cada fichero.
    • mutations.json: 209 casos, con la clave verdicts y los casos ok, desde memoria y desde un Blob, con un sumidero que debe acabar abortado.
    • inspect_differential.json: 5 110 casos sobre 14 bases.
    • cbor.json con el control de versión 3; head_schema.json, security.json, paths.json y path_fold.json.
    • ibe-vectors.json, regenerado con scripts/ibe-go-vectors.go para los nueve fixtures nuevos.
  • Los textos de error de los 209 casos quedan congelados desde Go, con un script, en testing/, igual que capsule-vectors.json. En la v0.9 se compararon una sola vez, fuera del repositorio.
  • check-build.mjs añade a los secretos de fixture que no pueden publicarse el head, la sal, el comentario, los ficheros y BODY.

Paso 4. Escritor

  • encryptFiles(files, opts):
    • Cada fichero trae path, size, mtime opcional (en milisegundos, como File.lastModified) y una forma de leerlo dos veces: un Blob o open().
    • Las opciones ganan comment, author y las extensiones del head.
  • Primera fase:
    • Rutas y textos con las reglas del lector: CR LF y un CR suelto pasan a LF en el comentario.
    • La mtime con la regla 16 de §62.1.
    • L medido con un head de sal y hashes a cero.
    • |HEAD| de 16 MiB como máximo, y L como máximo L_MAX.
    • La primera pasada de SHA-256, en piezas de 64 KiB.
  • Segunda fase:
    • La sal y HEAD_CBOR, el control de versión 3 y el SECURITY_CBOR vacío.
    • La autodecodificación de los tres CBOR (MUST).
    • La segunda pasada, que aborta si un fichero cambió de tamaño o de SHA-256, con el texto de Go.
    • El .dkk.
  • capsuleLength3 en lengths.ts: el tamaño exacto antes de escribir, para la página.
  • encrypt escribe el formato 2 solo con testVectors, con el texto de Go. La página deja de usarlo en el paso 7.
  • Interoperabilidad:
    • scripts/capsule-ts-samples.mjs gana muestras del formato 3, y scripts/capsule-go-verdicts.go las abre con capsule.Open y un sumidero.
    • capsule-vectors.json se regenera.
    • Con sorteos fijos, las secciones deterministas coinciden con las de los fixtures format3_*.

Paso 5. ZIP y sumidero de la página

  • Hechos y cubiertos al 100 %:
    • crc32.ts.
    • zip.ts: entradas almacenadas, nombres UTF-8 con el bit 11, sin descriptores de datos ni entradas de carpeta, el CRC-32 parcheado en la cabecera local, fechas DOS en UTC entre 1980 y 2107, el campo NTFS 0x000A, que manda, el 0x5455 cuando cabe en 32 bits con signo, y ZIP64 por tamaño, posición o número de entradas.
  • zipsink.ts, un sumidero sobre un solo fichero de OPFS:
    • Un único fichero de un segmento se escribe tal cual.
    • En otro caso va el ZIP, con las cabeceras escritas por adelantado, el CRC-32 con escrituras posicionadas y el directorio central en commit.
    • Cada fichero se ofrece como un trozo (slice) del de OPFS.
    • tempfile.ts gana la escritura posicionada.
  • Interoperabilidad:
    • Un script escribe ZIP con TypeScript: nombres no ASCII, mtime ausente o fuera de rango, ficheros vacíos y 65 535 entradas.
    • archive/zip de Go los lee, y el resultado queda congelado en testing/zip-vectors.json.
    • La entrada de 4 GiB solo se prueba en la disposición: el fichero entero no cabe en una prueba.

Paso 6. Página /inspect

  • Primero los veredictos, en sus líneas de §29.7, y después el autor declarado y el comentario, con el prefijo de la regla.
  • Las rutas, en <bdi dir=auto> y con los invisibles escapados.
  • Avisos según la clave de R7: .lnk, .url, .library-ms, .searchConnector-ms, desktop.ini, .git, ejecutables y un - inicial.
  • Descargas:
    • Un único fichero de un segmento se descarga con su nombre, pasado por safeFileName.
    • Un único fichero dentro de una carpeta se descarga primero, y el ZIP después (decisión 8).
    • Con varios ficheros, el ZIP se llama <primer segmento común>.zip, o <nombre del .dkc>.zip, y cada fichero tiene su descarga.
  • El espacio de OPFS se comprueba dos veces: con el contenido cifrado antes de empezar, como en el formato 2, y con la longitud exacta del ZIP al leer el head, antes de escribir nada.
  • check-build.mjs comprueba que las tablas de pathrule no entran en la primera carga de ninguna página.

Paso 7. Página /create

  • Ficheros y carpetas, con multiple, webkitdirectory y arrastrar y soltar.
  • Rutas editables, validadas con pathrule a medida que se escriben.
  • Exclusiones tachadas, que se pueden reactivar: .DS_Store, Thumbs.db, desktop.ini, ._* y __MACOSX/.
  • Comentario, autor declarado, y una casilla de mtime marcada por defecto.
  • Las dos fases del escritor, con el progreso de las dos pasadas.
  • El tamaño exacto del .dkc y la comprobación de la cuota antes de escribir.
  • creator.ts sigue inspeccionando la cápsula escrita y exige el tamaño y la ronda del plan.

Paso 8. Documentación, verificación y revisión

  • README: versiones, módulos, páginas, vectores, dependencias y testdata. CHANGELOG: bajo «sin publicar»; el número de versión lo decide el autor.
  • npm run verify y npm run testdata:check.
  • Revisión adversarial de las páginas, del lector y del escritor, con subagentes, como en la fase 3.
  • Actualizar el handoff.

Powered by TurnKey Linux.