244 lines
14 KiB
Markdown
244 lines
14 KiB
Markdown
# SDD 17 — Cierres de frontera priorizados × cruce tawasuyu
|
||
|
||
> Análisis 2026-07-15. Origen: la jaula (SDD 16) y la capa CRDT (SDD 15 H2) cayeron
|
||
> "de casualidad" — eran básicas y no estaban en el plan. Este doc responde: ¿qué otros
|
||
> cierres, tecnologías de frontera o complementos dan ventaja competitiva, y qué crate o
|
||
> arquitectura de `../tawasuyu` los abarata? Es, en la práctica, la "parte 2" de
|
||
> `tawasuyu/shared/PLAN-CRUCES.md` (que no menciona a hammer ni una vez).
|
||
|
||
## 0. Tesis
|
||
|
||
Los tres invariantes ya pagados — **bit-reproducibilidad** (SDD 11/13), **direccionamiento
|
||
por contenido** (SDD 06) y **clausura-como-política** (SDD 16) — hacen casi gratis para
|
||
hammer tecnologías que para todos los demás son carísimas. La búsqueda correcta no es
|
||
"qué frontera agregar" sino **"qué cae solo del invariante"**, igual que la jaula cayó del
|
||
sandbox y el CRDT cayó de H2.
|
||
|
||
Rieles ya cableados entre repos (doc maestro:
|
||
`tawasuyu/03_ukupacha/arje/PLAN-ATESTACION-Y-HAMMER.md`): bus arje↔hammerd con contrato
|
||
wire por bytes, CAS BLAKE3 `b3:` compartido, boot-graph (ADR 0010), `arje-absorb
|
||
--attest-from`, `BuildSys::Cargo`.
|
||
|
||
Crates de `tawasuyu/shared/` limpios para importar (no_std o casi, deps mínimas):
|
||
**`fork-proof`, `reconcile`, `dataflow`, `umbral`, `grafo-nav`, `format`, `crdt`**.
|
||
|
||
## 1. Los diez cierres, en orden de prioridad
|
||
|
||
### 1. Consenso de reconstrucción — caché sin confianza
|
||
|
||
N builders independientes reproducen el mismo hash ⇒ el binario es confiable **sin que
|
||
nadie firme nada**. Piezas hammer listas: bit-repro verificada (selfhost, kernel), granja
|
||
efímera, embrión del log de transparencia (`bootstrap.json`, SDD 11 §4 / SDD 09 §4).
|
||
Nix/Debian no pueden ofrecerlo (repro incompleta). Convierte la repro de QA en **primitiva
|
||
de distribución**: cualquiera puede ser mirror, nadie puede envenenar el repo.
|
||
|
||
**Cruce**: `fork-proof` (log firmado hash-encadenado BLAKE3+Ed25519, no_std, con
|
||
`detectar_fork` = detección de equivocation no repudiable — **el log de transparencia ya
|
||
está escrito y testeado**, no hay que construir un rekor) · `umbral` (quórum M-de-N de
|
||
builders, agnóstico del backend cripto) · `card-net` (DhtKey = `kind_tag ++ blake3`, el
|
||
mismo hash que `b3:` — distribución de artefactos por hash en la malla) · `reconcile`
|
||
(sync de índices de mirrors en O(diferencia)). Economía del reparto: `sheafsync::BudgetRouter`
|
||
+ escrow (créditos de cómputo; el gancho a H2 ya está previsto en PLAN-OS-CRDT §E3c).
|
||
|
||
### 2. `hammer why-differs` — diffoscope propio
|
||
|
||
Cuando un hash no reproduce, explicar **por qué** (sección, timestamp, orden de símbolos).
|
||
Multiplicador doble: hace escalar el barrido de granja (hoy debuggear una no-reproducción
|
||
es artesanal) y produce evidencia legible por máquina para el bucle agéntico.
|
||
|
||
**Cruce**: `format` (grafo blob+árbol BLAKE3 no_std: dos árboles idénticos colapsan al
|
||
mismo hash ⇒ el diff estructural = descender sólo donde difiere) · `reconcile` (ese
|
||
descenso ES su algoritmo, huellas por rango) · `foreign-fs` (chunking content-defined de
|
||
256 KiB bit-reproducible) · `grafo-nav` (verbo "bifurcación" para pintarlo).
|
||
|
||
### 3. Política de runtime derivada del closure
|
||
|
||
Fase 3 natural de harkaq: la clausura de ficheros medida en build ES la política
|
||
Landlock del binario instalado. AppArmor/flatpak escriben políticas a mano; hammer las
|
||
**deriva**. Nadie tiene esto y la receta sellada ya contiene la evidencia.
|
||
|
||
**Cruce (oro, el riel existe)**: `ConcesionCapacidad` firmada sobre
|
||
`(blake3(binario), permisos)` que arje verifica al arranque + `arje-absorb --attest-from
|
||
<json>` que integra concesiones emitidas por hammer (PLAN-ATESTACION §B.3, hecho). La
|
||
clausura de harkaq son los `permisos` de esa concesión — el veredicto `Hermetico` se
|
||
convierte en política atestada sin inventar formato. Filosofía de referencia: el modelo
|
||
wawa "capacidad = frontera física, no tabla de permisos" (WAWA.md §4.2). Lado runtime:
|
||
`pacha-core` / `sandokan-lifecycle`.
|
||
|
||
**La lección casper (plan-freebsd T2.1–T2.2).** Capsicum, más puro que Landlock, terminó
|
||
necesitando demonios auxiliares (`casper`) porque hay una clase — *servicios del mundo* —
|
||
que no son paths y no caben en ninguna jaula por-fichero. La clausura de build **no
|
||
contiene esa clase** (builds offline por `--unshare-all`): derivarla a ciegas produce
|
||
binarios que revientan en el primer `getaddrinfo`. Política runtime = clausura de build
|
||
**+ clases de servicio declaradas por nombre** (D3 aplica en runtime: no se ensancha en
|
||
silencio). El mapa clase→permiso en musl cabe aquí porque musl no tiene nsswitch ni
|
||
dlopen de módulos NSS — la mitad de por qué casper existe no aplica:
|
||
|
||
| clase | permiso concreto (musl) |
|
||
|---|---|
|
||
| `dns` | leer `/etc/resolv.conf` + `/etc/hosts`, socket UDP/TCP :53 |
|
||
| `tls-certs` | leer `/etc/ssl/certs/` |
|
||
| `random` | `getrandom(2)` — ni path necesita |
|
||
| `locale` / `tz` | leer `/etc/TZ`, `/usr/share/zoneinfo/` (locale va embebido en musl) |
|
||
| `syslog` | socket unix `/dev/log` |
|
||
|
||
La clase viaja como campo de la `ConcesionCapacidad` — sin formato nuevo.
|
||
|
||
**Medición que confirma y acota lo anterior (Opus 4.8, 2026-07-16).** Se probó el riel de punta
|
||
a punta y salieron dos cosas que ajustan el diseño; la lección casper queda **confirmada y
|
||
reforzada**:
|
||
|
||
1. **El sujeto: la clausura de build no puede ser la política de runtime, ni siquiera de base.**
|
||
No es sólo que le falten las clases del mundo (casper): también le **sobra** casi todo. Un
|
||
build lee `zlib.h`, `make`, `gcc`; el binario resultante no abre ninguno. Medido con `htop`
|
||
(musl-estático, **0 `NEEDED`**): bajo la jaula con política mínima **no tocó un solo fichero**
|
||
fuera de sí mismo ⇒ su política de runtime es `ro <su binario>` y nada más. Derivarla del
|
||
build le habría concedido headers y compilador — permisos de más, firmados.
|
||
⇒ **la política granular se MIDE corriendo el binario** (`scripts/harkaq/runtime-policy.sh`:
|
||
corre bajo la jaula y **resta el baseline del lanzador**, que si no se lleva el ruido del `sh`).
|
||
Para un estático la política *no puede* salir de las libs: sólo de correrlo.
|
||
|
||
2. **La cripto ya es "frontera, no tabla" — y por eso las clases encajan sin tocarla.** Lo que la
|
||
`ConcesionCapacidad` firma **no** es `card-core::Permissions` (el struct) sino
|
||
`format::Permisos` = **`u32` bitmask**, dentro de `mensaje_capacidad` =
|
||
`hash(32) || permisos_le(4)` = **36 bytes canónicos, zero-alloc, con espejo `no_std` en Ring 0**
|
||
(`wawa-kernel/src/claves.rs:464`). Meterle una tabla de paths rompería **todas** las firmas y
|
||
contradiría el "capacidad = frontera física, no tabla" que este mismo §3 cita.
|
||
⇒ **las clases de servicio SON los bits del `u32`** (`PERMISO_RED` ya es uno; `dns` sería otro).
|
||
"Sin formato nuevo" se cumple literalmente.
|
||
|
||
**Diseño unificado (los dos niveles coexisten, cada uno donde cabe):**
|
||
|
||
| nivel | qué | dónde | cómo se obtiene |
|
||
|---|---|---|---|
|
||
| **frontera** | clases de servicio (`dns`, `tls-certs`, `random`, `locale`, `syslog`) | `u32` firmado, verificado en Ring 0 | **declaradas por nombre** — no se pueden medir: el build es offline (casper) |
|
||
| **detalle** | paths concretos (fs) | Landlock, userspace | **medidos** corriendo el binario bajo la jaula |
|
||
|
||
El kernel verifica la frontera con 36 bytes; Landlock aplica el detalle. D3 rige en ambos: nada
|
||
se ensancha en silencio.
|
||
|
||
**Reparto de tareas (para no pisarnos):**
|
||
- **Clases de servicio** (Fable 5): la tabla clase→permiso musl, el bit en el `u32`, y el cableado
|
||
con `ConcesionCapacidad`/`arje-absorb --attest-from`. **✅ HECHO (tawasuyu `6eba521c6`,
|
||
2026-07-17)**: `format::PERMISO_{DNS,TLS_CERTS,RANDOM,LOCALE_TZ,SYSLOG}` (bits 8..12 del mismo
|
||
`u32` ⇒ `mensaje_capacidad` intacto, 36 bytes) + `CLASES_SERVICIO` con los nombres de alambre
|
||
(`dns`, `tls-certs`, `random`, `tz`, `syslog` — `tz` convergido con la emisión real de
|
||
runtime-policy.sh, tawasuyu `799e5327e`) y mapeo nombre↔bit para consumir lo que
|
||
emita `runtime-policy.sh`; `arje-attest::detalle_musl(bit)` expande frontera→detalle (paths
|
||
RO/sockets/red) FUERA de lo firmado, y `clases_encendidas(permisos)` es el bucle del aplicador.
|
||
El cableado con `--attest-from` no necesitó ni una línea: la concesión firma el `u32` tal cual,
|
||
los bits nuevos fluyen (test: escalar un bit sin re-firmar ⇒ `FirmaInvalida`). format 57✓
|
||
arje-attest 11✓ wawa-kernel Ring 0 compila✓.
|
||
- **Medición** (Opus 4.8): `runtime-policy.sh`, el harness harkaq (jaula, lector, canario D9) y el
|
||
baseline del lanzador.
|
||
- **Punto de contacto acordado**: `runtime-policy.sh` emitirá también la **clase** detectada, no
|
||
sólo el path — si el binario toca `/etc/resolv.conf` ⇒ propone `dns`; si toca `/etc/ssl/certs/`
|
||
⇒ `tls-certs`. La medición alimenta la tabla; la tabla decide el bit. Ninguno de los dos
|
||
ensancha por su cuenta.
|
||
- **Consumidor esperándonos**: `plan-jaula-juegos.md` F1 («la jaula sellada con pressure-vessel +
|
||
política harkaq del runtime») — un Steam que no puede leer `~/.ssh` sale de este §3.
|
||
|
||
### 4. CVE por grafo
|
||
|
||
`hammer affected CVE-X` exacto (grafo fuente→artefacto→instalado) + frontera mínima de
|
||
rebuild + hydrate para repartir el parche rebuild-free. Donde Debian/Alpine aproximan por
|
||
nombre-versión, hammer responde exacto. Tabla de mesa para adopción seria.
|
||
|
||
**Cruce**: `dataflow` (`DepGraph<K>` no_std: `dirty_cone` = literalmente la frontera
|
||
mínima de rebuild; `topo_order` = la agenda determinista) · `grafo-nav` (cono/verbos).
|
||
|
||
### 5. Sellar el arranque: verity + medida
|
||
|
||
El store content-addressed hace fs-verity/dm-verity casi gratis (el hash YA es la
|
||
identidad del artefacto). EFI-stub propio (ADR 0010) ⇒ firmar la UKI + measured boot con
|
||
TPM. Cierra la cadena firmware→PID1→store; sin esto, la soberanía del build descansa
|
||
sobre un rootfs mutable.
|
||
|
||
**Cruce**: la atestación al arranque de arje ya existe (gate Halt/Degraded/Warn, dry-run
|
||
off-boot, `verify_chain_from_cas` — PLAN-ATESTACION §A); el `expected_hash` del `.swm` ES
|
||
el BLAKE3 que arje atesta. TPM/verity = extender ese gate hacia el firmware, no construir
|
||
la capa.
|
||
|
||
### 6. Matar el trusting-trust: DDC (Diverse Double-Compiling)
|
||
|
||
Con la cadena mrustc cerrada y bit-repro verificada, hammer es de los poquísimos
|
||
proyectos del mundo que puede **ejecutar** DDC: compilar la cadena partiendo de Alpine vs
|
||
partiendo de sí misma y comparar hashes. Un fin de semana de granja, resultado
|
||
publicable. Largo plazo: semilla full-source (stage0/Mes).
|
||
|
||
**Cruce**: el resultado se ancla en el log de §1 (`fork-proof`); `sandokan`
|
||
(Engine/RemoteEngine sobre `brahman-ssh-multiplex`) como supervisor de jobs remotos.
|
||
|
||
### 7. De-Alpinizar el rootfs del sandbox
|
||
|
||
El hallazgo del plugin LTO (binutils de hammer cargando el gcc de Alpine) mostró un canal
|
||
impuro **estructural** mientras el sandbox se apoye en Alpine. Harkaq lo mide; el cierre
|
||
es rootfs de build 100% hammer-built (el patrón de de-Alpinización ya existe).
|
||
|
||
**Cruce**: ninguno directo (trabajo interno de hammer). Disciplina análoga en tawasuyu:
|
||
`scripts/check-shared-cores.sh` (guardián de simetría no_std).
|
||
|
||
### 8. `hammer oci`
|
||
|
||
Emitir imágenes distroless **bit-reproducibles** desde un closure (closure → capas →
|
||
manifest). Vector de adopción realista: la gente consume hammer vía contenedores años
|
||
antes de instalar la distro.
|
||
|
||
**Cruce**: `format`/`foreign-fs` para capas dedup por contenido · `card-net` como
|
||
distribución por hash alternativa al registry.
|
||
|
||
### 9. Updates diferenciales content-defined
|
||
|
||
Chunking estilo casync sobre el store; el Merkle-DAG de H3 (SDD 15) es media
|
||
implementación. Complementa hydrate para metal/USB.
|
||
|
||
**Cruce**: `reconcile` (Meyer/Willow, el candidato canónico) · chunking de `foreign-fs` ·
|
||
`crdt::wire` (anti-entropy agnóstico de transporte) · transporte `card-net` /
|
||
Akasha-over-Ether.
|
||
|
||
### 10. Bucle agéntico con juez mecánico
|
||
|
||
Agente propone receta → harkaq da veredicto → granja reproduce ×2 → catálogo acepta. Ya
|
||
demostrado a mano con zlib (Impuro→Hermetico ×3 fases guiado sólo por harkaq). LA tesis
|
||
AI-nativa: **el catálogo se cultiva solo porque el juez es mecánico**. Sin juez, recetas
|
||
LLM son deuda; con él, son cosecha.
|
||
|
||
**Cruce**: `willay-checkpoint` (`Propuesta` = "lo que la IA observó/propuso + veredicto
|
||
del simulador" — mapea 1:1 a receta+veredicto-harkaq) · `willay-hilo` (caja negra forense
|
||
por-device sobre fork-proof ⇒ bucle agéntico **no repudiable**) · `atipay` (catálogo
|
||
determinista de capacidades → plan tool-use) · `sandokan-journal` (replay del plano de
|
||
control) · `rag-motor` (contrato RAG con citación, alimentado por why-differs).
|
||
PLAN-ATESTACION ya enuncia el ciclo: "IA propone → humano commitea (hammer) → init
|
||
atesta (arje)".
|
||
|
||
## 2. Qué NO priorizar
|
||
|
||
- **Solver SAT de versiones**: el grafo es curado, no lo necesita.
|
||
- **Multi-arch**: costo enorme; esperar demanda (la historia RISC-V puede reabrirlo).
|
||
- **Config declarativa estilo NixOS**: cancha ajena; si acaso, `allichay` ya es ese
|
||
vocabulario en tawasuyu.
|
||
|
||
## 3. Nota CRDT
|
||
|
||
El cierre CRDT en hammer = journal/catálogo replicado granja↔laptop sin git como bus
|
||
(anti-entropy `crdt::wire` sobre el LwwMap de H2). El transporte real vive en
|
||
PLAN-OS-CRDT §E3 (tawasuyu) — no duplicar. Estado real de ese plan a 2026-07-15: **E2
|
||
(`fork-proof`) y E3c (`BudgetRouter`) ya son código con tests; E1 (MonotonicLog en el
|
||
kernel wawa) sigue siendo plan** — la parte que hammer necesita ya existe.
|
||
|
||
## 4. Caveats del cruce
|
||
|
||
- `sheafsync` es scaffold M0 y su teoría de haces fracasó honestamente (PLAN-OS-CRDT §0);
|
||
reutilizar `escrow`/`BudgetRouter`/`fencing`, no la cohomología.
|
||
- `willay` es v1 en construcción; `tejido`/`willay-rag` arrastran libp2p/tokio/iniy — no
|
||
importarlos al build hermético. Usar el patrón ya validado con hammerd: contrato wire
|
||
por bytes, sin dependencia de crate (PLAN-ATESTACION §B.2).
|
||
|
||
## 5. Elegidos (ventaja competitiva por unidad de esfuerzo)
|
||
|
||
1. **Consenso de reconstrucción** — nadie más puede; `fork-proof`+`umbral` lo bajan de
|
||
"proyecto" a "wiring sobre la granja". Le da razón de existir al log de transparencia
|
||
de SDD 09 §4.
|
||
2. **why-differs** — multiplicador de todo lo demás (granja Y agente); `format`+`reconcile`
|
||
regalan el esqueleto.
|