Verax
Verax: o corpo agente responsável. Portão, registro de decisão, recibo, reconciliação. Apache-2.0.
Documentação
Verax
O corpo que um agente consulta antes de agir.
Listado em: npm · Glama · MCP Registry · MCP Market · mcp.so · Docker Hub · Zenodo
Verax é um servidor MCP que fica entre um agente e suas ferramentas. Cada chamada de ferramenta passa por um portão de política e deixa um registro de decisão assinado antes que qualquer coisa seja executada; toda chamada que foi executada deixa uma linha de efeito que é reconciliada com seu registro depois. Uma recusa é registrada da mesma forma que uma aprovação. Uma chamada que a política não decide sozinha é retida até que um operador nesta máquina a aprove. O livro-razão permanece na máquina em que o corpo é executado, e o corpo só abre quando sua autorização está configurada: não há token padrão.
Quebre, e nós pagamos. USD 100 para cada relato válido de uma forma de a conta do agente ter uma chamada recusada permitida, executar uma chamada sem registro de decisão, ou alterar o código, chaves ou livro-razão do serviço. O orçamento é de USD 500 no total. Termos: SECURITY.md.
Por VERAX Teknoloji. Projetos irmãos: Conarium · Tugra · Cedulon. Os registros de decisão usam o formato de registro Cedulon.
Veja em execução
npx @verax-ai/body demo
A gravação é a saída de uma execução em um terminal onde a pergunta de
aprovação foi respondida y. Essa execução levou cerca de um segundo; é reproduzida
lentamente aqui para que possa ser lida.
O que imprime, sem um terminal para responder à pergunta de aprovação:
verax demo
memory.put / memory.get
allowed; two signed records
message.send -> ops@blocked.test
refused egress-blocked (signed)
ref 6c6e4925-b769-4a8b-8fc4-e2443613a5b6
spend 100 minor USD sample-merchant
held
no terminal to ask, so it stays held (run this in a terminal to be asked)
audit.explain of the refuse
finding none
trust-root own-key
chain and signatures read back
records 5
effects 3
ledger removed on exit (run with --keep to keep it and check it with verax verify)
Not shown here: data masking arrives with a downstream server such as Conarium; statement reconciliation needs a real statement (verax reconcile).
Node 22.6 ou mais recente, @verax-ai/body 0.2.1 ou posterior. O comando registra uma
escrita e leitura de memória permitidas, uma
recusa assinada de uma mensagem para um host fora da lista de políticas, e um pagamento retido
para o operador nesta máquina (aprovado quando o terminal responde y).
--keep deixa o livro-razão temporário no disco. verax verify <dir> o lê
de volta sem um corpo, como em Leia o livro-razão de volta sem nós.
As mesmas regras, animadas
Quatro episódios curtos mostram o mesmo portão, com personagens no lugar de um terminal. São cenários de exemplo: as cenas são desenhadas em three.js e as vozes são geradas com ElevenLabs.
Episódio 1, "$1.850": um pagamento é retido até que uma pessoa o aprove em um telefone, e mudar um centavo no registro quebra sua assinatura.
https://github.com/user-attachments/assets/772ae1c4-2697-47a0-a228-36f0508b0d93
Episódio 2, "Sem regra, sem passagem": uma chamada sem regra é recusada, a mesma chamada sob um novo nome é recusada novamente, e ambas as recusas são assinadas.
https://github.com/user-attachments/assets/4fb86627-3310-4f10-b1a9-059d8fcffb28
Episódio 3, "A alavanca vermelha": um operador interrompe o corpo, toda chamada posterior é recusada e assinada, e uma chamada que já estava em execução não é cortada.
https://github.com/user-attachments/assets/8d19eed9-3359-46b3-bd77-f2b1b1c4dd75
Episódio 4, "Quem aprovou?": um gasto retido espera por verax approve na
máquina, o agente não pode aprová-lo, e o id do operador do aprovador vai para
o registro.
https://github.com/user-attachments/assets/0b8aade4-a970-4b63-835e-4837e2a39cc9
Conecte seu agente
verax install e verax approve elevados executam uma cópia deste programa que apenas um administrador pode alterar; uma cópia que sua conta pode alterar é recusada. No Windows, um CLI elevado approve é a forma de aprovar até que o painel de passkey seja liberado. Ele deve ser executado a partir de uma conta de administrador separada, não desta conta elevada, porque um shell elevado do mesmo usuário herda as variáveis de ambiente e o perfil do PowerShell desse usuário, que o agente pode definir. Limpe NODE_OPTIONS nesse shell (Remove-Item Env:NODE_OPTIONS). Inicie o PowerShell da outra conta com -NoProfile (um shell elevado, caso contrário, executa seu $PROFILE, que sua conta pode alterar):
npm install -g --prefix "$env:ProgramFiles\verax-cli" @verax-ai/body
& "$env:ProgramFiles\verax-cli\verax.cmd" install
No Linux e macOS, com um Node de propriedade do root (o /usr/bin/node da distribuição, ou /opt/verax-node/<dir>/bin/node; o instalador imprime esses passos quando o Node a partir do qual foi iniciado pode ser alterado pela sua conta). Não inicie um comando elevado com env node:
sudo npm install -g --prefix /opt/verax-cli @verax-ai/body
sudo /usr/bin/node /opt/verax-cli/lib/node_modules/@verax-ai/body/dist/cli.js install
O comando instala @verax-ai/body do registro npm em um diretório de propriedade do administrador após verificações de assinatura, executa esse Node e mantém o livro-razão sob uma conta de serviço. No Windows, o token do agente é %ProgramData%\Verax\agent-token\<your SID>\agent.token (Administrators e SYSTEM têm controle total, seu SID pode ler o arquivo e ler-executar o diretório). No Linux e macOS, um processo filho executando como seu uid escreve ~/.verax/agent.token a partir de seu stdin. Ele imprime a linha do Claude Code que lê esse arquivo. Porta 8787 ocupada? verax install --port 8797. O Node deve ser o instalador para todos os usuários do nodejs.org no Windows; um Node que sua conta pode reescrever é recusado. No macOS, a correção extrai o tarball oficial como root em /opt/verax-node (root:wheel, não gravável por grupo ou outros). No Linux, o mesmo local, /opt/verax-node (root:root), que o SELinux rotula usr_t. Em sistemas SELinux, a instalação requer Node rotulado bin_t ou usr_t (o Node da distribuição é; um tarball sob /usr/local/lib não é) e imprime a correção de uma linha. O serviço então executa em unconfined_service_t. A conta de serviço e as permissões de arquivo são o limite.
Aprove uma chamada retida com verax approve. O painel de passkey (verax desktop) ainda não foi liberado. No Windows, execute a aprovação a partir de uma conta de administrador separada, não desta conta elevada, em um PowerShell -NoProfile após Remove-Item Env:NODE_OPTIONS: & "$env:ProgramFiles\verax-cli\verax.cmd" approve. Linux e macOS, nomeando o Node de propriedade do root: sudo /usr/bin/node /opt/verax-cli/lib/node_modules/@verax-ai/body/dist/cli.js approve ou sudo /opt/verax-node/<dir>/bin/node /opt/verax-cli/lib/node_modules/@verax-ai/body/dist/cli.js approve. Desinstale da mesma forma, com uninstall no lugar de approve.
Para experimentar em seu próprio usuário, que não é um limite:
verax init --local ~/.verax
verax serve --env-file ~/.verax/verax.env
claude mcp add --transport http verax http://127.0.0.1:8787/mcp --header "Authorization: Bearer $(cat ~/.verax/local-issuer/agent.token)"
O token pode ler e escrever memória através do portão; não pode aprovar. A política enviada recusa spend até que você adicione uma regra para ela; uma chamada que sua política retém espera por verax approve nesta máquina. Veja docs/THREAT_MODEL.md.
Com Conarium
@verax-ai/body 0.2.2 e posterior aceita --with-conarium. 0.2.1 não
carrega a flag. A flag tem npx baixar @conarium-ai/core do npm e
executá-lo como um processo filho; isso precisa de rede.
Conarium mascara as linhas, e sua política de exemplo nega sua tabela public.secrets.
Verax coloca cada chamada através do mesmo portão que suas próprias ferramentas, mantém um
registro assinado e um hash da resposta, e recusa uma ferramenta downstream que a
política não nomeia antes que o filho veja a chamada. Quando Conarium responde
com um erro, o corpo diz ao chamador que ele o fez, não o que ele disse.
O que imprime, sem um terminal para responder à pergunta de aprovação:
verax demo
memory.put / memory.get
allowed; two signed records
message.send -> ops@blocked.test
refused egress-blocked (signed)
ref 6c6e4925-b769-4a8b-8fc4-e2443613a5b6
spend 100 minor USD sample-merchant
held
no terminal to ask, so it stays held (run this in a terminal to be asked)
conarium.query customers
allowed; masked by Conarium before the rows left it
measured [MASKED_PII] on every email and card
conarium.query public.secrets
allowed by this gate; Conarium answered with an error and no rows
recorded as a failed call
conarium.list_tables
refused no-rule (signed)
refused by this gate; the downstream server never saw the call
audit.explain of the refuse
finding none
trust-root own-key
chain and signatures read back
records 8
effects 5
ledger removed on exit (run with --keep to keep it and check it with verax verify)
Not shown here: a real database (these are Conarium's sample rows); statement reconciliation needs a real statement (verax reconcile).
O que é enviado
| Pacote | O que é |
|---|---|
@verax-ai/body | O servidor MCP e o comando verax: serve, install, uninstall, init, doctor, approve, operator, reconcile, witness, halt, resume, unlock (desktop ainda não foi liberado). |
@verax-ai/proxy | O proxy de decisão sobre o qual o corpo é construído: política, registros assinados, livro-razão, explain, reconciliar. |
@verax-ai/inventory | O documento de roster que um corpo serve e as listas do painel, com seu parser estrito. |
Os três pacotes são publicados juntos e carregam a mesma versão; a
matriz de capacidades em docs/STATUS.md nomeia a atual,
e é a versão no npm. O corpo também está listado no registro MCP como
io.github.verax-ai/verax. O que essa versão carrega, o que não carrega,
e o teste que sustenta cada linha estão na matriz de capacidades no topo
de docs/STATUS.md.
Leia o livro-razão de volta sem nós
Um livro-razão que apenas o serviço em execução do fornecedor pode ler é evidência de que um comprador
aluga, não evidência de que ele possui. verax verify lê um diretório de
estado por conta própria — sem corpo ouvindo, nada na rede — e declara quatro
coisas separadamente, porque elas falham separadamente:
$ verax verify ./verax-state
ledger ./verax-state
decisions 6
effects 4 (4 bound to a decision, 0 with none)
signatures 6 verify, 0 do not
chain unbroken
verified with the key carried in these files
verified against the key carried in the records themselves: this
shows the files are internally consistent, not that the key was
ever trusted. Pin a key you hold to check that.
VERIFIED
Esse último par de linhas é o ponto. Verificar um livro-razão contra a chave
ao lado dele prova que os arquivos concordam entre si e nada mais —
qualquer coisa capaz de escrever o livro-razão poderia escrever essa chave também. Passe
--key <public.pem> para verificar registros de decisão contra uma cópia que você possui, e
a resposta diz a key you supplied em vez disso. Efeitos são assinados com uma
chave separada. Uma linha self é verificada sob a chave de efeito: --effect-key <public.pem>
quando você a fixa, caso contrário, uma chave tirada da primeira linha self. Uma linha same-org
é verificada sob a chave de testemunha: --witness-key <public.pem> quando você a fixa,
caso contrário, uma chave tirada da primeira linha same-org. Fixar --effect-key enquanto
uma linha same-org está presente requer --witness-key também, e fixar
--witness-key enquanto uma linha self está presente requer --effect-key também;
caso contrário, o resultado não é verificado. Cada uma dessas linhas diz a
mesma coisa: os arquivos concordam entre si, não que a chave já foi sua.
Checkpoints são assinados pela chave de testemunha. Cada linha de checkpoint é verificada sob uma chave: --checkpoint-key <public.pem> quando você a fixa, caso contrário, uma chave tirada do arquivo de checkpoint, com a mesma nota de que concordância não é confiança. A cauda conta apenas checkpoints cujas assinaturas foram verificadas. Alguém que pode reescrever os arquivos ainda pode reverter esse arquivo para um prefixo válido mais antigo junto com os registros depois dele; apenas um checkpoint mantido em outro lugar detecta isso. --json imprime
o mesmo resultado para um
pipeline; o código de saída é 0 quando verifica e 1 quando não, e um
diretório sem livro-razão nunca é sucesso silencioso.
Registros são COSE_Sign1 com algoritmo -19 (Ed25519, RFC 9864), não o
antigo -8 polimórfico (EdDSA). Algumas bibliotecas COSE não conhecem -19 ainda:
a partir de go-cose 1.3.0 e pycose 1.1.0, ambas o rejeitam, e o suporte é rastreado
em go-cose#224 e
pycose#126.
verax verify não depende de nenhuma das bibliotecas.
Verificadores além dos nossos
test-vectors/ é um conjunto congelado de livros-razão, cada um com
o veredito e o estágio que um verificador deve relatar. Duas pessoas executaram o conjunto
em vectors-v1 com verificadores próprios e publicaram os resultados:
- Tymofii Pidlisnyi (Agent Passport System), com um executor no conjunto de conformidade APS: uma comparação parcial, estágio por estágio, em todos os 16 vetores, não um veredito de livro-razão inteiro (execução).
- Roberto Locatelli (cryptovalid-opencore), com verificadores de sala limpa escritos a partir dos rascunhos, das RFCs e do README do vetor: com o checkpoint verificado sob a chave de testemunha, 16 de 16 vereditos e 15 de 16 primeiros estágios com falha. Uma dessas correspondências veio de uma regra adicionada após a leitura do vetor, como a própria execução afirma (execução).
Uma execução correspondente mostra que outro verificador lê essas codificações e alcança o mesmo veredito no mesmo estágio. Não é uma auditoria independente do corpo.
Instalação
npm install -g @verax-ai/body
verax --help
verax doctor
Em uma conta onde todo processo é elevado (o Administrador integrado, ou EnableLUA=0), um comando de um prefixo npm gravável pelo usuário é recusado; use a cópia de propriedade do administrador em %ProgramFiles%\verax-cli.
Node 22.6 ou mais recente. O corpo fala MCP sobre Streamable HTTP em /mcp na
VERAX_BIND (padrão 127.0.0.1:8787) e precisa de um emissor, uma URL JWKS, um
público, um diretório de estado e um arquivo de política antes de ouvir; verax doctor nomeia o que está faltando. As variáveis e os passos de execução estão em
packages/body/README.md.
Ferramentas
A política decide quais destas os escopos de um token podem chamar;
packages/proxy/policy/default.json nega o que não nomeia.
| Ferramenta | Descrição |
|---|---|
memory.get | Lê um item de memória atrás do portão, armazenado por locatário. |
memory.put | Grava um item de memória atrás do portão, armazenado por locatário. |
audit.explain | Lê uma decisão de volta do livro-razão assinado, com sua cadeia, suas assinaturas e suas conclusões. |
message.read | Lê a caixa de entrada. |
message.send | Grava na caixa de saída; alcança apenas hosts na lista de permissões da política. |
spend | Autoriza um pagamento e o registra, sob um limite, uma lista de beneficiários e um limite diário da política; retido para um operador quando a política assim determina. O corpo não movimenta dinheiro. |
O que o corpo faz além do portão
Cada linha abaixo é uma linha na matriz de capacidades em
docs/STATUS.md, onde é declarada contra uma versão,
com o que ela não faz e o teste que falha quando deixa de ser
verdadeira.
- Aprovação: uma chamada retida é aprovada com
verax approvenesta máquina. No Windows, isso é executado a partir de uma conta de administrador separada. O painel de chave de acesso (verax operator,verax desktop) ainda não foi liberado. O ID do operador aprovador é vinculado ao registro assinado por hash. - Testemunha:
verax witnessassina linhas de efeito a partir de um segundo processo e grava pontos de verificação duráveis; sem ele, a classe de testemunha permaneceself. - Parada e revogação:
verax halttransforma toda chamada adicional em uma negação assinada; um ID de token revogado é recusado antes que qualquer registro seja gravado. - Reconciliação:
verax reconcilecompara gastos registrados com uma exportação de extrato de cartão e nomeia as linhas correspondentes, fantasmas e autorizadas-mas-não-pagas. - Chave do locatário: memória e caixa de entrada são armazenadas sob uma chave derivada do emissor e assunto do token; o ID de outro locatário é respondido com uma negação assinada.
- Limites: contadores de taxa e diários, uma recusa por disco cheio (HTTP 507) quando uma negação não pôde ser registrada, e uma lista de permissões de saída; contadores que não podem ser lidos falham de forma segura.
- Doctor e heartbeat:
verax doctornomeia o que está ausente ou desatualizado antes que a primeira chamada descubra.
Observe o silêncio (árvore não lançada)
O corpo em execução pulsa mesmo quando ocioso (10 s por padrão;
VERAX_HEARTBEAT_EVERY_MS, mínimo 1.000 ms). Linhas de início em starts.jsonl
registram lacunas do batimento anterior; verax verify <stateDir> resume
elas offline. Linhas de início não são assinadas na v1.
verax watch ./verax-state --max-silence 30s
verax watch ./verax-state --once
verax watch --url https://host/healthz --token-file ./audit.token --once
verax watch ./verax-state --on-silence exec --exec "node isolate.mjs"
Um batimento ilegível, desatualizado ou muito no futuro é silêncio. Uma observação local para por
padrão; a recuperação nunca a retoma. Um operador deve usar o caminho de
retomada existente. Observação remota relata silêncio e não pode parar remotamente. Tokens
são lidos apenas de arquivos; HTTPS é obrigatório, exceto em loopback. Um comando
exec é executado uma vez por episódio de silêncio com VERAX_WATCH_REASON em seu
ambiente, sem shell. Cite executável/argumentos contendo espaços.
--once sai com 0 ao vivo, 3 silencioso ou 2 em erros de uso. Observação contínua imprime
uma linha JSON por episódio de silêncio e recuperação, sondando em max-silence/3.
Execute-o onde o operador escolher; um observador no mesmo host compartilha a confiança
desse host e não é evidência independente se tanto o livro-razão quanto o observador desaparecerem.
Conecte um cliente
O corpo escuta em http://127.0.0.1:8787/mcp por padrão. Uma configuração
de cliente se parece com isto; o token vem do seu emissor.
{
"mcpServers": {
"verax": {
"url": "http://127.0.0.1:8787/mcp",
"headers": { "Authorization": "Bearer <token from your issuer>" }
}
}
}
Status
O que a árvore carrega e o que permanece não comprovado é declarado, item por item, em
docs/STATUS.md. Nada neste repositório é uma afirmação
além desse arquivo, e um parágrafo lá não é um lançamento. O modelo de ameaças está
em docs/THREAT_MODEL.md; como relatar uma
vulnerabilidade está em SECURITY.md.
O que mais está na árvore
apps/panelé a tela de conta: a lista de registros, a caixa preta e a visualização de status, lidas do livro-razão assinado. Privada; não é publicada. A sessão do painel usa o fluxo de código; o token de acesso permanece na memória e é descartado na atualização. O Vite pode ainda anexarVERAX_DEV_TOKENde.env.locala/apiquando a solicitação não tem cabeçalho Authorization (cérebros MCP de desktop e testes).scripts/dev-issuer.mjsé apenas para desenvolvimento; não é um servidor de autorização de produção. Ele atendeGET /authorize(PKCE S256) ePOST /token, grava um token em--oute nunca imprime um. Ele escuta emVERAX_DEV_ISSUER_PORT(padrão 8790).NODE_ENV=productionsai.scripts/demo-box.mjsé apenas para desenvolvimento: um processo que inicia o emissor de desenvolvimento e o corpo em loopback com um livro-razão temporário, cunha para si um token de curta duração através do fluxo de código do emissor e fala MCP via stdio para um sandbox que não pode manter um token próprio, como uma verificação de build de um diretório. O corpo não é alterado por ele: toda chamada ainda passa pelo portão e é registrada,spendé sempre retido, e nenhum operador está lá para aprová-lo.NODE_ENV=productionsai. Não é uma implantação.
Desenvolvendo
npm ci
npm test # guards, typecheck, build, unit and cost suites, panel
npm run pack:smoke # pack the three packages and install them elsewhere
O CI executa a suíte como um usuário não root no Linux e novamente no Windows, além da
verificação de desempenho do proxy. Lançamentos saem da aba Actions:
release.yml publica os três pacotes com publicação confiável do npm e uma
atestação de proveniência, então mcp-registry.yml atualiza o registro
uma vez que o npm responde pela nova versão. Nenhum é executado em push.
Testado em cada lançamento nas plataformas listadas em docs/PLATFORMS.md, cada linha vinculada à sua execução de CI.
Licença
Apache-2.0.