Unifica todo el proyecto tras adapter::SovereignAccount, con las precondiciones
del contrato §H en el centro:
- SubstrateCapabilities + AdapterError: open() REHÚSA (NoDurability /
NoDeviceIdentity) si el sustrato no cumple, en vez de prometer seguridad que
no tiene. La negativa es parte del diseño.
- Compone las piezas: EscrowState (presupuesto con procedencia, T10a) + WAL
durable por dispositivo (T11b) + ruteo edge-local por el nervio (T9b/T10b) +
época de fencing (T11c).
- API: spend (local | rebalanceo | Rejected{spendable}, fail-safe), available,
value/invariant_holds (certificado value≥floor), recover (desde WAL),
reboot (época), sync (Ok | CloneDetected como ALARMA, no recuperación).
M4.md: contrato congelado en tabla (cláusula → cómo se cumple → test), la API
pública, qué compone cada garantía, y las fronteras dichas (no previene clon;
no hay disponibilidad ilimitada bajo partición; no es motor de replicación).
Nerve ahora deriva Clone. 81 tests, clippy limpio.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.3 KiB
4.3 KiB
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áusula | Cómo se cumple | Respaldo |
|---|---|---|
Requiere WAL durable de spent por dispositivo |
open rehúsa con NoDurability si caps.durable_per_device == false |
rehusa_sin_durabilidad |
| Requiere identidad = conjunto de dispositivos | open rehúsa con NoDeviceIdentity si caps.identity_as_devices == false |
rehusa_sin_identidad_por_dispositivo |
| Garantiza seguridad coordination-free del invariante | value() ≥ floor en toda ejecución (Σ b0 conservado, gastos guardados) |
certificado_gastando_todo_el_slack |
| Acota y detecta (no previene) el clon | sync devuelve CloneDetected; el daño ya ocurrió, es alarma (BOUNDARY.md) |
clon_detectado_en_sync |
| Limita la disponibilidad bajo partición | spend devuelve Rejected { spendable }; nunca sobregira ni cuelga |
particion_sin_ruta_es_fail_safe |
| Rehúsa en vez de prometer de más | open devuelve Err(AdapterError), no una cuenta insegura |
ambos 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)
- Presupuesto con procedencia —
escrow::EscrowState(T10a): crash-safe y merge-safe;Σ avail = Σ b0 − Σ spentinvariante a las transferencias. - Durabilidad —
durable::WriteAheadLog(T11b): elspendpersiste al WAL antes del ack;recoverrestaura≥ último ack. Sin ella,openrehúsa. - Ruteo edge-local —
nerve+ transferenciasgrant(T9b/T10b):spendrebalancea de vecinas con excedente, transaccional (o rechaza, no cuelga). - Réplica-por-dispositivo —
escrow::Identity(T11a): la cuenta ES la identidad; cada dispositivo, una celda single-writer. - Fencing / clon — época device-local +
sync→MergeOutcome::CloneDetected(T11c). Detalle del daño acotado a una celda enfencing.rs.
Lo que M4 NO promete (las fronteras, dichas)
- No previene el doble gasto por clon. Lo acota (una celda) y lo delata.
CloneDetectedes una alarma, no una recuperación: el dinero ya salió, la compensación vive en la capa de aplicación y puede fracasar (BOUNDARY.md). - No hay disponibilidad ilimitada bajo partición. Cada dispositivo se limita a
su presupuesto local;
diffuse(ruteo proactivo,router.rs) lo mitiga, no lo elimina (AVAILABILITY.md). CAP: safety > availability. - No es un motor de replicación. No hay red real ni wire protocol: es la capa de decisión coordination-free que el sustrato soberano invoca. La persistencia y el transporte los provee Tawasuyu/Hammer; el adaptador exige que la persistencia sea durable-por-dispositivo, o rehúsa.
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.