🛡️ sandbox-labs GitHub ↗

CM-00 · Entrada al sandbox regulatorio#

En una frase, para cualquiera: antes de dejar que una empresa nueva maneje el dinero de otras personas, alguien tiene que mirar qué hace exactamente, qué puede salir mal y quién responde. Este caso es esa mirada, convertida en un procedimiento que se puede repetir.

Estado real: 🔴 plannedno hay código todavía · Carpeta prevista: domains/capital-markets/cases/00-regulatory-entry

Sin dinero real, sin valores reales, sin credenciales reales y sin conectividad de producción. Este simulador no es una autorización regulatoria de la CMF ni de ninguna otra autoridad, y nada de lo que produzca es una recomendación de inversión.

Por qué se realiza este caso#

Es la puerta de entrada al resto de la familia. Los otros veinte casos prueban una actividad concreta; este decide qué actividad es y, por tanto, qué reglas le aplican.

La pregunta que responde no es «¿es buena esta empresa?». Es más precisa y más incómoda: ¿de quién es el dinero en cada momento, y qué pasa si la empresa desaparece mañana?

Casi todos los problemas regulatorios serios empiezan por una clasificación mal hecha:

Cómo se presentaLo que en realidad es
«Solo conectamos inversionistas con proyectos»Intermediación, si toca el dinero
«Guardamos el saldo para tu comodidad»Custodia, con todo lo que implica
«Recomendamos según tu perfil»Asesoría, con deber de idoneidad
«Es una plataforma tecnológica»Depende enteramente de qué hace con los fondos

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

Clasificar es decidir. El resultado no es un informe: es una de tres resoluciones —aprobación, aprobación condicionada o rechazo— con los límites y los controles asociados escritos, de forma que los demás casos puedan ejecutarse dentro de esos límites.

Una aprobación condicionada es la salida más interesante: dice «sí, pero con tope de volumen, sin custodiar efectivo y reportando cada mes». Eso es política como código, no una opinión.

Casos de uso reales#

Cómo funcionará#

flowchart LR
  F["📝 Formulario<br/>de postulación"] --> C["🏷️ Clasificación<br/>de servicios"]
  C --> R["⚠️ Identificación<br/>de riesgos"]
  R --> L["📏 Límites propuestos"]
  L --> E["⚖️ Evaluación<br/>de controles"]
  E --> D{"Resolución"}
  D --> A1["✅ Aprobación"]
  D --> A2["🟡 Aprobación condicionada<br/>con límites y obligaciones"]
  D --> A3["🚫 Rechazo motivado"]
  A1 & A2 & A3 --> EV["🧾 Evidencia firmada"]
flowchart TB
  A["¿Qué hace la empresa<br/>con el dinero?"] --> B{"¿Lo custodia?"}
  B -- sí --> B1["→ CM-03 custodia obligatoria<br/>segregación, conciliación"]
  B -- no --> C{"¿Ejecuta órdenes?"}
  C -- sí --> C1["→ CM-02 y CM-05<br/>mejor ejecución, conflictos"]
  C -- no --> D{"¿Recomienda?"}
  D -- sí --> D1["→ CM-07 idoneidad"]
  D -- no --> E["Servicio auxiliar:<br/>régimen más ligero"]

Qué debe incluir la postulación#

BloqueQué se preguntaPor qué importa
Servicios ofrecidosQué hace exactamenteDetermina el régimen entero
BeneficiariosA quién sirveUn inversionista no calificado exige más protección
ParticipantesQuién más intervieneCada uno añade un punto de fallo
Flujos de dineroPor dónde pasa cada pesoLa pregunta central
InstrumentosQué se negociaDetermina riesgo y liquidez
ProveedoresDe quién se dependeConcentración y continuidad
GobiernoQuién decide y quién respondeSin esto no hay a quién exigir
CiberseguridadCómo se protegeVer la familia técnica de este mismo repositorio
ContinuidadQué pasa si algo caeCM-14
ReclamosCómo se atiende al que pierde dineroLo primero que se descuida
Salida ordenadaCómo se cierra devolviendo todoCM-13. Se pregunta al entrar, no al salir

Esa última fila es la que más sorprende y la más importante: se exige el plan de cierre antes de abrir, porque quien no sabe explicar cómo devolvería el dinero probablemente no ha separado bien de quién es.

Esquemas#

Postulación#

{
  "applicant": "Fintech de ejemplo SpA",
  "jurisdiction": "CL",
  "services": ["custody", "order-routing"],
  "beneficiaries": ["retail"],
  "moneyFlows": [
    { "from": "cliente", "to": "cuenta segregada", "custodian": "banco simulado" }
  ],
  "instruments": ["acciones-simuladas"],
  "governance": { "board": true, "complianceOfficer": true },
  "windDownPlan": { "documented": true, "maxDays": 30 }
}

Resolución#

{
  "outcome": "conditional",
  "classification": ["custody", "order-routing"],
  "risks": [
    { "id": "R-01", "risk": "mezcla de activos de clientes con los propios", "severity": "alta", "control": "CM-03 conciliación diaria" }
  ],
  "limits": { "maxClientFunds": { "minorUnits": 50000000000, "currency": "CLP" }, "maxClients": 500 },
  "obligations": ["reporte mensual CM-12", "plan de salida probado CM-13"],
  "rationale": "…",
  "notAnAuthorization": true
}

ninguna salida de este simulador puede presentarse como una autorización.

Software necesario#

ComponentePara qué¿Obligatorio?
Rust 1.75+El motor de clasificación y las reglas como código
Node.js 20+ y pnpm 9+El formulario en el panel de controlSolo para la interfaz
bubblewrapNo hace falta: no se ejecuta código no confiableNo

Esta familia no necesita aislamiento del sistema: lo que se prueba son reglas de negocio, no código ajeno. Corre en cualquier sistema con Rust, Windows incluido.

Instalación#

cargo build --release
cargo run -p sandboxctl -- markets --help

Procesos que se crearán#

sandboxctl markets entry --application postulacion.json
  │
  └─ un solo proceso           ← determinista, sin red, sin estado externo
      ├─ validación del esquema
      ├─ clasificación
      ├─ evaluación de controles
      └─ evidencia firmada

Un solo proceso y sin red por diseño: una evaluación regulatoria tiene que poder reproducirse años después y dar exactamente el mismo resultado.

Tiempo de carga estimado#

OperaciónCoste esperado
Validar la postulación< 10 ms
Clasificar y evaluar< 50 ms
Firmar la evidencia< 1 ms

Qué hace falta para construirlo#

  1. Esquema de postulación, validado en cada commit.
  2. Motor de clasificación con reglas versionadas y con fecha de vigencia —**las

reglas regulatorias cambian y no se codifican como verdad permanente**.

  1. Catálogo de riesgos con el control que los mitiga y el caso que lo prueba.
  2. Las tres resoluciones, con límites que los demás casos puedan leer.
  3. Evidencia firmada de cada evaluación.

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
La resolución sale rejected y el solicitante no entiende por quéLa clasificación detectó una actividad que el modelo de negocio no declarabaEl campo rationale cita la regla y el dato de la postulación que la activó. Se corrige la postulación o se corrige el modelo de negocio, no la regla
La misma postulación da resultados distintos en dos fechasUna regla cambió de versión entre mediasEs correcto y está previsto: las reglas llevan fecha de vigencia. La resolución guarda qué versión la evaluó, para poder reconstruirla años después
El solicitante no sabe describir sus flujos de dineroSuele significar que no ha decidido de quién es el dinero en cada momentoEs el hallazgo más útil del caso. Se responde con una aprobación condicionada que exija resolverlo antes de operar
Falta el plan de salida ordenadaSe pide al entrar, no al salirNo se aprueba sin él. Quien no sabe explicar cómo devolvería el dinero probablemente no lo ha separado bien
Alguien presenta la resolución como una autorizaciónMalentendido graveToda salida lleva notAnAuthorization: true en el esquema, y es obligatorio. Este simulador no autoriza nada

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-00

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 regulatory_entry

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-13 · salida ordenada · CM-03 · custodia