@fractalai/decision-ingest
v0.1.0
Published
Zero-dependency Node SDK that turns the decision logs your system already produces into third-party-verifiable receipts — post-quantum (Dilithium-2), Black-Box chained, optionally anchored on-chain (VAID-1). Honest scope: proves INTEGRITY + non-repudiatio
Maintainers
Readme
FractalAI Decision Ingest Connector
El eslabón que faltaba: toma los logs de decisión que tu sistema ya produce y los convierte en recibos verificables por terceros — sin custodiar tus datos, sin cambiar tu stack. Es código de ejemplo / SDK ($0, cero dependencias). No toca producción.
log del cliente ─▶ conector ─▶ recibo verificable por terceros
(tu decisión) (este SDK) (Dilithium-2 + Black-Box + ancla on-chain)Cada decisión se firma con Dilithium-2 (NIST FIPS 204, post-cuántico) y se encadena a la anterior (append-only, a prueba de manipulación). Cualquiera puede re-verificar el veredicto de la cadena después — sin confiar en el operador.
Qué prueba (y qué NO) — honestidad primero
El recibo prueba INTEGRIDAD + NO-REPUDIO + FRESCURA + ORDEN de lo que fue DECLARADO: estos bytes exactos fueron sellados por la clave Dilithium-2 de FractalAI en ese momento y encadenados en el Black Box del agente.
NO prueba que la decisión sea correcta, justa o completa. Un operador todavía puede
omitir decisiones; la cadena hace detectable una edición posterior, no una omisión en
origen. Dilithium-2 resiste ataques clásicos y cuánticos conocidos (NIST FIPS 204) — no es
"irrompible". Este es el mismo honest_scope que devuelven los endpoints.
Instalación
Paquete: @fractalai/decision-ingest — ESM, cero dependencias, Node >= 18
(usa fetch nativo). Se puede usar de dos formas:
# a) Como paquete instalado (cuando esté publicado / vía tarball local)
npm install @fractalai/decision-ingest
# b) Sin instalar nada: copia la carpeta connectors/ y usa los .mjs directamenteImport según la forma:
// a) instalado como paquete
import { ingestDecision, verifyLedger } from '@fractalai/decision-ingest';
import { sealComplianceEvent } from '@fractalai/decision-ingest/adapters/casp-compliance';
import { sealCuratorChange } from '@fractalai/decision-ingest/adapters/defi-curator';
// b) por ruta de archivo (sin instalar)
import { ingestDecision, verifyLedger } from './connectors/decision-ingest.mjs';Scripts del paquete (desde connectors/):
npm run check # node --check de los 4 .mjs (sintaxis)
npm test # suite offline con node --test (mock de fetch, sin red)
npm run demo # prueba EN VIVO contra el endpoint GRATIS (requiere red)También expone el bin fractalai-decision-demo (= la demo en vivo).
Integración en 10 minutos
Requisito: Node >= 18 (usa fetch nativo). Sin dependencias.
import { ingestDecision, verifyLedger } from '@fractalai/decision-ingest';
// 1) Sella una decisión que tu sistema ya tomó.
const receipt = await ingestDecision({
agentId: 'risk-desk:vault-0xBEEF', // quién decide (agrupa su ledger encadenado)
input: { question: '¿Subir supply cap?', utilization: 0.92 }, // contexto (se hashea)
output: { decision: 'approved', newCap: '15000000' }, // decisión (se hashea)
modelId: 'gauntlet-risk-v3',
modelVersion: '2026-08-08',
});
console.log(receipt.entry_hash, receipt.signature);
// 2) Un tercero (LP, auditor, regulador) re-verifica la cadena completa.
const { verdict } = await verifyLedger('risk-desk:vault-0xBEEF');
// verdict => { valid: true, entries: N, reason: 'all N entries signed (...) and chained' }input y output pueden ser strings u objetos. Los objetos se serializan de forma
determinista (claves ordenadas) para que el hash sea estable. Solo el sha256 sale de tu
sistema — el input/output crudo nunca se almacena en FractalAI.
Configuración (variables de entorno)
| Variable | Default | Descripción |
|-------------------|-----------------------------|-------------|
| BASE_URL | https://fractalai.net.co | Origen de la API de FractalAI. |
| X_PAYMENT | (vacío) | Prueba de pago x402 opcional para la ruta PAGA: un 0x… txHash USDC en Base, o un header X-PAYMENT en base64. Si está vacío, se usa la ruta GRATIS. |
| HTTP_TIMEOUT_MS | 20000 | Timeout por request (ms). |
También puedes pasar baseUrl, timeout, mode, payment, agentId por-llamada en
opts (segundo argumento de ingestDecision y de los adaptadores).
Dos rutas de sellado
| Ruta | Endpoint | Pago | Qué añade |
|--------|-----------------------------------|-----------|-----------|
| FREE | POST /api/blackbox | ninguno | Firma Dilithium-2 + encadenado (Black Box, a prueba de manipulación). |
| PAID | POST /api/x402/attest-decision | $0.05 x402 | Todo lo anterior + ancla on-chain VAID-1 (recibo attestation_hash + permalink). |
ingestDecision(..., { mode }) acepta 'auto' (default: PAGA si hay payment/X_PAYMENT,
si no GRATIS), 'free' o 'paid'. En modo PAGA sin pago válido el endpoint responde 402
y el conector lanza IngestError con status: 402 y el desafío accepts[] en .body
(cómo pagar y reintentar — txHash USDC en Base o autorización EIP-3009 gasless).
Adaptadores de ejemplo (formatos reales de cliente)
Mapean el evento nativo del cliente a ingestDecision. Cópialos y ajusta el mapeo a tu
esquema.
B1 — Curador / Risk-Manager DeFi (adapters/defi-curator.mjs)
Un cambio de parámetro/allocation (estilo Morpho/Gauntlet) → decisión sellada.
import { sealCuratorChange } from './connectors/adapters/defi-curator.mjs';
await sealCuratorChange({
vault: '0xBEEF... / Steakhouse USDC',
curator: 'gauntlet',
param: 'supplyCap',
market: 'wstETH/USDC',
oldValue: '10000000',
newValue: '15000000',
rationale: 'Utilización 92%, colateral sano, oráculo nominal.',
ts: '2026-08-08T12:00:00Z',
txHash: '0xabc...', // opcional: tx que ejecutó el cambio
});
// => recibo verificable. agentId por defecto: defi-curator:<curator>:<vault>Caso de uso: cuando un mercado se rompe, LPs/aseguradoras/reguladores preguntan quién cambió el parámetro, a qué, cuándo y por qué — y si el log no fue editado después. El recibo lo prueba (del registro declarado).
B4 — Compliance CASP MiCA/DORA (adapters/casp-compliance.mjs)
Un evento de compliance (KYC/AML/orden) → decisión sellada.
import { sealComplianceEvent } from './connectors/adapters/casp-compliance.mjs';
await sealComplianceEvent({
type: 'aml_alert', // kyc_approval | aml_alert | aml_disposition | order | sanctions_screen | ...
subject: 'customer-ref-8891', // referencia pseudonimizada — NO PII cruda
decision: 'escalated',
rulesetVersion: 'aml-2026.2',
officer: 'auto-screening',
reason: 'Patrón de structuring en 6 depósitos.',
caseId: 'CASE-2026-0042',
ts: '2026-08-08T12:00:00Z',
}, { entity: 'acme-casp' });
// => recibo verificable. agentId por defecto: casp-compliance:<entity>:<type>Caso de uso: MiCA (record-keeping) y DORA (Art.9/Art.17, registros ICT + logging de incidentes) exigen registros a prueba de manipulación de decisiones de compliance, entregables a una autoridad competente y re-verificables de forma independiente.
Privacidad: pasa siempre una referencia pseudonimizada como
subject, nunca PII cruda. Aun así solo susha256abandona tu sistema.
Prueba en vivo
node connectors/examples/demo.mjsSella tres decisiones de ejemplo (raw + adaptador B1 + adaptador B4) contra el endpoint
GRATIS con agent_id = demo-curator-connector y verifica el veredicto de la cadena.
Salida real de una corrida:
1) ingestDecision (raw)… mode=free seq=1 entry_hash=5df0176a4e8f31a5…
2) DeFi curator adapter (B1)… mode=free seq=2 entry_hash=8e6d1410b040f969…
3) CASP compliance adapter… mode=free seq=3 entry_hash=c6eb65ada504e8cf…
4) verifyLedger… verdict={"valid":true,"entries":4,
"reason":"all 4 entries signed (Dilithium-2 (NIST FIPS 204)) and chained — tamper-evident"}El ledger de producción puede estar vacío al inicio; sellar una decisión de ejemplo lo demuestra en vivo.
demo-curator-connectores un id de demo, no colisiona con ledgers reales.
API
ingestDecision({ agentId, input, output, modelId?, modelVersion? }, opts?) → Promise<receipt>
Sella la decisión. opts: { mode: 'auto'|'free'|'paid', payment, baseUrl, timeout, agentId }.
Recibo (campos clave): mode, agent_id, seq, prev_hash, entry_hash, input_hash, output_hash,
model_id, timestamp, signature, public_key, algorithm, honest_scope; en modo PAGA además
attestation_hash, permalink, block_number, anchor_error, payment. raw = respuesta cruda.
verifyLedger(agentId, opts?) → Promise<{ agent_id, entries, verdict, ledger, raw }>
Consulta el veredicto de la cadena. verdict = { valid, entries, reason, broken_at? }.
Errores
Todos los fallos lanzan IngestError con .status (HTTP), .body (JSON parseado) y
.cause. Casos notables: 402 (pago requerido — accepts[] en .body), 409 (pago ya
redimido), 429 (rate-limit), timeout/red.
Archivos
package.json— manifiesto ESM cero-dependencias (@fractalai/decision-ingest), conexportspara el core y los adaptadores,bin(demo) y scripts (check/test/demo).decision-ingest.mjs— módulo Node ESM (fetch nativo).ingestDecision,verifyLedger,stableStringify,IngestError.adapters/defi-curator.mjs— adaptador B1 (curador DeFi).adapters/casp-compliance.mjs— adaptador B4 (compliance CASP).examples/demo.mjs— prueba en vivo contra el endpoint GRATIS.test/decision-ingest.test.mjs— suite offline (node --test):stableStringify, normalización y manejo de 402/409 confetchmockeado. Sin dependencias.
Qué falta para que un CASP real lo adopte (honestidad, Regla 4)
Este SDK ya produce recibos re-verificables del registro declarado. Lo que todavía NO resuelve — y un comprador CASP-MiCA / entidad-DORA necesitará antes de producción:
- Firma del propio CASP, no solo la de FractalAI. Hoy el sello lo firma la clave
Dilithium-2 de FractalAI: prueba integridad/no-repudio frente a FractalAI, no que el
CASP originó el registro. Falta que el CASP firme el
input_hash/output_hashcon su clave (o un HSM/eIDAS) y que ese sig del cliente viaje en el recibo. Es el paso que convierte "FractalAI lo selló" en "el CASP lo declaró y no puede repudiarlo". - Mapeo a artículos concretos. Los adaptadores citan DORA Art.9/Art.17 y record-keeping MiCA de forma general; falta el mapeo campo-por-campo a los RTS/ITS aplicables y a los plazos de retención (p.ej. 5 años), y un formato de export entregable a la autoridad.
- Anti-omisión. La cadena hace detectable una edición posterior, no una omisión en origen. Un control real requiere reconciliar el ledger sellado contra el volumen de eventos del sistema fuente (conteo/secuencia esperada), fuera del alcance de este SDK.
- Retención/exportación y disponibilidad. SLA de anclaje on-chain, prueba de inclusión (Merkle) entregable, y un procedimiento de export/verificación auditables end-to-end.
- Privacidad/PII. El diseño ya hashea input/output; falta el due-diligence formal
(DPIA) confirmando que solo salen hashes y que
subjectes siempre pseudonimizado.
