Conarium

Camada de governança auto-hospedada entre assistentes de IA e seus dados reais. Mascaramento determinístico de PII, política de permitir/negar, auditoria encadeada por hash, recibos Ed25519 verificáveis offline por acesso quando um sumidouro de recibos está configurado.

Documentação

Conarium

O Terceiro Olho para os Dados da Sua Empresa.

Parte do VERAX, da VERAX Teknoloji. Comece pelo corpo VERAX: verax-ai/verax. Projetos irmãos: Tugra · Cedulon.

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

Um gateway auto-hospedado e governado que permite que assistentes de codificação com IA (Cursor, Copilot, Claude) acessem seus dados reais sob uma política que você define—valores protegidos são mascarados antes de saírem. Quando um destino de recibos está configurado, ele grava um recibo assinado e verificável de forma independente para cada acesso que media; conarium-init define esse destino, então o layout padrão o faz.

npm CI OpenSSF Scorecard OpenSSF Best Practices Website License Early Access


O site está em conarium.dev; este repositório é o produto.

Verifique antes de ler o resto

Nada abaixo precisa ser aceito por confiança. Existe uma cadeia de recibos ao vivo; verifique-a contra sua chave pública na sua própria máquina, sem conta e sem dados seus:

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 saída 0. Os três recibos são uma leitura comum, um onde cinco endereços de e-mail e um número de cartão foram mascarados antes de o modelo vê-los, e uma recusa. Altere qualquer campo e o hash recalculado para de corresponder ao armazenado — saída 10. Altere a assinatura — saída 13.

O verificador é um único arquivo que não importa nada do pacote que está verificando, então um Conarium comprometido não pode convencê-lo a um resultado aprovado. Observe que ele informa voluntariamente o que não verificou, na primeira linha de sua própria saída, antes das boas notícias.

Limitações

O que este repositório não fez está em LIMITATIONS.md (Türkçe). A página de comparação datada é conarium.dev/compare.html — essa é a única cópia; este repositório não mantém uma segunda.

Padrões

draft-dogru-scitt-disclosure-evidence é uma submissão individual. Não adotada por um grupo de trabalho da IETF, e não tem status formal — um Internet-Draft é um registro público datado, não um padrão. É publicado para que o formato de recibo possa ser implementado sem nós. Os arquivos-fonte estão em standards/.

👁️ O Problema

Aponte o Cursor ou o Copilot para um banco de dados de produção e ele bebe o fluxo bruto—SSNs, cartões de crédito, salários e chaves ativas. Um único prompt malicioso pode expor suas tabelas mais sensíveis. Equipes de segurança simplesmente não podem permitir isso.

🛡️ A Solução: Conarium

O Conarium atua como um Proxy MCP (Model Context Protocol) de alto desempenho. Ele fica diretamente entre o Assistente de IA e seus bancos de dados, avaliando políticas em milissegundos para impor limites de linhas e mascarar PII (Informações Pessoais Identificáveis) no tráfego.

A IA recebe o contexto necessário para escrever código; os valores que sua política protege são mascarados antes de chegarem a ela. Mascarar esconde um valor — não o torna impossível de aprender, e onde uma linguagem de solicitação permite predicados sobre uma coluna protegida, uma consulta permitida ainda pode responder perguntas sobre ela. protectedColumns é a resposta mais restrita para isso, e o limite está declarado em LIMITATIONS.md em vez de deixado para você descobrir.

Principais Recursos

  • Mascaramento de PII em Linha: E-mails, IDs, cartões e segredos são redigidos no fluxo de resposta ([MASKED_PII] / [MASKED_SECRET]) antes que o modelo veja um único caractere.
  • Listas de Permitir / Negar: Lista de permissões do que a IA pode acessar. Suas tabelas secrets e financials permanecem invisíveis.
  • Limites de Linhas: Limites rígidos por consulta. Impedem a exfiltração silenciosa de milhões de linhas.
  • Registro de Auditoria à Prova de Adulteração: Cada acesso através do Conarium é registrado (quem, o quê, quando, linhas, decisão). Encadeado por hash, o que torna a alteração e a remoção no meio da cadeia detectáveis — não impossíveis: um arquivo em disco ainda pode ser excluído ou truncado, e detectar truncamento exige um pino de fora do arquivo (veja Cobertura e Reconciliação abaixo). Seguro para PII: nenhuma PII bruta é gravada nos logs.
  • Recibos Verificáveis: Assinados com Ed25519, verificáveis de forma independente — veja abaixo.
  • Perfis de mascaramento por pessoa: o que mascarar para um agente de IA não é o que mascarar para o controlador de dados. Um perfil nomeado relaxa o mascaramento para uma pessoa identificada, e o recibo registra qual perfil foi aplicado — veja abaixo.
  • Cobertura e Reconciliação: uma declaração de cobertura assinada sobre a cadeia de recibos (conarium-coverage), além de reconciliação bilateral contra os contadores de consultas do próprio banco de dados (conarium-reconcile) — atividade registrada no banco que nenhum recibo cobre é exposta em vez de permanecer invisível.
  • 100% Auto-Hospedado: Executa inteiramente na sua infraestrutura. Nada que enviamos transmite seus dados para qualquer lugar: valores protegidos brutos permanecem dentro do seu perímetro, e o que chega ao seu cliente de IA é a divulgação aprovada pela política — cujos bytes exatos o recibo registra (disclosure.hash). Dizer que seus dados nunca saem seria a afirmação errada: liberar uma divulgação governada a um assistente é o trabalho. O gateway faz exatamente uma solicitação de saída que não é sua: na inicialização, ele pergunta ao registro público do npm se uma versão mais recente existe e imprime uma linha no stderr se houver. Ele não envia nada sobre você — nenhum identificador, configuração ou contagem — e um gateway remoto que ninguém olha por semanas é o motivo de ele existir. Desative-o com CONARIUM_NO_UPDATE_CHECK=1, ou aponte-o para seu espelho interno com CONARIUM_NPM_REGISTRY. Ele tem um tempo limite de 2 segundos e nunca bloqueia ou falha na inicialização. Listamos isso aqui porque um produto de governança que faz uma conexão de saída não divulgada já perdeu o argumento.
  • Nativo para MCP: Funciona prontamente com Cursor, GitHub Copilot, Claude Code e Codex.

Recibos Verificáveis

O Conarium pode emitir recibos portáteis (formato Art. 12 / 19) que um terceiro verifica offline com um único arquivo — sem instalação do Conarium.

Afirmação oficial (não amplie): Um Recibo Conarium prova que os registros ainda no arquivo não foram alterados, reordenados ou com data retroativa após terem sido criados, e que nenhum foi removido do meio da cadeia (prevHash / seq). Ele não prova que estavam corretos no momento da criação. Também não pode, por si só, provar que registros não foram descartados do final: uma cadeia restante mais curta ainda é internamente consistente. Detectar truncamento na cauda exige um pino de fora do arquivo — --expect-count, --expect-last-hash, uma âncora OpenTimestamps ou conarium-reconcile contra os contadores do próprio banco de dados.

(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

Um segundo verificador, apenas Go e a biblioteca padrão, está em verifiers/go. go build -o conarium-verify . então os mesmos argumentos que conarium-verify; test-vectors/ é o contrato.

A ancoragem é uma etapa separada. Carimbe um documento com npx conarium-stamp <file>, ou envie um hash de cabeça de cadeia com npx conarium-anchor-service. CONARIUM_ANCHOR_SINK=opentimestamps seleciona o cliente de calendário na árvore que essas ferramentas usam; ele não carimba recibos conforme são gravados. Atualize provas pendentes depois com npx conarium-anchor-upgrade ./audit.jsonl.anchors.jsonl. O cliente está na árvore (Node crypto + calendário HTTPS). Ele não instala javascript-opentimestamps. Veja LIMITATIONS.md.

Perfis de mascaramento por pessoa

O mascaramento correto para um agente de IA é errado para a pessoa que possui os dados. O proprietário perguntando "qual cliente deve mais" precisa do nome; o assistente resumindo receita não precisa. Responder isso com um interruptor global liga/desliga desativaria a única garantia real do produto, então o mascaramento é resolvido por pessoa:

{
  "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 restrito, porque este é o único recurso que pode afrouxar a proteção:

  • Um perfil pode substituir maskColumns, maxRows e maskLabelledNames — e nada mais. Permissões de tabela, ferramenta e conector permanecem globais; um perfil nunca pode ampliar o que é acessível, apenas o que é legível dentro dele. protectedColumns não é sobreponível: um perfil que pudesse removê-lo seria uma porta dos fundos por pessoa.
  • Somente tokens por usuário. Um ator autenticado com um token compartilhado nunca recebe um perfil. "Quem quer que segure esta string vê PII não mascarada" é exatamente a falha que este produto existe para prevenir.
  • Falha fechada em todos os outros lugares: nenhum ator, ator não listado ou um nome de perfil que não existe caem todos de volta para a política base, nunca para uma mais ampla.
  • Os scanners de conteúdo ainda são executados. Detectores de e-mail / ID nacional / telefone / cartão / IBAN / segredo não são substituíveis, então esses permanecem mascarados em texto livre independentemente de qual perfil foi aplicado. IBAN é aceito apenas quando ISO 7064 mod-97-10 é válido. MRZ de passaporte (TD3, dígitos de verificação 7-3-1) está ativado por padrão e igualmente não pode ser desativado por um perfil — apenas policy.detectors.mrz: false na política base o exclui. Endereços IP estão desativados até policy.detectors.ip: true. O mascaramento de nomes é o único detector que um perfil pode desativar (maskLabelledNames: false), porque o controlador lendo sua própria lista de clientes é o caso para o qual este recurso existe.
  • O recibo diz qual perfil foi aplicado — policy.id torna-se conarium.policy/<profile>, dentro do hash assinado. Um acesso feito sob um perfil relaxado não pode ser apresentado posteriormente como totalmente mascarado. Isso é o que mantém a história de auditoria honesta: o ponto nunca foi "ninguém vê PII", é "todo acesso é governado, e a evidência diz sob quais regras."

Nomes em texto livre

Todo outro identificador tem uma forma. Um e-mail tem um @, um ID nacional tem um checksum, um cartão tem um comprimento — uma regex decide, e a decisão se reproduz. Um nome não tem forma, então maskColumns era a única coisa capturando um, e um nome digitado em um note de texto livre chegava ao modelo verbatim.

Duas passagens determinísticas fecham a parte dessa lacuna que pode ser fechada honestamente:

PassagemO que a acionaExemplo
TransferênciaO valor é um que esta política já mascara em alguma colunacustomer_name é mascarado, então note: "Ayşe Demir called" é mascarado também — inclusive entre linhas
RotuladoO próprio texto o marca: um título ou um rótulo de campoSn. Ahmet Yılmaz, Yetkili: Ayşe Demir, customer: John Smith
**O que isto não faz, deliberadamente: um nome simples em prosa corrente não é
detectado.** "Ahmet ligou ontem" passa. Capturar isso exige NER — um
modelo, um dicionário e uma pontuação de confiança — e cada decisão que este
gateway toma deve ser reproduzível apenas pela regra, por alguém que não
confia em nós. Um mascarador probabilístico também seria um recibo probabilístico. Ferramentas
que executam NER (as baseadas em Presidio, por exemplo) cobrem mais tipos de entidades; elas
compram isso com um limite de confiança. Nenhuma posição domina — esta é
declarada para que um auditor saiba qual delas está segurando.

Ainda não capturado por scanners de conteúdo — por design, não por omissão: endereços de rua e nomes simples. Um detector de endereços não consegue distinguir "Atatürk Caddesi No:15" de "Atatürk Barajı" sem um gazetteer. Um detector de nomes não consegue distinguir Deniz / Güneş / Umut das palavras. Ambos precisariam de um dicionário ou um modelo; este gateway's decisões são determinísticas. Feche essas lacunas com maskColumns (nomes de colunas) e conarium-suggest-policy (um palpite baseado em nome que não escreve sua configuração).

Endereços IP são capturados quando você os ativa (policy.detectors.ip: true). Eles estão desativados por padrão: um IP de servidor nem sempre é dado pessoal, e uma máscara que você não pode desativar quebra o trabalho de SOC. 1.2.3.4 é estruturalmente um endereço IPv4 válido; quando o detector está ativo, ele é mascarado, mesmo se você quis dizer um número de versão. Datas (13.08.2026) e valores (1.250,00) não são IPv4.

Números de passaporte em texto livre não são capturados. MRZ é: duas linhas TD3 × 44 caracteres, P na posição 1, dígitos verificadores 7-3-1. Uma falha de checksum não é um MRZ e é deixada de lado. TD1/TD2 não são implementados.

HTML &#64; / &#x40;, JSON \u0040, e %40 são mascarados quando estão dentro de um token em formato de e-mail. Um 5&#64; store ou C:\path\u0040abc isolado é deixado de lado. Uma passagem de decodificação; &amp;#64; não é perseguido.

Um TCKN dividido entre dois campos com nomes semelhantes na mesma linha (tckn_1 / tckn_2) é mascarado quando a concatenação passa no checksum. Colunas não relacionadas não são combinadas.

Caracteres de largura zero, dígitos de largura total / @, e travessões unicode são removidos ou mapeados para ASCII antes dos detectores — essa passagem não é um decodificador de codificação geral; tokens base64/hex embrulhados dentro de um campo são mascarados apenas quando decodificam para uma detecção existente do detector.

Comprimento da varredura. Um único campo de texto com mais de policy.scanCharCap (padrão 16 384; env CONARIUM_SCAN_CHAR_CAP substitui) é substituído por [MASKED_PII] como um todo, mesmo quando não contém um identificador. O scanner não é pulado: pular significaria que uma nota longa, blob JSON ou linha de log é o caminho para passar pela máscara. Esta é uma configuração de usabilidade. Aumentá-la cresce o custo de varredura quadraticamente — um campo alfanumérico de 40 KB levava ~1 s no regex de e-mail ilimitado antes que esse regex fosse limitado. maskedCount registra que uma decisão foi tomada.

O carry-over ignora valores com menos de três caracteres (um valor de dois caracteres corresponde em todo lugar e destruiria a saída) e corresponde em limites de palavras Unicode, então Ali é mascarado em Ali onayladı mas não dentro de Kalite.

Cobertura e reconciliação (detecção de bypass)

Recibos provam o que passou pelo gateway. Reconciliação pergunta ao banco de dados o que ele viu e compara:

Nenhum comando inventa suas entradas e conarium-init não as cria, então ambos respondem 20 (entrada ausente) até que você as tenha produzido: declaration.json é sua própria declaração de período e escopo (docs/RECEIPT-SPEC.md nomeia os campos), e os dois snapshots vêm 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

A linguagem é deliberada: ausência é relatada como "acesso NÃO REGISTRADO" / "não receitado", nunca "nenhum acesso ocorreu" — um registro ausente é ambíguo por natureza, e uma ferramenta que finge o contrário está mentindo para seu auditor.

Executado contra nosso próprio ERP de produção no dia em que foi lançado, incluindo um bypass real que realizamos em nós mesmos e a ferramenta capturou: docs/dogfood/2026-08-06-reconcile.md.

Esquema completo, códigos de saída e lacunas conhecidas: docs/RECEIPT-SPEC.md.

Co-assinatura (a parte que você não pode fazer por si mesmo)

Recibos provam o que passou pelo gateway. Reconciliação prova que nada passou ao redor dele. Ambos são seus, auto-hospedados e assinados por sua própria chave — que é exatamente o que um auditor desconta: você manteve o registro, você o assinou, e você o armazenou. Uma co-assinatura responde a isso colocando uma segunda parte na mesma cabeça da cadeia.

O serviço está neste pacote, então você pode executar o seu próprio e assinar suas próprias cabeças — útil para um segundo custodante interno e inútil contra a objeção acima. O que o torna valioso é que o signatário não é você.

# 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

O log é uma cadeia de hash: entradas são anexadas, nunca reescritas, e um carimbo de tempo OTS cobre a cabeça em vez de cada submissão. O que uma co-assinatura prova — e, igualmente importante, o que ela não prova — está escrito em docs/COUNTERSIGN.md, junto com o que uma chave de assinatura vazada custaria.

Pro é a co-assinatura hospedada — alguém diferente de você assina a cabeça da cadeia. $20/mês ou $200/ano — economize $40. Um período, não uma assinatura. Não renova sozinho — quando o período termina, o acesso termina e você pode comprá-lo novamente. Reembolso de 14 dias sem perguntas; depois disso, sem reembolsos parciais. IVA adicionado onde aplicável. O checkout ainda não está aberto: conarium.dev/buy redireciona para o formulário de lista de espera até que o caminho de pagamento entre no ar, então estes termos são o preço publicado em vez de algo que você pode pagar hoje. O binário acima é o que você executa sozinho; Pro é o segundo signatário. Enviado no pacote desde 0.2.16; o endpoint operado pela VERAX ainda não está aberto para clientes. O negócio permanece na lista de espera: reconciliação agendada, alertas de cobertura e o relatório de período assinado estão no contrato, ainda não enviados.

Implementando o formato você mesmo

O recibo é feito para sobreviver a esta implementação, então ele vem com vetores de conformidade — treze casos congelados mais um manifesto legível por máquina em test-vectors/:

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

Aponte seu próprio verificador para cada receipts.jsonl, passe os argumentos listados em manifest.json e compare o código de saída. expected-hashes.json fornece os hashes canônicos JCS → SHA-256 para que você possa verificar sua canonicalização sem precisar de nossa chave privada, que deliberadamente não é publicada.

Os vetores encontraram duas coisas neste repositório em sua primeira execução: uma verificação de esquema que relatou um recibo estruturalmente inválido como adulterado e uma suposição errada nossa sobre recibos não assinados. Ambos agora estão congelados como casos 007 e 008.

Ancorando sua cadeia (opcional)

conarium-stamp ancora um arquivo aos calendários OpenTimestamps, e conarium-anchor-upgrade preenche a altura do bloco Bitcoin quando ela chega. Esses dois são tudo que a maioria das configurações precisa.

Se você preferir expor a ancoragem como um pequeno serviço — para vários gateways, ou para dar a um auditor uma URL estável — bin/conarium-anchor-service.mjs é um: ele submete hashes, retém provas, serve o .ots bruto em um caminho permanente, e atualiza âncoras pendentes em um temporizador.

É código que você executa, não um serviço que operamos — não há instância hospedada para se inscrever. Ele também serve a prova bruta precisamente para que um terceiro possa verificar com o cliente OpenTimestamps de referência e ignorar o serviço inteiramente. Um endpoint de ancoragem que você precisa confiar derrotaria o propósito da ancoragem.

Assinatura é fail-closed: defina CONARIUM_AUDIT_SIGNING_KEY e/ou CONARIUM_AUDIT_HMAC_KEY, ou explicitamente CONARIUM_AUDIT_UNSIGNED=1 para configurações descartáveis. Rotação de chaves: mantenha PEMs públicos anteriores em CONARIUM_AUDIT_TRUST_PUBKEYS (, / ; separados). Após a primeira linha de auditoria assinada, toda linha posterior deve carregar sig.

Onde isto se encaixa entre projetos semelhantes

Conarium não é o primeiro projeto a produzir recibos assinados e verificáveis para atividade de IA. Acta, Emilia Protocol, AuthProof, Agent Receipts e Invariant SVR todos fazem uma forma disso, e alguns estão à nossa frente em padronização — Acta e Emilia ambos têm Internet-Drafts da IETF. Pesquisa relacionada: Aegon (arXiv 2604.06693), Decentralised Trust Layers (ACM Web Conf 2026) e ISO/IEC TS 27560:2023 para registros de consentimento assinados.

Esses recibos atestam o que um agente fez. Um recibo Conarium atesta o que o modelo foi impedido de ver — porque o componente que mascara os dados é o mesmo componente que assina o registro. Aplicação e evidência são uma parte aqui, não dois sistemas que precisam ser reconciliados.

O que defenderemos: Conarium é a única implementação que conhecemos que combina todos os três de (1) aplicação inline (política + mascaramento), (2) um recibo portátil e verificável offline dessa aplicação, e (3) reconciliação de cobertura — verificando os contadores de consulta do próprio banco de dados contra a cadeia de recibos, para que o acesso que contornou o gateway seja revelado em vez de permanecer invisível. Assinar recibos sem aplicar é comum; aplicar sem recibos portáteis é comum; reconciliar ambos os lados contra a contabilidade do próprio fonte de dados é a parte que não encontramos em outro lugar. Medido de ponta a ponta em um ERP ao vivo de uma empresa operacional real — 121.374 registros, 121.366 identidades mascaradas, 485.496 campos mascarados, zero vazados para o modelo (Relatório de Governança 001).

O que esse número é, e o que não é. Ele vem de uma execução em lote contra o ERP da nossa própria empresa, e o que o respalda é um arquivo de auditoria encadeado por hash de 123 linhas cuja aritmética você pode re-somar e cuja cadeia foi re-verificada 17 dias depois. O que não o respalda é uma cadeia de recibos: essa execução emitiu entradas de auditoria, não recibos portáteis assinados, e seu ator é uma identidade de serviço em lote, não uma pessoa. Então, se você perguntar "mostre-me os recibos desses 485.496 campos", a resposta honesta é que eles não existem — a cadeia de recibos é uma medição separada e muito menor. Escala e verificabilidade offline são duas afirmações diferentes aqui, e preferimos traçar essa linha nós mesmos do que você a encontrar. O mecanismo é verificável sem confiar em nós; esta figura particular é nossa própria medição, e Relatório de Governança 001 lista seus limites.

Essa afirmação é protegida de propósito, e docs/PRIOR-ART.md é a evidência por trás dela: onze projetos — dez verificados em 6 de agosto de 2026 e Vaara adicionado em 19 de agosto — o que cada um tem, o trabalho acadêmico anterior mais próximo (Sello / Notarized Agents, que nomeia essa lacuna melhor do que nós), e nove coisas que não pudemos verificar. Se você conhece uma implementação combinando todos os três, abra uma issue e ela será corrigida.

⚠️ A linha Vaara estreitou essa afirmação em vez de confirmá-la. Esse projeto especifica uma reconciliação de cobertura em seus documentos de design; uma busca em sua árvore não encontrou código executando-a, então a linha lê "especificado, não encontrado implementado". A ideia não é só nossa — o código em execução, até onde esta varredura alcança, ainda é, e o arquivo diz isso acima de sua própria tabela.


🏗️ Arquitetura (A Tríade)

Conarium opera em uma arquitetura tripartite estrita, equilibrando poder entre três 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. O Gateway: Um proxy que fala fluentemente com assistentes de LLM.
  2. O Motor: Avalia políticas JSON, varreduras regex e limites de linhas em milissegundos.
  3. O Ledger: Um log de auditoria à prova de adulteração registrando cada consulta e decisão que ele media.

Experimente sem um banco de dados

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

Inicia um servidor MCP local em linhas de amostra, não em um banco de dados. Uma tabela permitida retorna linhas com valores de email e cartão mascarados antes que as linhas saiam do portão; uma tabela negada é recusada; o limite de linhas é aplicado; chamadas permitidas e recusadas são registradas em uma cadeia assinada. Nenhum dos conectores incluídos é exercitado.

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

🚀 Início 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

O passo 3 não é decoração. Um arquivo de configuração ausente não interrompe o gateway — ele inicia com zero conectores e não governa nada — e um conector que falha ao conectar é registrado, não levantado. conarium-doctor nomeia ambos, sai com 1 quando algo está errado para que possa controlar uma implantação, e nunca imprime um segredo, então sua saída é segura para colar em um issue.

Da fonte em vez disso
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 recusa a sobrescrever arquivos existentes a menos que você passe --force. Ele nunca imprime a chave privada — apenas seu caminho.

Atalho de área de trabalho para o console

O editor de políticas é npx conarium-console. Ele ainda vincula 127.0.0.1 e ainda exige um token. Esses dois comandos apenas adicionam uma porta na área de trabalho:

npx conarium-console --install-shortcut
npx conarium-console --uninstall-shortcut
Windows.lnk na área de trabalho (janela do console minimizada)
macOS~/Applications/Conarium Console.app
Linux~/.local/share/applications/conarium-console.desktop

Um clique duplo inicia o mesmo console, aguarda até que a porta esteja escutando e então abre seu navegador. O token não é colocado na URL; um nonce de uso único (≤30s) é trocado por um cookie de sessão. Se um atalho com esse nome já existir, um sufixo -2 é usado em vez de sobrescrever.

Exporte CONARIUM_CONSOLE_TOKEN antes de --install-shortcut para que o lançador possa lê-lo de ~/.conarium/console.token (criado 0600). O arquivo de atalho em si não contém o token.

O atalho usa assets/conarium-mark.ico / .icns / -512.png, todos do mesmo SVG. Se esses arquivos estiverem ausentes, o atalho ainda é criado e o comando avisa.

A aba Makbuzlar do console lista recibos assinados de audit.receiptSink (mais recentes primeiro) e mostra o mesmo HTML de recibo que demo.conarium.dev/proof. Ela verifica a cadeia de hash e escreve zincir sağlam ou kırık (satır N). Se o destino estiver vazio ou não definido, ela informa isso — não inventa um recibo de amostra. Os Registros de Auditoria permanecem a trilha de playground não assinada; eles não são recibos.

Quando o pacote estiver no npm, os mesmos binários serão enviados no tarball (conarium-init, conarium-doctor, conarium-verify, conarium-suggest-policy). Até lá, execute-os a partir deste repositório como acima.

Antes de registrar um bug: execute o doctor

conarium-doctor verifica as coisas que falham silenciosamente. Duas delas importam mais: um arquivo de configuração ausente não interrompe o gateway — ele inicia com zero conectores e não governa nada — e um conector que não consegue conectar é registrado, não levantado, então o processo parece saudável enquanto não serve nada. O doctor também detecta o sidecar <pubkey>.keyid ausente, o que faz cada recibo verificar como 13 (parece adulteração, mas não é).

Ele sai com 0 quando limpo e 1 quando algo está errado, para que possa controlar uma implantação. Ele nunca imprime um segredo — senhas, tokens e material de chave são relatados apenas como forma (postgresql://appuser@db.internal:5432/prod (senha definida, não mostrada)), o que significa que a saída é segura para colar em um issue ou em um email.

Conarium fala MCP sobre stdio, então seu assistente de IA o lança como um comando. Adicione isso à configuração do seu cliente MCP (ex.: Cursor):

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

⚙️ Configuração (Política como Código)

Controle o acesso usando um arquivo de política conarium.json simples:

{
  "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"]
}

Qualquer coisa que não esteja em allowTables é negada por padrão; maskColumns correspondentes são redigidos para [MASKED_PII] antes que os dados cheguem ao modelo.

protectedColumns usa a mesma sintaxe de glob. Cada padrão também é mascarado no resultado. Além disso, essa coluna não pode aparecer em um predicado (WHERE, HAVING, JOIN … ON, ORDER BY, GROUP BY) ou em uma expressão SELECT derivada — a consulta é recusada. Um SELECT email simples ainda é permitido e retorna mascarado. Omita o campo e o comportamento permanece inalterado. Um perfil não pode defini-lo. mssql / oracle se recusam a iniciar se o campo não estiver vazio: esses portões não podem percorrer posições de predicado, e este produto não reivindica uma regra que não pode aplicar.

policy.dialect seleciona o portão SQL que a ferramenta query usa: postgres (padrão omitido), mssql, ou oracle. É a declaração do operador — Conarium não adivinha o dialeto a partir da declaração. Um erro de digitação ou mysql rejeita a configuração.

Conectores são fail-closed. allowConnectors é uma lista de permissões estrita: se estiver ausente ou vazia, nenhum conector é permitido (anteriormente uma lista vazia significava "permitir todos"). Se você configurar conectores, deve listá-los aqui — caso contrário, o servidor se recusa a iniciar e informa exatamente qual campo adicionar. denyConnectors ainda tem precedência sobre allowConnectors.

policy.detectors e policy.scanCharCap

Detectores de identidade — TCKN, cartão, IBAN, email — não podem ser desativados. Uma configuração que tenta (detectors: { tckn: false }) é rejeitada no carregamento. Esse é o produto: mascaramento que um banco pode desativar de um arquivo JSON não é mascaramento.

ChavePadrãoPorquê
detectors.ipfalseUm IP de servidor nem sempre é dado pessoal. Uma máscara sem interruptor de desligamento quebra SOC ("quantas solicitações deste endereço?"). Opte por ativar quando a coluna realmente for um endereço de cliente.
detectors.mrztrueUm MRZ de passaporte é identidade e tem dígitos verificadores. Desative na política base se você não lida com documentos de viagem.
scanCharCap16384Usabilidade. Campos mais longos que isso são substituídos inteiros ([MASKED_PII]), nunca pulados. Env CONARIUM_SCAN_CHAR_CAP substitui. Aumente e o custo de varredura cresce quadraticamente. Teto 1 048 576.
{
  "scanCharCap": 32768,
  "detectors": { "ip": true }
}

policy.customPatterns

Formatos que os detectores integrados não conhecem — um número de cliente bancário, um código de conta doméstica — podem ser registrados como regras extras no mesmo scanner. Este não é um segundo caminho de mascaramento e não substitui maskColumns.

Cada regra precisa de um nome (o que o recibo registra), um padrão, globs de coluna opcionais e um rótulo de máscara. Um sample opcional é o que conarium-doctor tenta contra o padrão compilado — sucesso na compilação não é uma captura. Um padrão quebrado ou em forma de ReDoS rejeita a configuração; o padrão e a amostra nunca são escritos em logs, recibos ou saída do doctor.

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

Quantificadores devem ser limitados ({8}, {4,12}). +, *, grupos aninhados e lookaround são rejeitados no carregamento. Uma regra nomeia um formato que você já conhece; ela não inventa um.

conarium-suggest-policy --sql schema.sql imprime um palpite de maskColumns a partir de nomes de colunas (*name*, *address*, *tckn*, …). Ele não escreve sua configuração. A primeira linha da saída diz isso.

🗺️ Roadmap

Conarium é acesso antecipado — e honesto sobre o que é real:

Enviando agora: gateway MCP governado (stdio + HTTP) · mascaramento determinístico de PII, incluindo nomes rotulados em texto livre · permitir/negar + limites de linhas · perfis de mascaramento por pessoa · livro-razão de auditoria com cadeia de hash à prova de adulteração · recibo assinado com Ed25519 por acesso uma vez que um destino de recibo esteja configurado, com um verificador offline · declarações de cobertura assinadas · reconciliação bidirecional contra os próprios contadores do banco de dados · ancoragem OpenTimestamps e um serviço de ancoragem opcional · vetores de conformidade · portão SQL: Postgres, Microsoft SQL Server, Oracle (MySQL não é implementado; sinônimos Oracle e links de banco de dados não são resolvidos — veja LIMITAÇÕES) · conectores Postgres, Supabase, docs, OpenAPI, Jira e Slack · conarium-init / conarium-doctor via npx (@conarium-ai/core).

Próximo: vinculação de consentimento (especificação publicada, sem código — revisão de patente primeiro) · uma segunda implementação independente do formato de recibo · identidade por usuário vinculada a um provedor de identidade em vez de um mapa de tokens do operador.

Deliberadamente não planejado, para que ninguém espere por isso:

  • Mascaramento "semântico" baseado em LLM. O portão é determinístico de propósito. Uma máscara probabilística faria um recibo probabilístico, que não é um recibo.
  • Console em nuvem hospedado. Auto-hospedado é a reivindicação; um console hospedado nos colocaria no caminho de dados que dizemos que não estamos.
  • Sem SOC 2 para nós. Nesta fase, a prioridade é teste de penetração independente e garantia em nível de implementação, em vez de certificação organizacional. Isso é sobre nossa certificação, não a sua: os recibos assinados e declarações de cobertura são seus para mostrar ao seu próprio auditor, e se eles satisfazem uma auditoria específica é entre você e esse auditor. Se algum dia tivermos seus dados, ou um engajamento depender do certificado em si, esta linha muda primeiro.
  • O selo de Melhores Práticas OpenSSF acima é autocertificação, não uma auditoria. Respondemos suas 67 perguntas e publicamos as respostas; qualquer um pode lê-las em projeto 14160 e verificar cada uma contra este repositório. Isso vale algo — as respostas são falseáveis — e não é o mesmo que alguém independente ter olhado. Três das 67 estão marcadas como não aplicáveis e explicam o porquê. O selo Scorecard ao lado é medido por máquina e inclui uma pontuação Code-Review de 0, porque pull requests aqui são mesclados sem um segundo aprovador.

Lacunas conhecidas: LIMITATIONS.md, o README acima, docs/RECEIPT-SPEC.md, docs/BENCHMARK.md, e docs/API-STABILITY.md.

📜 Licença

MIT — tudo isso, incluindo o verificador, as ferramentas de reconciliação e o serviço de ancoragem. Não há nenhum recurso retido para um nível pago; o código é MIT. O que conarium.dev vende é um segundo signatário (Pro) e, mais tarde, cobertura operada (Business — ainda não enviado) — não acesso ao código.