Conarium

Capa de gobernanza autoalojada entre asistentes de IA y tus datos reales. Enmascaramiento determinista de PII, política de permitir/denegar, auditoría encadenada por hash, recibos Ed25519 verificables sin conexión por acceso cuando se configura un sumidero de recibos.

Documentación

Conarium

El Tercer Ojo para los Datos de tu Empresa.

Parte de VERAX, por VERAX Teknoloji. Comienza con el cuerpo de VERAX: verax-ai/verax. Proyectos hermanos: Tugra · Cedulon.

Listado en: npm · Glama · MCP Registry · MCP Market · LobeHub · Zenodo

Una puerta de enlace autohospedada y gobernada que permite a los asistentes de codificación con IA (Cursor, Copilot, Claude) tocar tus datos reales bajo una política que tú escribes: los valores protegidos se enmascaran antes de salir. Cuando se configura un sumidero de recibos, escribe un recibo firmado e independientemente verificable de cada acceso que media; conarium-init configura ese sumidero, por lo que el diseño predeterminado lo hace.

npm CI OpenSSF Scorecard OpenSSF Best Practices Website License Early Access


El sitio vive en conarium.dev; este repositorio es el producto.

Compruébalo antes de leer el resto

Nada de lo siguiente tiene que tomarse por fe. Hay una cadena de recibos en vivo; verifícala contra su clave pública en tu propia máquina, sin cuenta y sin datos tuyos:

npm i @conarium-ai/core
curl -fsS https://conarium.dev/proof/chain.jsonl   -o chain.jsonl
curl -fsS https://conarium.dev/proof/key.pem       -o key.pem
curl -fsS https://conarium.dev/proof/key.pem.keyid -o key.pem.keyid
npx conarium-verify chain.jsonl --pubkey key.pem
note: tail truncation is not visible — this run did not see receipts deleted from the
end of the file. Pin with --expect-count, --expect-last-hash, or --anchor-check.
ok: 3 receipt(s) verified (3 with undeclared model, 3 with undeclared client)

Código de salida 0. Los tres recibos son una lectura ordinaria, una donde cinco direcciones de correo electrónico y un número de tarjeta fueron enmascarados antes de que el modelo los viera, y una denegación. Cambia cualquier campo y el hash recalculado deja de coincidir con el almacenado — código de salida 10. Cambia la firma en su lugar — código de salida 13.

El verificador es un solo archivo que no importa nada del paquete que está verificando, por lo que un Conarium comprometido no puede convencerlo de un resultado aprobatorio. Ten en cuenta que declara lo que no verificó, en la primera línea de su propia salida, antes de las buenas noticias.

Limitaciones

Lo que este repositorio no ha hecho está en LIMITATIONS.md (Türkçe). La página de comparación fechada es conarium.dev/compare.html — esa es la única copia; este repositorio no mantiene una segunda.

Estándares

draft-dogru-scitt-disclosure-evidence es una presentación individual. No adoptada por un grupo de trabajo de la IETF, y no tiene estatus formal — un Internet-Draft es un registro público fechado, no un estándar. Se publica para que el formato de recibo pueda implementarse sin nosotros. Los archivos fuente viven en standards/.

👁️ El Problema

Apunta Cursor o Copilot a una base de datos de producción y bebe el flujo crudo: números de seguro social, tarjetas de crédito, salarios y claves en vivo. Un solo mensaje malicioso puede exponer tus tablas más sensibles. Los equipos de seguridad simplemente no pueden permitir eso.

🛡️ La Solución: Conarium

Conarium actúa como un Proxy MCP (Model Context Protocol) de alto rendimiento. Se sitúa directamente entre el Asistente de IA y tus bases de datos, evaluando políticas en milisegundos para imponer límites de filas y enmascarar PII (Información Personal Identificable) en el cable.

La IA obtiene el contexto que necesita para escribir código; los valores que tu política protege se enmascaran antes de que lleguen a ella. Enmascarar oculta un valor — no lo hace inaprendible, y donde un lenguaje de solicitud permite predicados sobre una columna protegida, una consulta permitida aún puede responder preguntas sobre uno. protectedColumns es la respuesta más estricta a eso, y el límite se declara en LIMITATIONS.md en lugar de dejarte que lo descubras.

Características Clave

  • Enmascaramiento de PII en línea: Correos electrónicos, identificaciones, tarjetas y secretos se redactan en el flujo de respuesta ([MASKED_PII] / [MASKED_SECRET]) antes de que el modelo vea un solo carácter.
  • Listas de Permitir / Denegar: Lista blanca de lo que la IA puede acceder. Tus tablas secrets y financials permanecen invisibles.
  • Límites de Filas: Límites duros por consulta. Previenen la exfiltración silenciosa de millones de filas.
  • Registro de Auditoría a Prueba de Manipulación: Cada acceso a través de Conarium se registra (quién, qué, cuándo, filas, decisión). Encadenado por hash, lo que hace detectable la alteración y la eliminación en medio de la cadena — no imposible: un archivo en disco aún puede eliminarse o truncarse, y detectar el truncamiento requiere una ancla desde fuera del archivo (ver Cobertura y Conciliación a continuación). Seguro para PII: no se escribe PII cruda en los registros.
  • Recibos Verificables: Firmados con Ed25519, recibos independientemente verificables — ver a continuación.
  • Perfiles de enmascaramiento por persona: lo que se enmascara para un agente de IA no es lo que se enmascara para el controlador de datos. Un perfil nombrado relaja el enmascaramiento para una persona identificada, y el recibo registra qué perfil se aplicó — ver a continuación.
  • Cobertura y Conciliación: una declaración de cobertura firmada sobre la cadena de recibos (conarium-coverage), más conciliación bidireccional contra los contadores de consultas de la propia base de datos (conarium-reconcile) — la actividad registrada en la base de datos que ningún recibo cubre se muestra en lugar de permanecer invisible.
  • 100% Autohospedado: Se ejecuta completamente en tu infraestructura. Nada de lo que enviamos transmite tus datos a ningún lugar: los valores protegidos crudos permanecen dentro de tu perímetro, y lo que llega a tu cliente de IA es la divulgación aprobada por la política — cuyos bytes exactos registra el recibo (disclosure.hash). Decir que tus datos nunca salen en absoluto sería una afirmación incorrecta: liberar una divulgación gobernada a un asistente es el trabajo. La puerta de enlace hace exactamente una solicitud saliente que no es tuya: al inicio pregunta al registro público de npm si existe una versión más nueva, e imprime una línea a stderr si es así. No envía nada sobre ti — sin identificador, sin configuración, sin conteos — y una puerta de enlace remota que nadie mira durante semanas es la razón por la que existe en absoluto. Desactívalo con CONARIUM_NO_UPDATE_CHECK=1, o apúntalo a tu espejo interno con CONARIUM_NPM_REGISTRY. Tiene un tiempo de espera de 2 segundos y nunca bloquea ni falla el inicio. Lo enumeramos aquí porque un producto de gobernanza que hace una conexión saliente no divulgada ya ha perdido el argumento.
  • Nativo MCP: Funciona de serie con Cursor, GitHub Copilot, Claude Code y Codex.

Recibos Verificables

Conarium puede emitir recibos portátiles (con forma de Art. 12 / 19) que un tercero verifica sin conexión con un solo archivo — sin necesidad de instalar Conarium.

Afirmación oficial (no ampliar): Un Recibo de Conarium prueba que los registros aún en el archivo no han sido alterados, reordenados o retrofechados después de crearse, y que ninguno fue eliminado del medio de la cadena (prevHash / seq). No prueba que fueran correctos en el momento de la creación. Tampoco puede, por sí solo, probar que los registros no fueron eliminados del final: una cadena restante más corta sigue siendo internamente consistente. Detectar el truncamiento de la cola requiere una ancla desde fuera del archivo — --expect-count, --expect-last-hash, un ancla de OpenTimestamps, o conarium-reconcile contra los contadores de la propia base de datos.

(TR) Conarium Makbuzu, dosyada hâlâ duran kayıtların oluşturulduktan sonra değiştirilmediğini, ortadan silinmediğini, yeniden sıralanmadığını ve geriye dönük tarihlenmediğini kanıtlar. Oluşturma anında doğru olduğunu kanıtlamaz. Sondan kesmeyi tek başına göremez: kalan zincir tutarlıdır, yalnızca kısadır. (/TR)

# Generate an Ed25519 keypair (private PEM + .pub.pem + .keyid sidecars).
# The .keyid sidecars are not optional: without them the verifier answers 13
# for every receipt, which reads like tampering and is not.
npx conarium-init

export CONARIUM_AUDIT_SIGNING_KEY=./audit-ed25519.pem

# init writes keys and config, not receipts: your own audit file does not exist
# until the gateway has served a query. The three commands below therefore run
# against the demo chain downloaded above, so they work as written — swap in
# your own sink (conarium.config.json → audit.sink) once it has records.

# Verify a receipt chain (exit 0 = the records *in the file* are intact)
npx conarium-verify chain.jsonl --pubkey key.pem

# Pin length / last hash if you need to catch records dropped from the end
npx conarium-verify chain.jsonl --pubkey key.pem --expect-count 3

# Check the OpenTimestamps sidecar. The demo chain ships without one, so this
# answers 14, deliberately not 0: an absent anchor is not a verified anchor.
# A sidecar that exists but is not yet confirmed → exit 0 with a warning.
npx conarium-verify chain.jsonl --pubkey key.pem --anchor-check

Un segundo verificador, solo Go y la biblioteca estándar, está en verifiers/go. go build -o conarium-verify . luego los mismos argumentos que conarium-verify; test-vectors/ es el contrato.

El anclaje es un paso separado. Sella un documento con npx conarium-stamp <file>, o envía un hash de cabeza de cadena con npx conarium-anchor-service. CONARIUM_ANCHOR_SINK=opentimestamps selecciona el cliente de calendario en el árbol que esas herramientas usan; no sella recibos a medida que se escriben. Actualiza pruebas pendientes más tarde con npx conarium-anchor-upgrade ./audit.jsonl.anchors.jsonl. El cliente está en el árbol (Node crypto + calendario HTTPS). No instala javascript-opentimestamps. Ver LIMITATIONS.md.

Perfiles de enmascaramiento por persona

El enmascaramiento que es correcto para un agente de IA es incorrecto para la persona que posee los datos. El propietario que pregunta "qué cliente debe más" necesita el nombre; el asistente que resume ingresos no. Responder eso con un interruptor global de encendido/apagado deshabilitaría la única garantía real del producto, por lo que el enmascaramiento se resuelve por persona:

{
  "policy": {
    "allowTables": ["zion.customers", "zion.orders"],
    "maskColumns": ["*.customer_name", "*.email", "*.phone"],  // default: everyone
    "maxRows": 100,

    "profiles": {
      // The controller sees customer names; email and phone stay masked.
      "controller-full": { "maskColumns": ["*.email", "*.phone"], "maxRows": 1000 }
    },
    "actorProfiles": { "emekcan": "controller-full" }
  }
}

Deliberadamente estrecho, porque esta es la única característica que puede aflojar la protección:

  • Un perfil puede anular maskColumns, maxRows y maskLabelledNames — y nada más. Los permisos de tabla, herramienta y conector permanecen globales; un perfil nunca puede ampliar lo que es alcanzable, solo lo que es legible dentro de él. protectedColumns no es superponible: un perfil que pudiera eliminarlo sería una puerta trasera por persona.
  • Solo tokens por usuario. Un actor autenticado con un token compartido nunca recibe un perfil. "Quien tenga esta cadena ve PII sin enmascarar" es precisamente el fallo que este producto existe para prevenir.
  • Cierre por defecto en todos los demás casos: sin actor, actor no listado, o un nombre de perfil que no existe, todos caen a la política base, nunca a una más amplia.
  • Los escáneres de contenido aún se ejecutan. Los detectores de correo electrónico / identificación nacional / teléfono / tarjeta / IBAN / secretos no se pueden anular en absoluto, por lo que permanecen enmascarados en texto libre sin importar qué perfil se aplicó. IBAN se acepta solo cuando se cumple ISO 7064 mod-97-10. El MRZ de pasaporte (TD3, dígitos de verificación 7-3-1) está activado por defecto y tampoco puede desactivarse mediante un perfil — solo policy.detectors.mrz: false en la política base lo excluye. Las direcciones IP están desactivadas hasta policy.detectors.ip: true. El enmascaramiento de nombres es el único detector que un perfil puede desactivar (maskLabelledNames: false), porque el controlador que lee su propia lista de clientes es el caso para el que existe esta característica.
  • El recibo dice qué perfil se aplicó — policy.id se convierte en conarium.policy/<profile>, dentro del hash firmado. Un acceso realizado bajo un perfil relajado no puede presentarse más tarde como completamente enmascarado. Esto es lo que mantiene honesta la historia de auditoría: el punto nunca fue "nadie ve PII", es "cada acceso está gobernado, y la evidencia dice bajo qué reglas".

Nombres en texto libre

Cada otro identificador tiene una forma. Un correo electrónico tiene un @, una identificación nacional tiene un checksum, una tarjeta tiene una longitud — una regex decide, y la decisión se reproduce. Un nombre no tiene forma, por lo que maskColumns era lo único que lo capturaba, y un nombre escrito en un note de texto libre llegaba al modelo textualmente.

Dos pasadas deterministas cierran la parte de esa brecha que puede cerrarse honestamente:

PasadaQué la activaEjemplo
TransferenciaEl valor es uno que esta política ya enmascara en alguna columnacustomer_name está enmascarado, por lo que note: "Ayşe Demir called" también está enmascarado — incluso entre filas
EtiquetadoEl texto mismo lo marca: un título o una etiqueta de campoSn. Ahmet Yılmaz, Yetkili: Ayşe Demir, customer: John Smith
**Lo que esto no hace, deliberadamente: un nombre simple en prosa corriente no se
detecta.** "Ahmet llamó ayer" pasa. Detectar eso requiere NER — un
modelo, un diccionario y una puntuación de confianza — y cada decisión que esta
puerta de enlace toma está pensada para ser reproducible solo a partir de la regla,
por alguien que no confía en nosotros. Un enmascarador probabilístico también sería
un recibo probabilístico. Las herramientas que sí ejecutan NER (las basadas en
Presidio, por ejemplo) cubren más tipos de entidades; lo logran
con un umbral de confianza. Ninguna posición domina — esta se
declara para que un auditor sepa cuál está sosteniendo.

Todavía no detectado por los escáneres de contenido — por diseño, no por omisión: direcciones postales y nombres simples. Un detector de direcciones no puede distinguir "Atatürk Caddesi No:15" de "Atatürk Barajı" sin un diccionario geográfico. Un detector de nombres no puede distinguir Deniz / Güneş / Umut de las palabras. Ambos necesitarían un diccionario o un modelo; las decisiones de esta puerta de enlace son deterministas. Cierra esas brechas con maskColumns (nombres de columna) y conarium-suggest-policy (una suposición basada en nombres que no escribe tu configuración).

Las direcciones IP se detectan cuando las activas (policy.detectors.ip: true). Están desactivadas por defecto: una IP de servidor no siempre es un dato personal, y una máscara que no puedes desactivar rompe el trabajo de SOC. 1.2.3.4 es estructuralmente una dirección IPv4 válida; cuando el detector está activo se enmascara, incluso si querías decir un número de versión. Las fechas (13.08.2026) y los montos (1.250,00) no son IPv4.

Los números de pasaporte en texto libre no se detectan. El MRZ sí: dos líneas TD3 × 44 caracteres, P en la posición 1, dígitos de verificación 7-3-1. Un fallo de suma de verificación no es un MRZ y se deja intacto. TD1/TD2 no están implementados.

HTML &#64; / &#x40;, JSON \u0040 y %40 se enmascaran cuando están dentro de un token con forma de correo electrónico. Un 5&#64; store o C:\path\u0040abc aislado se deja intacto. Una sola pasada de decodificación; &amp;#64; no se persigue.

Un TCKN dividido entre dos campos con nombres similares en la misma fila (tckn_1 / tckn_2) se enmascara cuando la concatenación pasa la suma de verificación. Las columnas no relacionadas no se combinan.

Los caracteres de ancho cero, los dígitos de ancho completo / @ y los guiones unicode se eliminan o se mapean a ASCII antes de los detectores — esa pasada no es un decodificador de codificación general; los tokens base64/hex envueltos dentro de un campo se enmascaran solo cuando se decodifican a una detección existente.

Longitud de escaneo. Un campo de texto único más largo que policy.scanCharCap (por defecto 16 384; la variable de entorno CONARIUM_SCAN_CHAR_CAP lo anula) se reemplaza con [MASKED_PII] en su totalidad, incluso cuando no contiene un identificador. El escáner no se omite: omitirlo significaría que una nota larga, un blob JSON o una línea de registro son la vía para evadir el enmascaramiento. Esta es una configuración de usabilidad. Aumentarla incrementa el costo de escaneo cuadráticamente — un campo alfanumérico de 40 KB tomó ~1 s en la expresión regular de correo sin límite antes de que esa expresión se acotara. maskedCount registra que se tomó una decisión.

La transferencia ignora valores de menos de tres caracteres (un valor de dos caracteres coincide en todas partes y destrozaría la salida) y coincide en límites de palabras Unicode, por lo que Ali se enmascara en Ali onayladı pero no dentro de Kalite.

Cobertura y conciliación (detección de evasión)

Los recibos prueban lo que pasó por la puerta de enlace. La conciliación pregunta a la base de datos qué vio y compara:

Ningún comando inventa sus entradas y conarium-init no las crea, por lo que ambos responden 20 (entrada faltante) hasta que las hayas producido: declaration.json es tu propia declaración de período y alcance (docs/RECEIPT-SPEC.md nombra los campos), y las dos instantáneas provienen de scripts/pg-snapshot.sql.

# One-sided: signed coverage declaration over a period + declared scope
npx conarium-coverage ./declaration.json --pubkey ./audit-ed25519.pub.pem --receipts ./receipts.jsonl

# Two-sided: reconcile the DB's own per-role query counters against receipts.
# Snapshots come from pg_stat_statements (scripts/pg-snapshot.sql), taken at
# window start and window end with a dedicated DB role per gateway instance.
npx conarium-reconcile --before before.json --after after.json --receipts ./receipts.jsonl
# exit 0  = every DB query pattern in the window is attributable to a receipt for
#           the same table (object attribution, not per-statement coverage —
#           see LIMITATIONS.md)
# exit 40 = the DB recorded activity no receipt covers — the gateway may have
#           been bypassed, or the receipt sink failed

El lenguaje es deliberado: la ausencia se reporta como "acceso NO REGISTRADO" / "no recibido", nunca "no ocurrió ningún acceso" — un registro ausente es ambiguo por naturaleza, y una herramienta que finge lo contrario le está mintiendo a su auditor.

Ejecutado contra nuestro propio ERP de producción el día que se lanzó, incluida una evasión real que realizamos sobre nosotros mismos y la herramienta detectó: docs/dogfood/2026-08-06-reconcile.md.

Esquema completo, códigos de salida y brechas conocidas: docs/RECEIPT-SPEC.md.

Cofirma (la parte que no puedes hacer por ti mismo)

Los recibos prueban lo que pasó por la puerta de enlace. La conciliación prueba que nada la rodeó. Ambos son tuyos, autoalojados y firmados con tu propia clave — que es exactamente lo que un auditor descuenta: tú guardaste el registro, lo firmaste y lo almacenaste. Una cofirma responde a eso poniendo una segunda parte en la misma cabeza de cadena.

El servicio está en este paquete, para que puedas ejecutar el tuyo y firmar tus propias cabezas — útil para un segundo custodio interno e inútil contra la objeción anterior. Lo que le da valor es que el firmante no eres tú.

# Run the endpoint. It refuses to start without a signing key or a token file:
# with neither present the three lines below exit 2 and name what is missing,
# which is the intended answer, not a failed install. Generating both is in
# deploy/anchor-service/.
CONARIUM_ANCHOR_TOKENS=./anchor.tokens.json \
CONARIUM_ANCHOR_SIGNING_KEY=./anchor.pem \
CONARIUM_ANCHOR_BASE_URL=https://anchor.example.com \
npx conarium-anchor-service

# Verify a countersignature you were given — offline, no network, no package.
# record.json is what the endpoint returned to you; without it, exit 20.
npx conarium-countersign-verify ./record.json --pubkey ./anchor.pub.pem
# exit 0  = signature valid (and inclusion valid if a proof or --log-url was given)
# exit 13 = signature invalid / unknown keyId
# exit 14 = inclusion proof present and false
# exit 15 = the log could NOT be checked — deliberately not the same as 14

El registro es una cadena de hash: las entradas se agregan, nunca se reescriben, y una marca de tiempo OTS cubre la cabeza en lugar de cada envío. Lo que una cofirma prueba — y, igual de importante, lo que no — está escrito en docs/COUNTERSIGN.md, junto con lo que costaría una clave de firma filtrada.

Pro es la cofirma alojada — alguien más que tú firma la cabeza de la cadena. $20/mes o $200/año — ahorra $40. Un período, no una suscripción. No se renueva solo — cuando el período termina, el acceso termina y puedes comprarlo de nuevo. Reembolso de 14 días sin preguntas; después de eso, sin reembolsos parciales. IVA añadido donde corresponda. El pago aún no está abierto: conarium.dev/buy redirige al formulario de lista de espera hasta que la vía de pago esté activa, así que estos términos son el precio publicado más que algo que puedas pagar hoy. El binario anterior es lo que ejecutas tú mismo; Pro es el segundo firmante. Incluido en el paquete desde 0.2.16; el endpoint operado por VERAX aún no está abierto para clientes. El negocio sigue en la lista de espera: la conciliación programada, las alertas de cobertura y el informe de período firmado están en el contrato, aún no enviados.

Implementar el formato tú mismo

El recibo está pensado para sobrevivir a esta implementación, por lo que incluye vectores de conformidad — trece casos congelados más un manifiesto legible por máquina en test-vectors/:

npm run test:vectors     # our verifier against the frozen cases

Apunta tu propio verificador a cada receipts.jsonl, pasa los argumentos listados en manifest.json y compara el código de salida. expected-hashes.json da los hashes canónicos JCS → SHA-256 para que puedas verificar tu canonicalización sin necesitar nuestra clave privada, que deliberadamente no se publica.

Los vectores encontraron dos cosas en este repositorio en su primera ejecución: una verificación de esquema que reportaba un recibo estructuralmente inválido como manipulado, y una suposición incorrecta nuestra sobre recibos sin firmar. Ambos están ahora congelados como casos 007 y 008.

Anclar tu cadena (opcional)

conarium-stamp ancla un archivo a los calendarios de OpenTimestamps, y conarium-anchor-upgrade completa la altura del bloque de Bitcoin una vez que llega. Esos dos son todo lo que la mayoría de las configuraciones necesitan.

Si prefieres exponer el anclaje como un pequeño servicio — para varias puertas de enlace, o para darle a un auditor una URL estable — bin/conarium-anchor-service.mjs es uno: envía hashes, conserva pruebas, sirve el .ots crudo en una ruta permanente y actualiza los anclajes pendientes con un temporizador.

Es código que ejecutas, no un servicio que operamos — no hay una instancia alojada para registrarse. También sirve la prueba cruda precisamente para que un tercero pueda verificar con el cliente de referencia de OpenTimestamps e ignorar el servicio por completo. Un endpoint de anclaje en el que tengas que confiar anularía el propósito del anclaje.

La firma es de cierre seguro: establece CONARIUM_AUDIT_SIGNING_KEY y/o CONARIUM_AUDIT_HMAC_KEY, o explícitamente CONARIUM_AUDIT_UNSIGNED=1 para configuraciones desechables. Rotación de claves: mantén los PEM públicos anteriores en CONARIUM_AUDIT_TRUST_PUBKEYS (, / ; separados). Después de la primera línea de auditoría firmada, cada línea posterior debe llevar sig.

Dónde se sitúa entre proyectos similares

Conarium no es el primer proyecto que produce recibos firmados y verificables para la actividad de IA. Acta, Emilia Protocol, AuthProof, Agent Receipts e Invariant SVR hacen una forma de esto, y algunos están por delante de nosotros en estandarización — Acta y Emilia tienen ambos borradores de Internet del IETF. Investigación relacionada: Aegon (arXiv 2604.06693), Decentralised Trust Layers (ACM Web Conf 2026) e ISO/IEC TS 27560:2023 para registros de consentimiento firmados.

Esos recibos dan fe de lo que un agente hizo. Un recibo de Conarium da fe de lo que al modelo se le impidió ver — porque el componente que enmascara los datos es el mismo componente que firma el registro. La aplicación y la evidencia son una sola parte aquí, no dos sistemas que tengan que conciliarse.

Lo que defenderemos: Conarium es la única implementación que conocemos que combina las tres cosas: (1) aplicación en línea (política + enmascaramiento), (2) un recibo portátil y verificable sin conexión de esa aplicación, y (3) conciliación de cobertura — verificar los contadores de consultas de la propia base de datos contra la cadena de recibos, para que el acceso que evadió la puerta de enlace salga a la superficie en lugar de permanecer invisible. Firmar recibos sin aplicar es común; aplicar sin recibos portátiles es común; conciliar ambos lados contra la propia contabilidad de la fuente de datos es la parte que no hemos encontrado en otro lugar. Medido de extremo a extremo en el ERP en vivo de una empresa operativa real — 121 374 registros, 121 366 identidades enmascaradas, 485 496 campos enmascarados, cero filtrados al modelo (Informe de Gobernanza 001).

Qué es ese número y qué no es. Proviene de una ejecución por lotes contra el ERP de nuestra propia empresa, y lo respalda un archivo de auditoría encadenado por hash de 123 líneas cuya aritmética puedes re-sumar tú mismo y cuya cadena se re-verificó 17 días después. Lo que no lo respalda es una cadena de recibos: esa ejecución emitió entradas de auditoría, no recibos portátiles firmados, y su actor es una identidad de servicio por lotes, no una persona. Entonces, si preguntas "muéstrame los recibos de esos 485 496 campos", la respuesta honesta es que no existen — la cadena de recibos es una medición separada y mucho más pequeña. La escala y la verificabilidad sin conexión son dos afirmaciones diferentes aquí, y preferimos trazar esa línea nosotros mismos a que la encuentres tú. El mecanismo es verificable sin confiar en nosotros; esta cifra particular es nuestra propia medición, y Informe de Gobernanza 001 enumera sus límites.

Esa afirmación está acotada a propósito, y docs/PRIOR-ART.md es la evidencia detrás de ella: once proyectos — diez verificados el 6 de agosto de 2026 y Vaara agregado el 19 de agosto — qué tiene cada uno, el trabajo académico previo más cercano (Sello / Notarized Agents, que nombra esta brecha mejor de lo que lo hicimos nosotros) y nueve cosas que no pudimos verificar. Si conoces una implementación que combine las tres, abre un issue y se corregirá.

⚠️ La fila de Vaara estrechó esta afirmación en lugar de confirmarla. Ese proyecto especifica una conciliación de cobertura en sus documentos de diseño; una búsqueda en su árbol no encontró código que la ejecute, por lo que la fila dice "especificada, no encontrada implementada". La idea no es solo nuestra — el código en ejecución, hasta donde llega este escaneo, todavía lo es, y el archivo lo dice encima de su propia tabla.


🏗️ Arquitectura (La Tríada)

Conarium opera con una arquitectura tripartita estricta, equilibrando el poder entre tres pilares:

graph LR
    A([AI Assistant\nCursor / Copilot]) -- "MCP Query" --> B{The Gateway\nConarium Proxy};
    B -- "Intercept & Parse" --> C[The Engine\nGovernance & Regex];
    C -- "Execute Query" --> D[(Your Database\nPostgres / SQL Server / Oracle)];
    D -- "Raw Data" --> C;
    C -- "Mask & Cap" --> B;
    B -- "Sanitized Data" --> A;
    C -. "Write Log" .-> E[The Ledger\nAudit DB];
    
    style A fill:#05070f,stroke:#5a8cff,stroke-width:2px,color:#fff
    style B fill:#05070f,stroke:#ff6f80,stroke-width:2px,color:#fff
    style C fill:#05070f,stroke:#6fe0e0,stroke-width:2px,color:#fff
    style D fill:#05070f,stroke:#f2d79a,stroke-width:2px,color:#fff
    style E fill:#05070f,stroke:#838dad,stroke-width:2px,color:#fff
  1. La Puerta de Enlace: Un proxy que habla con fluidez con los asistentes de LLM.
  2. El Motor: Evalúa políticas JSON, escaneos de expresiones regulares y límites de filas en milisegundos.
  3. El Libro Mayor: Un registro de auditoría a prueba de manipulaciones que registra cada consulta y decisión que media.

Pruébalo sin una base de datos

npx -y --package=@conarium-ai/core conarium --demo

Inicia un servidor MCP local sobre filas de muestra, no sobre una base de datos. Una tabla permitida devuelve filas con valores de correo electrónico y tarjeta enmascarados antes de que las filas salgan de la puerta; una tabla denegada es rechazada; se aplica el límite de filas; las llamadas permitidas y rechazadas se registran en una cadena firmada. Ninguno de los conectores incluidos se utiliza.

{
  "mcpServers": {
    "conarium": {
      "command": "npx",
      "args": ["-y", "--package=@conarium-ai/core", "conarium", "--demo"]
    }
  }
}

🚀 Inicio rápido

# 1. Install
npm i @conarium-ai/core

# 2. Write a fail-closed skeleton (config + Ed25519 pair + .keyid sidecars)
npx conarium-init
export CONARIUM_AUDIT_SIGNING_KEY="$PWD/audit-ed25519.pem"

# 3. Check the install before trusting it. Until step 4 points the config at a
#    reachable DSN, doctor reports the placeholder host unreachable and exits 1.
#    That FAIL is the check working, not the install being broken — it is the one
#    thing a gateway must not be quiet about, because it keeps running with zero
#    connectors and looks healthy while serving nothing.
npx conarium-doctor

# 4. Point the generated conarium.config.json at your read-only DSN,
#    fill policy.allowTables, then run the governed MCP gateway
npx conarium

El paso 3 no es decorativo. Un archivo de configuración faltante no detiene la puerta de enlace: se inicia con cero conectores y no gobierna nada—y un conector que falla al conectarse se registra, no se lanza. conarium-doctor nombra ambos, sale con 1 cuando algo está mal para poder controlar un despliegue, y nunca imprime un secreto, por lo que su salida es segura para pegar en un issue.

Desde el código fuente en su lugar
git clone https://github.com/dogrucanemek-alt/conarium.git
cd conarium
npm install && npm run build
# The repository already ships a conarium.config.json, so init refuses rather
# than overwrite it (exit 1). Pass --force only if you want it regenerated.
node bin/conarium-init.mjs --force
node bin/conarium-doctor.mjs --no-net
npm start

conarium-init se niega a sobrescribir archivos existentes a menos que pases --force. Nunca imprime la clave privada—solo su ruta.

Acceso directo de escritorio para la consola

El editor de políticas es npx conarium-console. Aún se vincula a 127.0.0.1 y aún requiere un token. Estos dos comandos solo añaden una puerta en el escritorio:

npx conarium-console --install-shortcut
npx conarium-console --uninstall-shortcut
Windows.lnk en el escritorio (ventana de consola minimizada)
macOS~/Applications/Conarium Console.app
Linux~/.local/share/applications/conarium-console.desktop

El doble clic inicia la misma consola, espera hasta que el puerto esté escuchando, y luego abre tu navegador. El token no se coloca en la URL; un nonce de un solo uso (≤30s) se intercambia por una cookie de sesión. Si ya existe un acceso directo con ese nombre, se usa un sufijo -2 en lugar de sobrescribir.

Exporta CONARIUM_CONSOLE_TOKEN antes de --install-shortcut para que el lanzador pueda leerlo desde ~/.conarium/console.token (creado 0600). El archivo de acceso directo en sí no contiene el token.

El acceso directo usa assets/conarium-mark.ico / .icns / -512.png, todos del mismo SVG. Si esos archivos faltan, el acceso directo aún se crea y el comando advierte.

La pestaña Makbuzlar de la consola lista recibos firmados de audit.receiptSink (los más recientes primero) y muestra el mismo HTML de recibo que demo.conarium.dev/proof. Verifica la cadena hash y escribe zincir sağlam o kırık (satır N). Si el sumidero está vacío o no está configurado, lo dice—no inventa un recibo de muestra. Los registros de auditoría siguen siendo el rastro de juguete sin firmar; no son recibos.

Cuando el paquete esté en npm, los mismos binarios se incluirán en el tarball (conarium-init, conarium-doctor, conarium-verify, conarium-suggest-policy). Hasta entonces, ejecútalos desde este repositorio como se indicó anteriormente.

Antes de reportar un error: ejecuta el doctor

conarium-doctor verifica las cosas que fallan silenciosamente. Dos de ellas importan más: un archivo de configuración faltante no detiene la puerta de enlace—se inicia con cero conectores y no gobierna nada—y un conector que no puede conectarse se registra, no se lanza, por lo que el proceso parece saludable mientras no sirve nada. El doctor también detecta el sidecar <pubkey>.keyid faltante, que hace que cada recibo se verifique como 13 (parece manipulación, pero no lo es).

Sale con 0 cuando está limpio y 1 cuando algo está mal, por lo que puede controlar un despliegue. Nunca imprime un secreto—contraseñas, tokens y material de claves se reportan solo como forma (postgresql://appuser@db.internal:5432/prod (contraseña establecida, no mostrada)), lo que significa que la salida es segura para pegar en un issue o un correo electrónico.

Conarium habla MCP sobre stdio, por lo que tu asistente de IA lo lanza como un comando. Añade esto a la configuración de tu cliente MCP (por ejemplo, Cursor):

{
  "mcpServers": {
    "conarium": {
      "command": "npx",
      "args": ["-y", "--package=@conarium-ai/core", "conarium", "--config", "/path/to/your/conarium.config.json"]
    }
  }
}

⚙️ Configuración (Política como Código)

Controla el acceso usando un archivo de política conarium.json simple:

{
  "maxRows": 50,
  "allowTables": ["public.customers", "public.orders"],
  "denyTables": ["public.secrets", "public.financials"],
  "maskColumns": ["email", "ssn", "*.card", "*.api_key"],
  "protectedColumns": ["*.email", "customers.tckn"],
  "allowConnectors": ["postgres-main", "docs"]
}

Cualquier cosa que no esté en allowTables se deniega por defecto; los maskColumns coincidentes se redactan a [MASKED_PII] antes de que los datos lleguen al modelo.

protectedColumns usa la misma sintaxis de glob. Cada patrón también se enmascara en el resultado. Además, esa columna no puede aparecer en un predicado (WHERE, HAVING, JOIN … ON, ORDER BY, GROUP BY) o en una expresión SELECT derivada —la consulta se rechaza. Un SELECT email simple aún se permite y regresa enmascarado. Omite el campo y el comportamiento no cambia. Un perfil no puede configurarlo. mssql / oracle se niegan a arrancar si el campo no está vacío: esas puertas no pueden recorrer posiciones de predicado, y este producto no reclama una regla que no puede aplicar.

policy.dialect selecciona la puerta SQL que usa la herramienta query: postgres (predeterminado omitido), mssql, o oracle. Es la declaración del operador—Conarium no adivina el dialecto de la declaración. Un error tipográfico o mysql rechaza la configuración.

Los conectores están cerrados por fallo. allowConnectors es una lista de permitidos estricta: si falta o está vacía, ningún conector está permitido (anteriormente una lista vacía significaba "permitir todos"). Si configuras conectores, debes listarlos aquí— de lo contrario, el servidor se niega a iniciar y te dice exactamente qué campo añadir. denyConnectors aún tiene prioridad sobre allowConnectors.

policy.detectors y policy.scanCharCap

Los detectores de identidad—TCKN, tarjeta, IBAN, correo electrónico—no se pueden desactivar. Una configuración que lo intente (detectors: { tckn: false }) se rechaza al cargar. Ese es el producto: un enmascaramiento que un banco puede desactivar desde un archivo JSON no es enmascaramiento.

ClavePredeterminadoPor qué
detectors.ipfalseUna IP de servidor no siempre es un dato personal. Un enmascaramiento sin interruptor de apagado rompe SOC ("¿cuántas solicitudes desde esta dirección?"). Opta por activarlo cuando la columna realmente sea una dirección de cliente.
detectors.mrztrueUn MRZ de pasaporte es identidad y tiene dígitos de verificación. Desactívalo en la política base si no manejas documentos de viaje.
scanCharCap16384Usabilidad. Los campos más largos que esto se reemplazan completos ([MASKED_PII]), nunca se omiten. La variable de entorno CONARIUM_SCAN_CHAR_CAP lo anula. Auméntalo y el costo de escaneo crece cuadráticamente. Tope 1 048 576.
{
  "scanCharCap": 32768,
  "detectors": { "ip": true }
}

policy.customPatterns

Formatos que los detectores integrados no conocen—un número de cliente bancario, un código de cuenta doméstica—se pueden registrar como reglas adicionales en el mismo escáner. Esto no es una segunda ruta de enmascaramiento y no reemplaza maskColumns.

Cada regla necesita un nombre (lo que registra el recibo), un patrón, globs de columna opcionales y una etiqueta de enmascaramiento. Un sample opcional es contra lo que conarium-doctor prueba el patrón compilado—el éxito de compilación no es una captura. Un patrón roto o con forma de ReDoS rechaza la configuración; el patrón y la muestra nunca se escriben en registros, recibos o salida del doctor.

{
  "customPatterns": [
    {
      "name": "teb-hesap",
      "pattern": "HSP-[0-9]{8}",
      "columns": ["*.hesap_no"],
      "label": "[MASKED_HESAP]"
    }
  ]
}

Los cuantificadores deben estar acotados ({8}, {4,12}). +, *, grupos anidados y lookaround se rechazan al cargar. Una regla nombra un formato que ya conoces; no inventa uno.

conarium-suggest-policy --sql schema.sql imprime una suposición de maskColumns a partir de nombres de columna (*name*, *address*, *tckn*, …). No escribe tu configuración. La primera línea de la salida lo dice.

🗺️ Hoja de ruta

Conarium es acceso temprano—y honesto sobre lo que es real:

Enviando ahora: puerta de enlace MCP gobernada (stdio + HTTP) · enmascaramiento determinista de PII, incluyendo nombres etiquetados en texto libre · permitir/denegar + límites de filas · perfiles de enmascaramiento por persona · libro de auditoría encadenado por hash a prueba de manipulación · recibo firmado con Ed25519 por acceso una vez que se configura un sumidero de recibos, con un verificador fuera de línea · declaraciones de cobertura firmadas · reconciliación bidireccional contra los contadores propios de la base de datos · anclaje OpenTimestamps y un servicio de anclaje opcional · vectores de conformidad · puerta SQL: Postgres, Microsoft SQL Server, Oracle (MySQL no está implementado; los sinónimos de Oracle y los enlaces de base de datos no se resuelven—ver LIMITACIONES) · conectores de Postgres, Supabase, docs, OpenAPI, Jira y Slack · conarium-init / conarium-doctor vía npx (@conarium-ai/core).

Siguiente: vinculación de consentimiento (especificación publicada, sin código— revisión de patente primero) · una segunda implementación independiente del formato de recibo · identidad por usuario vinculada a un proveedor de identidad en lugar de un mapa de tokens del operador.

Deliberadamente no planificado, para que nadie lo espere:

  • Enmascaramiento "semántico" basado en LLM. La puerta es determinista a propósito. Un enmascaramiento probabilístico haría un recibo probabilístico, que no es un recibo.
  • Consola en la nube alojada. Autoalojado es la afirmación; una consola alojada nos pondría en la ruta de datos en la que te decimos que no estamos.
  • Sin SOC 2 para nosotros. En esta etapa, la prioridad son las pruebas de penetración independientes y la garantía a nivel de implementación, más que la certificación organizacional. Esto es sobre nuestra certificación, no la tuya: los recibos firmados y las declaraciones de cobertura son tuyos para mostrar a tu propio auditor, y si satisfacen una auditoría dada es entre tú y ese auditor. Si alguna vez tenemos tus datos, o un compromiso depende del certificado en sí, esta línea cambia primero.
  • La insignia de Mejores Prácticas de OpenSSF arriba es autocertificación, no una auditoría. Respondimos sus 67 preguntas y publicamos las respuestas; cualquiera puede leerlas en proyecto 14160 y verificar cada una contra este repositorio. Eso vale algo—las respuestas son falsables— y no es lo mismo que alguien independiente haya mirado. Tres de las 67 están marcadas como no aplicables y dicen por qué. La insignia de Scorecard al lado es medida por máquina e incluye una puntuación Code-Review de 0, porque las solicitudes de extracción aquí se fusionan sin un segundo aprobador.

Brechas conocidas: LIMITATIONS.md, el README anterior, docs/RECEIPT-SPEC.md, docs/BENCHMARK.md, y docs/API-STABILITY.md.

📜 Licencia

MIT—todo, incluyendo el verificador, las herramientas de reconciliación y el servicio de anclaje. No hay ninguna función retenida para un nivel de pago; el código es MIT. Lo que conarium.dev vende es un segundo firmante (Pro) y, más adelante, cobertura operada (Business—aún no enviado)—no acceso al código.