RiskRouter evidence log
Endpoint MCP hospedado para um log de evidências à prova de adulteração. Sem uma chave, leia cabeçalhos assinados, provas de inclusão e consistência e checkpoints; com uma, registre o SHA-256 com salt de um registro de decisão. O registro em si nunca sai de você.
Servidor MCP hospedado
npx add-mcp 'https://api.riskrouter.eu/mcp'Instala no Claude Code, Codex, Cursor e outros
Documentação
Não há SDK para instalar e nada para licenciar. O mecanismo é um endpoint HTTP, a matriz de preços é publicada em outro, e o livro de auditoria é uma única tabela. Tudo abaixo roda contra a compilação de validação ao vivo agora mesmo.
Precifique uma configuração em uma única solicitação
Sem chave, sem conta, sem sessão. Envie uma vertical e os componentes que o cliente ativou. Você recebe um preço real. Registrar essa cotação no livro de auditoria é uma decisão separada, e é essa que precisa de uma chave — obtenha uma chave de sandbox agora, ou leia Chaves e a trilha de auditoria primeiro.
curl -X POST https://api.riskrouter.eu/api/v1/quote \
-H 'Content-Type: application/json' \
-d '{
"active_vertical": "urban_rental",
"selected_components": { "deposit_liquidity_swap": true, "smart_home_iot": true }
}'
Você recebe itens de linha precificados, um total, o estado normalizado dos componentes que o mecanismo usou e um relatório separado sobre se uma gravação de auditoria foi tentada e se foi concluída.
De um backend Node
const res = await fetch('https://api.riskrouter.eu/api/v1/quote', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
active_vertical: 'mobility',
selected_components: { commuter_roadside: true }
})
});
const quote = await res.json();
if (!res.ok || quote.ok !== true) throw new Error(quote.error?.code ?? \`HTTP ${res.status}\`);
// Show this. Never show a number your own code calculated.
const total = quote.quote.totals.total_monthly_premium; // "3.00"
// A 200 does not mean a record exists. Check the write separately.
// Without an API key this is false by design, not by failure.
const recorded = quote.persistence.persisted === true;
De Python
import requests
r = requests.post(
"https://api.riskrouter.eu/api/v1/quote",
json={"active_vertical": "micro_travel",
"selected_components": {"winter_sports_gear": True}},
timeout=10,
)
r.raise_for_status()
quote = r.json()
total = quote["quote"]["totals"]["total_monthly_premium"] # "6.00"
recorded = quote["persistence"]["persisted"] is True
Registre, exporte e verifique em cinco minutos, sem escrever para ninguém
Uma chave de sandbox registra cotações no livro real, exatamente como uma chave que emitimos manualmente. Você a obtém nesta página, uma vez. Não pedimos nada sobre você e não armazenamos nada sobre você: sem conta, sem e-mail, sem nome. Apenas um resumo SHA-256 da chave é mantido.
Sua chave está registrando e sua evidência confere?
Cole uma chave e esta página pergunta à API pela sua exportação, depois verifica aqui: se a chave é reconhecida, quantas entradas ela registrou, se a cadeia se conecta até o cabeçalho publicado e se assinamos esse cabeçalho. A chave é enviada apenas para api.riskrouter.eu, não é armazenada e desaparece quando você sai da página.
Precificação é aberta. Registro é atribuído.
O livro é à prova de adulteração: cada entrada sela a anterior. É isso que o torna valioso para um auditor, e também é por isso que o caminho de gravação não pode ser aberto. Uma entrada escrita por ninguém em particular é selada permanentemente, e removê-la depois quebraria todos os resumos seguintes. Então o mecanismo trata três casos de forma diferente, e o terceiro é o ponto.
| Você envia | Você recebe | Livro |
|---|---|---|
| Sem chave | Um preço real, imediatamente | Nada gravado. attribution.mode é ANONYMOUS |
| Uma chave válida | Um preço real | Registrado contra seu distribuidor, dentro da cadeia de hash |
| Uma chave inválida, revogada ou suspensa | HTTP 401, sem preço | Nada gravado |
Uma chave ruim é recusada de imediato e nunca rebaixada silenciosamente para uma cotação anônima. A alternativa parece mais amigável e é muito pior: um distribuidor cuja chave foi digitada errado ou revogada continuaria recebendo 200s por meses, acreditando que estava construindo uma trilha de auditoria, e descobriria durante a auditoria que nada havia sido gravado. Ruído agora é melhor que silêncio depois.
curl -X POST https://api.riskrouter.eu/api/v1/quote \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $RISKROUTER_API_KEY" \
-H "Idempotency-Key: order-4711" \
-d '{ "active_vertical": "mobility", "selected_components": { "commuter_roadside": true } }'
// Two different questions. Ask both.
const priced = quote.ok === true; // is this number real
const recorded = quote.attribution.recorded === true; // is it in the ledger
Armazenamos o SHA-256 da sua chave, nunca a chave. Isso significa que não podemos mostrá-la novamente, não podemos enviá-la por e-mail e não podemos recuperá-la se você a perder — só podemos revogá-la e emitir outra. Também significa que uma violação do nosso banco de dados não dá a ninguém a capacidade de escrever na sua trilha de auditoria.
As chaves são por ambiente. Uma chave de sandbox e uma chave de produção são linhas separadas e resumos separados, então uma cotação de teste nunca pode cair em um livro de produção por acidente.
Obtendo sua evidência de volta
A mesma chave a exporta. Este é o endpoint para conectar a um trabalho mensal no primeiro dia, não no dia em que você precisar.
curl -s -H "Authorization: Bearer $RISKROUTER_API_KEY" \
https://api.riskrouter.eu/api/v1/ledger/export > "ledger-$(date +%F).json"
Você recebe suas entradas completas, o esqueleto de resumo de toda a cadeia em que estão inseridas e a atestação assinada para o cabeçalho. Dois scripts Node da biblioteca padrão verificam todos os três, offline, sem chave nossa e sem chamada para nós — clone github.com/aniljangrabe-dev/riskrouter-verify, um repositório público separado que não compartilha código com este:
git clone https://github.com/aniljangrabe-dev/riskrouter-verify
node riskrouter-verify/tools/verify-attestation.mjs ledger-2026-09-20.json # we signed this head
node riskrouter-verify/tools/verify-ledger.mjs ledger-2026-09-20.json # your entries produce it
Guarde-os. Uma exportação que você baixou no ano passado ainda verifica depois que pararmos de atender o telefone, que é a única resposta honesta para o que acontece com minha trilha de auditoria se vocês falirem. É também por isso que não há SDK e nada para licenciar: um produto difícil de deixar é um produto que precisa ser, e preferimos não precisar disso.
Código funcional na linguagem em que seu produto é escrito
Cada exemplo precifica uma cotação, registra-a com uma chave de idempotência e tenta novamente sem registrar duas vezes, registra uma impressão digital salgada de uma nota de demandas e necessidades, exporta a evidência e prova uma entrada. Apenas biblioteca padrão, sem SDK para instalar, e cada um é executado a cada mudança contra o mecanismo real, com sua saída verificada por dois verificadores independentes.
- Python: riskrouter.py, signer.py (assine suas próprias reivindicações), demo.py
- PHP: RiskRouter.php, demo.php
- C# (.NET 8): RiskRouter.cs, Program.cs, RiskRouterDemo.csproj
- Java: RiskRouterDemo.java
- Aplicativo de referência: app.py, uma mesa de corretor de arquivo único que mantém a nota do cliente do seu lado e produz um pacote de evidências que um inspetor pode verificar offline com check_pack.py.
- Verificador: riskrouter_verify.py, Python de biblioteca padrão, independente de tudo mais aqui. Como usar o kit: README.
- Uma página de verificação com sua própria marca: verifier-page.mjs escreve um arquivo HTML, com seu nome e cor, que verifica um recibo ou uma divulgação no navegador do seu cliente e cuja política de segurança proíbe qualquer solicitação de rede. example-brand.json
Evidência de onde suas decisões já são registradas
Se seu sistema já registra suas decisões, através do logging do Python, através de spans do OpenTelemetry, ou através de uma função que retorna uma decisão, um gravador transforma isso em evidência sem um projeto de integração. Ele canonicaliza cada registro, o salga e o mantém, com seu sal, em um diário do seu lado; apenas o resumo e o tipo são enviados, em lotes, para este log, para sua própria instância, ou para nenhum. Um registro é gravado no diário antes que seu resumo seja enviado, então uma interrupção nunca o perde, e é marcado como registrado apenas quando o log diz isso. Sem dependências, e nunca uma condição para usar a API.
# Python: a log line with extra={"evidence": record} becomes evidence
log.addHandler(EvidenceHandler(Recorder(api_key=KEY, journal="evidence.jsonl")))
log.info("referred", extra={"evidence": {"kind": "ai.decision", "record_id": "dec-2292", "outcome": "refer"}})
// Node: OpenTelemetry spans with evidence.kind become evidence
provider.addSpanProcessor(new EvidenceSpanProcessor(createRecorder({ apiKey: KEY, journal: './evidence.jsonl' })));
- Python (3.8+, biblioteca padrão):
pip install riskrouter-recorder, ou os arquivos: riskrouter_recorder, com um manipuladorlogging, um decorador e um processador de spans do OpenTelemetry, e agents.py. README - Node (20+, sem dependências):
npm install riskrouter-recorder, ou os arquivos: recorder.mjs, comwithEvidencee um processador de spans do OpenTelemetry; agents.mjs e mcp-server.mjs. README
Agentes de IA. Os mesmos pacotes carregam adaptadores para os frameworks com os quais os agentes são construídos: um manipulador de callback para LangChain e LangGraph (Python e JavaScript) e um processador de rastreamento para o OpenAI Agents SDK (ambas as linguagens). Cada execução de agente se torna um registro, com suas chamadas de ferramenta, chamadas de modelo, transferências, guardrails e nós de grafo como etapas; cada etapa mantém um SHA-256 do texto que manipulou, não o texto. Um servidor MCP dá a qualquer cliente MCP uma ferramenta record_decision; o que ele registra é a própria declaração do agente, e diz isso.
# LangGraph: every run of the graph becomes one record
graph.invoke(state, config={"callbacks": [EvidenceCallbackHandler(recorder, fields={"system_ref": "claims-agent"})]})
// OpenAI Agents SDK (JavaScript)
addTraceProcessor(new EvidenceTracingProcessor(recorder, { fields: { system_ref: 'claims-agent' } }));
bundle(record_digest) dá a você o registro, seu sal e a prova, que um supervisor verifica offline com qualquer verificador. Ambos os gravadores são testados a cada mudança contra o mecanismo real e os SDKs reais de OpenTelemetry, LangChain, OpenAI Agents e MCP. Eles são licenciados sob Apache-2.0, como os verificadores, a suíte de conformidade e o kit de integração acima. Ambos são publicados como riskrouter-recorder, no PyPI e npm; os arquivos acima são o mesmo código, se você preferir copiá-los.
Nada deixado de fora. Dê a um gravador um segredo de cadeia e cada registro entra em uma cadeia de completude numerada: o gravador adiciona os campos de cadeia ele mesmo e continua do seu diário após uma reinicialização, e completeness() retorna a lista assinada do log da cadeia com cada registro nela, pronta para um auditor verificar que nenhum está faltando.
recorder = Recorder(chain_secret=os.environ["RISKROUTER_CHAIN_SECRET"], chain="kyc-desk")
No OpenTelemetry Collector. otlp-sealer.mjs recebe OTLP/HTTP JSON de um Collector como qualquer outro backend, e transforma spans e registros de log que carregam evidence.kind em registros, sem biblioteca dentro do aplicativo. Um lote é respondido apenas quando está no diário, então o Collector tenta novamente qualquer coisa não mantida.
RISKROUTER_API_KEY=... node otlp-sealer.mjs --port 4319 --journal /var/lib/evidence/journal.jsonl --chain otel
Arquivos mantidos em outro lugar. Um registro pode nomear um arquivo que não contém, como uma gravação de chamada, uma fatura ou um lançamento: digest_file(path) em Python, digestFile(path) em Node, transmite seu SHA-256 e o arquivo permanece onde está.
Logs de segurança. logseal.mjs sela qualquer fluxo de log (journalctl, tail -F, um relay syslog) segmento por segmento, então após um incidente você pode mostrar que nenhum segmento selado foi alterado ou removido. Os segmentos permanecem no seu próprio arquivo. Logs de segurança selados
Conecte um agente de IA via MCP
O log de evidências fala o Model Context Protocol, então um assistente de IA ou framework de agente pode ler o log, buscar provas e registrar resumos sem que ninguém escreva uma integração. Adicione este servidor a qualquer cliente MCP:
https://api.riskrouter.eu/mcp
{ "mcpServers": { "riskrouter": {
"type": "http", "url": "https://api.riskrouter.eu/mcp",
"headers": { "Authorization": "Bearer <your key, only to record>" } } } }
Ler não precisa de chave. record_evidence recebe o SHA-256 de um registro que você mantém e um tipo curto, nunca o registro, e precisa da sua chave; uma chave de sandbox leva um minuto. Cada ferramenta é a mesma rota da referência da API, com as mesmas verificações. Não há ferramenta de precificação. Para registrar de dentro do processo do próprio agente, com o registro mantido no seu diário, use o servidor MCP local e os adaptadores de framework acima. A configuração de cada cliente em um só lugar: Agentes e assistentes de IA.
Escolha o que corresponde ao seu apetite de risco
1. Chame a API do seu backend
Seu servidor chama o nosso, sua interface renderiza o resultado. Você mantém controle total do relacionamento com o cliente e nunca vemos seu padrão de tráfego ou seu cliente. É o que escolheríamos. Chamadas de origem cruzada de um navegador são restritas ao nosso próprio console, então este padrão é servidor-para-servidor por design.
2. Vincule ao console hospedado
Aponte um cliente para o console de demonstração para configurar a cobertura e devolva a referência da cotação ao seu fluxo. A coisa mais rápida de montar, e o menor controle: a página é nossa, então sua aparência e texto mudam quando os nossos mudam.
3. Execute tudo você mesmo
Três arquivos e uma tabela. Implante o mecanismo na sua própria conta Cloudflare, aponte-o para seu próprio banco de dados, e não estamos mais no caminho. O código-fonte não é público hoje, então isso começa pedindo-o a nós. Coberto em Execute você mesmo abaixo.
Pergunte ao mecanismo o que ele cobra
Não codifique a lista de preços. GET /api/v1/verticals publica cada vertical, sua camada base obrigatória e seus módulos opcionais, com os preços que o mecanismo realmente aplicará. Construa sua interface a partir dessa resposta e uma mudança de preço nunca dessincroniza seu checkout da cotação.
const { verticals } = await (await fetch(BASE + '/api/v1/verticals')).json();
for (const v of verticals) {
renderTab(v.key, v.label, v.description);
renderLocked(v.base); // mandatory, always on
v.addons.forEach(renderToggle); // optional modules
}
Se você precisar armazenar em cache, faça com expiração e verifique novamente ao carregar. Nosso próprio console mantém uma cópia incorporada para a primeira pintura e hidrata deste endpoint imediatamente, e um teste falha a compilação se os dois discordarem.
Lide com estes seis antes de lançar
Cada um queimou uma integração real em algum lugar. São baratos de lidar agora e caros de descobrir em uma auditoria.
| O que acontece | O que fazer |
|---|---|
| Retorna 200, mas nenhum registro de auditoria foi gravado Você não enviou chave alguma, ou o ledger estava temporariamente inacessível. | Leia persistence.persisted. Mostre o preço, mas nunca diga ao cliente que a cotação está registrada, a menos que esteja literalmente em true. persistence.attempted distingue as duas causas. |
| O cliente alterna rapidamente As respostas chegam fora de ordem e um preço desatualizado chega por último. | Marque cada solicitação com um número crescente e ignore qualquer resposta mais antiga que a mais recente que você já exibiu. Aborte a solicitação anterior. |
| Você envia um componente que não precificamos Seu build está à frente do nosso, ou atrás. | Verifique ignored_components em cada resposta. Ele nunca fica vazio por acidente, então trate qualquer conteúdo como incompatibilidade de implantação e alerte sobre isso. |
| Retorna 401 onde antes retornava 200 Sua chave foi revogada, ou seu distribuidor foi suspenso. | Trate como uma indisponibilidade, não como erro de validação, e acione alguém. Não remova a chave e tente novamente: isso transforma uma falha ruidosa em silenciosa, e toda cotação posterior desaparece do seu trilho de auditoria. |
| O motor não responde Falha de rede ou timeout. | Defina um timeout de cliente de alguns segundos. Não recorra a um preço calculado localmente: mostrar um número que não produzimos é como um cliente recebe uma cotação que você não pode honrar. |
| Você tenta novamente uma cotação registrada após um timeout A primeira tentativa pode ter sido gravada antes da conexão cair. | Envie um cabeçalho Idempotency-Key — sua própria referência de pedido ou sessão serve — e reutilize-o em cada nova tentativa dessa cotação. A mesma chave registra no máximo uma entrada, e uma nova tentativa recebe essa entrada de volta com persistence.replayed: true. Sem ele, uma nova tentativa pode deixar uma segunda entrada permanente em um ledger append-only que diz que a cotação foi dada duas vezes. A mesma chave para uma cotação diferente é recusada com 409; use uma chave nova para uma cotação nova. |
O que o motor recusa
| Limite | Valor | Ao violar |
|---|---|---|
| Corpo da solicitação | 16 KB | 413 PAYLOAD_TOO_LARGE |
| Timeout de gravação no ledger | 5 s | A cotação ainda retorna, marcada como não persistida |
| Gravações no ledger, todos os chamadores | 120 / min | A cotação ainda retorna, marcada como não persistida |
| Origens do navegador | somente console | Bloqueado pelo navegador, não por nós |
O teto de gravação é deliberadamente compartilhado, não por chamador. O ledger recusa exclusão, então uma enxurrada seria dano permanente, e um limite que um chamador não consegue contornar vale mais do que um generoso que pode ser contornado.
Execute você mesmo
A plataforma são três arquivos: um esquema SQL, um Cloudflare Worker e um console de página única. Não há runtime proprietário e nada faz phone home. Montar sua própria cópia leva cerca de dez minutos depois que você tiver o código-fonte. Esse código-fonte está hoje em um repositório privado (o verificador, os gravadores e os kits são o que está publicado), então peça-o a nós; se executá-lo sem nós for uma condição do seu piloto, combine como você o obteria antes de o piloto começar. Veja o plano de continuidade e saída.
# 1. Create the audit ledger in your own Postgres or Supabase project
psql -f schema.sql
# 2. Point the engine at it and deploy to your own Cloudflare account
wrangler secret put SUPABASE_SERVICE_ROLE_KEY
wrangler deploy
# 3. Publish the console
npm run deploy:console
A matriz de classificação vive em um único objeto congelado no topo do Worker. Altere um preço lá, execute os testes, faça o deploy. A suíte de testes recalcula cada prêmio a partir da matriz e falha se o console ou a documentação discordar dela.
Preferimos que você possa sair a ficar preso. Uma integração da qual você pode se afastar é uma na qual você pode se comprometer.
O que você traz
RiskRouter é infraestrutura. Ela não torna ninguém um distribuidor de seguros e não substitui o que os reguladores esperam que você possua.
- Seu próprio registro FSMA, ou o equivalente no seu estado-membro
- Uma seguradora ou pool de subscrição disposto a respaldar a cobertura
- Seu próprio processo de aprovação de produto e de demandas e necessidades sob a IDD
- Seus próprios termos voltados ao cliente e os documentos de apólice correspondentes
Fornecemos o roteamento, a determinismo de preços e o trilho de auditoria. A posição regulatória explica onde fica o limite e por que ele é traçado ali.