🛡️ sandbox-labs GitHub ↗

CM-11 · Finanzas abiertas y consentimiento#

En una frase, para cualquiera: das permiso a una aplicación para ver los datos de tu banco. La pregunta que casi nadie hace es: ¿qué datos, por cuánto tiempo, y cómo se lo quitas?

Estado real: 🟠 prototype — hay código y escenarios que se ejecutan, sin verificación en un entorno real · Módulo: crates/sandbox-markets/src/cases/consent.rs

Participantes, certificados, APIs y datos simulados. Sin credenciales reales ni datos personales reales. No es una autorización regulatoria.

Por qué se realiza este caso#

Las finanzas abiertas se apoyan enteramente en el consentimiento: es lo único que separa «un servicio que te ayuda» de «un tercero con acceso permanente a tu vida financiera».

Y el consentimiento se rompe de formas discretas:

FalloQué significa
Consentimiento vencidoSe sigue consultando después de la fecha
Alcance incorrectoDiste permiso para saldos y leen movimientos
Consulta excesivaDiez mil consultas diarias para un servicio que necesita una
Token revocadoLo quitaste y sigue funcionando
DuplicaciónEl mismo consentimiento registrado dos veces, y revocas uno
IndisponibilidadLa API cae y el servicio finge tener datos frescos
FiltraciónLos datos llegan a un cuarto que nunca estuvo en el trato

La idea que enseña, y que ningún otro caso enseña#

El consentimiento es un objeto con ciclo de vida, no una casilla. Nace con un alcance y una fecha, se puede renovar, se puede revocar, y cada consulta tiene que comprobarlo en el momento. Si el sistema solo lo comprueba al conceder, la revocación no significa nada.

Y de ahí la trazabilidad: la persona tiene que poder ver quién consultó qué y cuándo, sin excepción.

Casos de uso reales#

Cómo funcionará#

flowchart LR
  P["🏢 Participante"] --> RG["📝 Registro<br/>+ certificado simulado"]
  U["👤 Usuario"] --> C["✅ Consentimiento<br/>alcance + vigencia"]
  RG & C --> A["🔐 Autenticación"]
  A --> API["🔌 APIs simuladas"]
  API --> V{"⚖️ Por CADA consulta:<br/>¿vigente? ¿en alcance?<br/>¿no revocado?"}
  V -- no --> X["🚫 Rechazada y registrada"]
  V -- sí --> D["📊 Datos"]
  D & X --> T["🗂️ Trazabilidad<br/>visible para el usuario"]
  U --> RV["🔴 Revocación"]
  RV --> V
stateDiagram-v2
  [*] --> Solicitado
  Solicitado --> Vigente: usuario concede
  Solicitado --> Rechazado: usuario niega
  Vigente --> Renovado: antes de vencer
  Renovado --> Vigente
  Vigente --> Vencido: llega la fecha
  Vigente --> Revocado: usuario retira
  Vencido --> [*]
  Revocado --> [*]
  Rechazado --> [*]

Esquemas#

{
  "consent": {
    "id": "cons-001",
    "user": "usuario-sintetico-1",
    "participant": "app-sim-1",
    "scope": ["accounts:balances"],
    "grantedAt": "2026-08-07T00:00:00Z",
    "expiresAt": "2026-11-07T00:00:00Z",
    "status": "vigente"
  }
}
{
  "findings": [
    { "kind": "ExpiredConsent", "consent": "cons-001", "queriedAt": "2026-12-01T10:00:00Z" },
    { "kind": "ScopeViolation", "consent": "cons-002", "requested": "accounts:transactions", "granted": ["accounts:balances"] },
    { "kind": "ExcessiveQuerying", "participant": "app-sim-2", "queriesPerDay": 9840, "expected": 24 }
  ]
}

Software necesario#

ComponentePara qué
Rust 1.75+Ciclo de vida del consentimiento y APIs simuladas
Node.js 20+ / pnpm 9+Pantalla de consentimiento y trazabilidad para el usuario

Sin jaula ni Linux. Los certificados son simulados y generados en local; el proyecto no almacena credenciales reales en ningún sitio, tampoco en fixtures.

Instalación#

cargo build --release

Procesos que se crearán#

sandboxctl markets consent --scenario token-revocado
  │
  └─ un proceso determinista, sin red
      ├─ reloj simulado (los consentimientos duran meses)
      ├─ APIs simuladas en proceso
      └─ registro append-only de cada consulta

Reloj simulado y sin red: se pueden probar tres meses de vigencia en milisegundos, y sin llamar a ningún sistema externo.

Tiempo de carga estimado#

OperaciónCoste esperado
Conceder o revocar un consentimiento< 1 ms
Comprobar una consulta contra el consentimientomicrosegundos
Simular tres meses de consultassegundos

Qué hace falta para construirlo#

  1. Modelo de consentimiento con alcance, vigencia y estado.
  2. Comprobación en cada consulta, no solo al conceder.
  3. Revocación efectiva e inmediata, con escenario que lo demuestre.
  4. Registro de trazabilidad visible para el usuario.
  5. Detección de consulta excesiva, alcance incorrecto y duplicación.
  6. Escenario de indisponibilidad: la API cae y el sistema no finge.

Si algo falla#

El caso ya tiene código y escenarios que se ejecutan. Lo que sigue son sus fallos con la causa y la salida:

SituaciónCausaCómo se resuelve
Una consulta funciona después de revocarEl fallo más grave del casoEl consentimiento se comprueba en cada consulta, no solo al conceder. Si se comprueba únicamente al conceder, revocar no significa nada
ScopeViolationEl participante pide más de lo que se le concedióSe rechaza y se registra. No se amplía el alcance sin volver a pedírselo al usuario
ExcessiveQueryingMiles de consultas para un servicio que necesita unas pocasPuede ser un fallo del participante o una recolección encubierta. Se limita y se le pide explicación
La API simulada no respondeEscenario de indisponibilidadEl sistema no finge tener datos frescos: devuelve el fallo. Servir datos viejos como actuales es peor que no servir nada
El usuario no sabe quién consultó sus datosFalta trazabilidadCada consulta queda registrada y es visible para el usuario, no solo para auditoría interna

Los fallos que afectan a cualquier caso —la compilación, el catálogo, la evidencia— están resueltos uno a uno en Cuando algo falla.

Esta familia no necesita aislamiento del sistema: no ejecuta código ajeno, sino reglas de negocio deterministas. Por eso casi ningún fallo suyo viene del entorno, y casi todos vienen de los datos.

Cómo se comprueba#

cargo run -p sandboxctl -- markets check --case CM-11

Ejecuta los escenarios de este caso y compara cada uno con lo que declara de antemano que debe salir. Corre en cada commit: si el caso deja de detectar lo que dice detectar, la integración continua se pone roja.

cargo test -p sandbox-markets consent

Los invariantes del módulo, incluidos los que ningún escenario de arriba cubre.

Sigue en prototype, no en functional. Los escenarios se ejecutan y pasan, pero el caso no emite evidencia firmada por ejecución ni se ha usado contra datos que no sean los suyos. La regla completa está en el ROADMAP.

Ver también: Catálogo completo · CM-19 · fraude · Caso 08 · agentes de IA