tawasuyu

tawasuyu/hifas

Motor en Rust para decidir, con demostración y no a ojo, cuándo un conjunto de réplicas local-first puede operar sin coordinación y cuándo no — y, cuando la respuesta es "sí, dentro de límites", proveer el mecanismo que lo garantiza.

Rust 11Markdown 1TOML 187 Definitions

⎇ 703ae7023578fabc109ef038063c7351fb3b9f52 M4.md Markdown · 70 lines · 4.3 KB History raw

M4: adaptador soberano con API congelada y contrato honesto 703ae7023 · Sergio ·

1# M4 — el adaptador soberano (API congelada)
2
3El puente a los sistemas soberanos (Tawasuyu/Hammer). Unifica todo el proyecto
4tras una API estable, `adapter::SovereignAccount`, con precondiciones honestas. No
5se declara completo hasta que el contrato de abajo se sostiene bajo los tests que
6lo respaldan (`adapter::tests`).
7
8## El contrato (§H de T9/T10/T11) — escrito en piedra
9
10| Cláusula | Cómo se cumple | Respaldo |
11|---|---|---|
12| **Requiere** WAL durable de `spent` por dispositivo | `open` rehúsa con `NoDurability` si `caps.durable_per_device == false` | `rehusa_sin_durabilidad` |
13| **Requiere** identidad = conjunto de dispositivos | `open` rehúsa con `NoDeviceIdentity` si `caps.identity_as_devices == false` | `rehusa_sin_identidad_por_dispositivo` |
14| **Garantiza** seguridad coordination-free del invariante | `value() ≥ floor` en toda ejecución (Σ b0 conservado, gastos guardados) | `certificado_gastando_todo_el_slack` |
15| **Acota y detecta** (no previene) el clon | `sync` devuelve `CloneDetected`; el daño ya ocurrió, es **alarma** (`BOUNDARY.md`) | `clon_detectado_en_sync` |
16| **Limita** la disponibilidad bajo partición | `spend` devuelve `Rejected { spendable }`; nunca sobregira ni cuelga | `particion_sin_ruta_es_fail_safe` |
17| **Rehúsa** en vez de prometer de más | `open` devuelve `Err(AdapterError)`, no una cuenta insegura | ambos `rehusa_*` |
18
19## La API pública congelada
20
21```rust
22SubstrateCapabilities { durable_per_device, identity_as_devices }
23AdapterError { NoDurability, NoDeviceIdentity, InvalidSplit }
24
25SovereignAccount::open(caps, inv, weights, edges) -> Result<Self, AdapterError>
26    // rehúsa si el sustrato no cumple; reparte el slack en celdas-dispositivo.
27
28  .spend(device, amount) -> SpendOutcome        // Local | rebalanceo | Rejected{spendable}
29  .available(device) -> i64                     // presupuesto local
30  .total_available() -> i64                     // Σ b0 − Σ spent
31  .value() -> i64                               // inicial − Σ spent (≥ floor: certificado)
32  .invariant_holds() -> bool
33  .recover(device)                              // restaura spent desde el WAL tras crash
34  .reboot(device) -> u64                        // incrementa la época device-local (fencing)
35  .sync(&other) -> MergeOutcome                 // Ok | CloneDetected (alarma)
36```
37
38## Qué compone (y de dónde sale cada garantía)
39
40- **Presupuesto con procedencia** — `escrow::EscrowState` (T10a): crash-safe y
41  merge-safe; `Σ avail = Σ b0 − Σ spent` invariante a las transferencias.
42- **Durabilidad** — `durable::WriteAheadLog` (T11b): el `spend` persiste al WAL
43  **antes** del ack; `recover` restaura `≥ último ack`. Sin ella, `open` rehúsa.
44- **Ruteo edge-local** — `nerve` + transferencias `grant` (T9b/T10b): `spend`
45  rebalancea de vecinas con excedente, transaccional (o rechaza, no cuelga).
46- **Réplica-por-dispositivo** — `escrow::Identity` (T11a): la cuenta ES la
47  identidad; cada dispositivo, una celda single-writer.
48- **Fencing / clon** — época device-local + `sync` → `MergeOutcome::CloneDetected`
49  (T11c). Detalle del daño acotado a una celda en `fencing.rs`.
50
51## Lo que M4 NO promete (las fronteras, dichas)
52
53- **No previene el doble gasto por clon.** Lo acota (una celda) y lo delata.
54  `CloneDetected` es una **alarma**, no una recuperación: el dinero ya salió, la
55  compensación vive en la capa de aplicación y puede fracasar (`BOUNDARY.md`).
56- **No hay disponibilidad ilimitada bajo partición.** Cada dispositivo se limita a
57  su presupuesto local; `diffuse` (ruteo proactivo, `router.rs`) lo mitiga, no lo
58  elimina (`AVAILABILITY.md`). CAP: safety > availability.
59- **No es un motor de replicación.** No hay red real ni wire protocol: es la capa
60  de decisión coordination-free que el sustrato soberano invoca. La persistencia y
61  el transporte los provee Tawasuyu/Hammer; el adaptador **exige** que la
62  persistencia sea durable-por-dispositivo, o rehúsa.
63
64## El enunciado, una última vez
65
66**Seguridad coordination-free módulo un supuesto físico nombrado:** un escritor
67durable por celda. Bajo él, el certificado dinámico de T10 aplica sin coordinación.
68Roto (clon), el daño está acotado a una celda por clon no detectado y se detecta al
69reconectar. No "seguro pase lo que pase" — seguro salvo esta condición física, con
70el costo exacto de romperla escrito en `BOUNDARY.md` y `AVAILABILITY.md`.

M4.md

M4 — el adaptador soberano (API congelada)

El puente a los sistemas soberanos (Tawasuyu/Hammer). Unifica todo el proyecto tras una API estable, adapter::SovereignAccount, con precondiciones honestas. No se declara completo hasta que el contrato de abajo se sostiene bajo los tests que lo respaldan (adapter::tests).

El contrato (§H de T9/T10/T11) — escrito en piedra

CláusulaCómo se cumpleRespaldo
Requiere WAL durable de spent por dispositivoopen rehúsa con NoDurability si caps.durable_per_device == falserehusa_sin_durabilidad
Requiere identidad = conjunto de dispositivosopen rehúsa con NoDeviceIdentity si caps.identity_as_devices == falserehusa_sin_identidad_por_dispositivo
Garantiza seguridad coordination-free del invariantevalue() ≥ floor en toda ejecución (Σ b0 conservado, gastos guardados)certificado_gastando_todo_el_slack
Acota y detecta (no previene) el clonsync devuelve CloneDetected; el daño ya ocurrió, es alarma (BOUNDARY.md)clon_detectado_en_sync
Limita la disponibilidad bajo particiónspend devuelve Rejected { spendable }; nunca sobregira ni cuelgaparticion_sin_ruta_es_fail_safe
Rehúsa en vez de prometer de másopen devuelve Err(AdapterError), no una cuenta inseguraambos rehusa_*

La API pública congelada

SubstrateCapabilities { durable_per_device, identity_as_devices }
AdapterError { NoDurability, NoDeviceIdentity, InvalidSplit }

SovereignAccount::open(caps, inv, weights, edges) -> Result<Self, AdapterError>
    // rehúsa si el sustrato no cumple; reparte el slack en celdas-dispositivo.

  .spend(device, amount) -> SpendOutcome        // Local | rebalanceo | Rejected{spendable}
  .available(device) -> i64                     // presupuesto local
  .total_available() -> i64                     // Σ b0 − Σ spent
  .value() -> i64                               // inicial − Σ spent (≥ floor: certificado)
  .invariant_holds() -> bool
  .recover(device)                              // restaura spent desde el WAL tras crash
  .reboot(device) -> u64                        // incrementa la época device-local (fencing)
  .sync(&other) -> MergeOutcome                 // Ok | CloneDetected (alarma)

Qué compone (y de dónde sale cada garantía)

Lo que M4 NO promete (las fronteras, dichas)

El enunciado, una última vez

Seguridad coordination-free módulo un supuesto físico nombrado: un escritor durable por celda. Bajo él, el certificado dinámico de T10 aplica sin coordinación. Roto (clon), el daño está acotado a una celda por clon no detectado y se detecta al reconectar. No "seguro pase lo que pase" — seguro salvo esta condición física, con el costo exacto de romperla escrito en BOUNDARY.md y AVAILABILITY.md.