digest: blake3 pelado, no length-prefijado — el mismo archivo tenía dos hex
Lo destapó escribir la contraparte del ADR 0014 para churay: churay direcciona sus blobs con blake3(bytes) pelado y hammer iba a sellar el digest con of_inputs(&[bytes]), los dos bajo el prefijo `b3:`. El mismo archivo con dos hex distintos, y un CAS compartido que no falla ruidosamente: cada lado busca un nombre distinto para los mismos bytes. Con una sola entrada el length-prefijado no desambigua ninguna concatenación — sólo hace que el nombre deje de ser verificable por un tercero con b3sum en la mano. `ArtifactHash::of_bytes` YA EXISTÍA y ya era blake3 pelado: es la convención de of_file y la del expected_hash de un .swm, así que of_inputs era además la pieza fuera de sitio dentro del propio repo. of_inputs se queda para lo que fue escrito: hashear una LISTA. Coste: una línea, porque ningún índice publicado lleva todavía el campo. Es el argumento del ADR aplicado a sí mismo — decidir antes de que haya usuarios. La corrección queda en el ADR, no reescrita en silencio. Guardián: digest_es_blake3_pelado_y_no_length_prefijado, con vector fijo de b3sum y un assert_ne contra of_inputs que nombra la consecuencia. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CK6HpSoHcN9M4GBpqRSusR
This commit is contained in:
@@ -100,10 +100,25 @@ alcanza: `expected_hash` es **opcional**, y el `.swm` se lee mucho antes de lleg
|
||||
colisiones de ficheros de `install` ya decide con su contenido). El comentario de `download.rs`
|
||||
decía que el `patch_url` «se cubre indirectamente»; *indirectamente* no es una cadena de confianza.
|
||||
|
||||
Se cierra con `PackageEntry::digest` (BLAKE3, `b3:…`, la misma función que sella artefactos — no una
|
||||
segunda convención de hash conviviendo con la primera), sellado al publicar y verificado antes de
|
||||
Se cierra con `PackageEntry::digest` (BLAKE3, `b3:…`), sellado al publicar y verificado antes de
|
||||
escribir un byte. La cadena queda: **clave raíz → firma del índice → `digest` → bytes**.
|
||||
|
||||
> **CORRECCIÓN (mismo día).** Este párrafo decía que el `digest` usaba «la misma función que sella
|
||||
> artefactos», o sea `of_inputs(&[bytes])` — length-prefijado. **Estaba mal, y la razón importa.**
|
||||
> Con una sola entrada el length-prefijado no desambigua ninguna concatenación: sólo hace que
|
||||
> `b3:<hex>` **deje de ser el hash que obtiene un tercero** con `b3sum` sobre el mismo archivo.
|
||||
>
|
||||
> Lo destapó escribir la contraparte de este ADR para churay (`02_ruway/churay/SDD-DISTRIBUCION.md`
|
||||
> §5 en tawasuyu): churay direcciona sus blobs con `blake3(bytes)` pelado y hammer iba a hacerlo
|
||||
> length-prefijado, **bajo el mismo prefijo `b3:`** ⇒ el mismo archivo con dos hex distintos, y un
|
||||
> CAS compartido que no falla ruidosamente sino que busca nombres distintos para los mismos bytes.
|
||||
>
|
||||
> Ahora usa `ArtifactHash::of_bytes` — que **ya existía en hammer** y ya era blake3 pelado; es la
|
||||
> convención de `of_file` y la del `expected_hash` de un `.swm`, así que `of_inputs` era además la
|
||||
> pieza fuera de sitio *dentro* del propio repo. Coste del cambio: una línea, porque ningún índice
|
||||
> publicado llevaba todavía el campo. Es el argumento de este ADR aplicado a sí mismo — decidir
|
||||
> antes de que haya usuarios. Hay guardián: `digest_es_blake3_pelado_y_no_length_prefijado`.
|
||||
|
||||
El campo es `Option` con `skip_serializing_if`, así que **un índice firmado antes de este cambio
|
||||
serializa idéntico y su firma sigue siendo válida** (hay test). Un índice sin digests no bloquea,
|
||||
pero **dice cuántos paquetes no verificó**: un índice viejo servido desde un espejo ajeno no es
|
||||
|
||||
Reference in New Issue
Block a user