O que deixa comprovante
Cada bloco que uma leitura de contexto acrescenta com
include (restrições, estado, coordenação e orçamento) deixa um comprovante próprio, ao lado do do contexto, com a versão do bloco e as contagens, nunca um valor; as leituras de estado tipado e as perguntas e declarações da coordenação entram na mesma trilha, sem o handle. As liberações de conteúdo, as inferências corrigidas ou apagadas, os pedidos de revisão e as retenções legais entram como admin, com a ação e o alvo.
Mudanças de identidade, apagamentos, exportações, cortes de fonte, retiradas de padrão, simulações e vereditos de revisão caem na mesma trilha das leituras; as mudanças do plano de controle também chegam à cadeia de cada espaço como comprovantes admin: cada configuração aplicada (config.applied, com a versão do instantâneo e o resumo do documento; quem propôs e quem aprovou fica no histórico versionado do plano de controle), cada chave emitida, alterada ou revogada (key.issued, key.updated, key.revoked, com o alvo key:<id da chave>:source:<id da fonte>, que diz de qual fonte é a chave) e cada mudança de acesso das pessoas e do SSO (convites, papéis, desativações, redefinições de segundo fator, conexões de SSO, pessoas criadas e papéis sincronizados num login por SSO), que a célula busca do plano de controle a cada 15 s por um feed assinado e grava uma vez em cada espaço do tenant, só com ids. O ator desses comprovantes é o plano de controle. O comprovante de uma ação de uma pessoa guarda o id dela (person_id), e a leitura devolve ao lado o e-mail (person_label), que fica fora da cadeia, como o pseudônimo do perfil (pseudonym): qualquer papel que lê comprovantes lê o nome.
Um comprovante denied guarda quem tentou, em qual superfície (pack, search, timeline, open ou object) e por quê, em detail.reason: scope_missing (a chave não tem o escopo da rota), forbidden (a finalidade da fonte não cobre aquele tipo de objeto, a navegação está desligada para a fonte, a ferramenta MCP não é oferecida a ela ou o token pertence a outra fonte), verification_not_allowed (o nível pedido não vale para a fonte: acima do teto dela, ou no_customer fora de um agente interno) ou about_without_link (a leitura em nome de uma organização sem vínculo ativo). O que foi pedido nunca entra: nem o cliente, nem a consulta. Uma chave desconhecida nunca chega à corrente de um espaço, então ninguém de fora consegue enchê-la. Num comprovante admin, detail guarda a ação (action), o alvo (target, quando há um) e os papéis da pessoa ou o id da chave que agiu.
O que um comprovante guarda
manifest_hash aponta para o manifesto de origem daquela entrega, que registra:
- cada item incluído, com o evento de onde veio e, quando a memória o registrou, de quem são as palavras dele (
spoken_by:customer,mixedoucompany), se são as palavras do próprio cliente sobre si para este leitor (own_words) e a regra que o liberou acima do nível mínimo da categoria (rule: mirror, o espelho); a releitura na hora da entrega decide com os mesmos dados que o compilador; - cada exclusão, com o motivo:
policy,verificationouquarantinequando a política reteve o item,budgetquando ele não coube no orçamento (com a regra que decidiu:budgetpara um item de valor que não coube,low_valuepara um abaixo do valor mínimo,skeletonpara uma linha que espera na reserva pelos encaixes do turno,viewpara uma seção que a view não traz eduplicatepara uma pendência que outra já diz ou um fato que uma conversa fixada no esqueleto já diz) eunusedquando a fonte não usa aquele tipo de item (Contexto mais enxuto por agente); - as versões do compilador, do modelo de texto, da política e do extrator;
- tokens por seção e a decisão de cache de prompt.
O comprovante dos encaixes
Uma leitura comquery deixa um segundo comprovante read, na superfície slots, com o que o turno escolheu da memória. detail.slots é o manifesto dos encaixes, em JSON canônico:
budget, os tokens que os encaixes do turno podiam somar, ebudget_rule, a regra que fixou esse orçamento:question, quando o turno pediu um valor (um número que ele nomeia ou um tipo de valor), uma contagem ou um dia, outurn, em qualquer outro turno. Na voz,questionvale 100 tokens e até três linhas,turn60 e duas; nas outras views a regra é registrada e o orçamento é o da view;tokens, o que os encaixes somaram, eitems, cada encaixe comid,kind,channels,position,tokense, num valor,value_type;derived, os tipos das linhas derivadas;channels, por canal, quantos acertos houve e se ele perdeu o prazo (skipped); eguards, quando houve, comid,value_typee o braço (arm) do grupo de controle.
detail.why diz por que cada encaixe entrou. Cada item traz id, a posição e a contribuição de cada canal, a pontuação fundida e, quando valem, excerpt: true (a linha foi cortada às frases que respondem ao turno) e atom: true (a conversa entrou como o átomo dela: o assunto e o valor que respondem ao turno, numa linha curta). Os dois só aparecem quando são verdadeiros, e uma linha nunca é as duas coisas. Uma linha derivada traz rule, a regra que a escreveu, e o que ela contou: a contagem pelo assunto que a extração nomeou escreve count_matter ou count_matter_complaints, com units, matched, matters (quantas chaves de assunto entraram na contagem), counted e window_days; a contagem pelas palavras, count_topic ou count_topic_complaints, com units e matched. Uma promessa cumprida nos últimos 7 dias, que o contexto mantém entre as pendências dizendo quando foi cumprida, entra no manifesto como qualquer pendência: um item open_item da seção pending, sem campo próprio; o que a distingue é a linha do contexto. Nada disso guarda as palavras nem o número: o mesmo turno sobre a mesma memória escreve o mesmo manifesto. A resposta de POST /v1/context com explain: true traz em pack.slots[].why a mesma posição, contribuição e pontuação e o excerpt; budget_rule e atom ficam só no comprovante.
Os comprovantes da navegação também registram a consulta, por HMAC com a chave do espaço, os ids dos itens devolvidos e quantos ficaram retidos. Uma busca ou uma linha do tempo com filtros guarda também um HMAC dos filtros enviados, com a mesma chave, em detail.filters_hash: o comprovante prova quais filtros foram pedidos sem guardar o que eles dizem, e detail entra na corrente como o resto.
A corrente
Comprovantes só crescem. Cada um traz a própria posição (seq) e o hash do anterior (prev_hash), encadeados por espaço, por fatia e por dia. detail entra no hash como o resto; um comprovante sem detail tem o hash que sempre teve, então os comprovantes antigos continuam conferindo. Um espaço pequeno tem uma fatia; um grande tem até 16, escolhidas pelo perfil, para que o espaço mais movimentado grave sem gargalo único.
Uma vez por dia, quando todo comprovante daquele dia já foi gravado, as cabeças das fatias são combinadas numa raiz de Merkle. A raiz fica no banco da célula e numa cópia fora dele, num armazenamento de gravação única (S3 com Object Lock em modo de conformidade): a cópia só é gravada se ainda não existe e fica retida por cinco anos, e ninguém, nem a própria célula, consegue apagá-la ou trocá-la antes disso. Alterar qualquer comprovante passado quebra todos os hashes seguintes e deixa de bater com a raiz, e reescrever comprovantes, cabeças e a raiz no banco ao mesmo tempo ainda deixa de bater com a cópia.
A exportação de auditoria: a raiz na sua própria cadeia
A Niadra não guarda uma segunda cadeia de auditoria para o que os agentes fizeram: ela entrega a dela à sua. O evento diárioaudit.root, por webhook ou pelo feed de avisos, leva a raiz dos comprovantes do dia e, num espaço que grava registros de turno, a raiz do índice da camada guardada (turns.root, com turns.count): cada turno guardado no dia tem uma linha (o id do turno, a fonte, o agente, o tipo, a hora, o modo de conteúdo e o hash da build) com o digest SHA-256 dela, e os digests, em ordem de id do turno, dobram-se numa raiz de Merkle com os prefixos da RFC 6962, um nó ímpar subindo sozinho. Só digests e contagens saem: nunca o que um turno leu ou disse.
GET /v1/turns/index/{day} lista as linhas de um dia UTC com os digests, por cursor, para a sua empresa recalcular turns.root, e GET /v1/receipts/verify recalcula a raiz dos comprovantes, para conferir as duas e ancorá-las onde quiser. Uma linha que vence ou é apagada depois deixa a raiz ancorada como estava: a raiz prova o que o dia teve, não o que ainda existe. O índice pede uma chave com o escopo replay ou uma pessoa com o papel integration ou security, e a funcionalidade turns. O webhook receipt.recorded entrega os elos da corrente (fatia, dia, seq, prev_hash e hash) assim que o gravador os guarda, para quem prefere manter a cópia em tempo próprio. Nenhum dos dois leva o que foi lido.
Nenhuma leitura sai sem comprovante. A fila confirma o comprovante em até 20 ms; quando não confirma, ele vai para o banco da célula como uma tarefa de gravação, que o escreve na corrente pelo menos uma vez e sem duplicar, porque o id do comprovante é único. Só quando os dois caminhos falham ele espera na memória do processo; com esse acúmulo cheio, as categorias sensíveis param de sair, e, com o dobro, as leituras param até os comprovantes serem gravados.
Uma conferência rápida de continuidade sobre uma página de uma fatia:
GET /v1/receipts/verify?day=2026-09-22 percorre todas as fatias daquele dia e responde valid, o número de receipts, as cabeças de cada fatia em heads, as quebras que achou em breaks, se a raiz recalculada bate com a ancorada (root_matches), se a cópia de fora do banco guarda a mesma raiz (anchor_copy_matches) e se essa cópia está no armazenamento de gravação única (anchor_locked). valid só é verdadeiro sem quebras e sem divergência da raiz ou da cópia. Enquanto o dia não foi ancorado, esses três campos vêm nulos; anchor_copy_matches também vem nulo quando a cópia não pode ser lida naquele momento, e falso quando ela falta ou guarda outra raiz.
As rotas de comprovante são rotas de governança: uma pessoa do Console com o papel security, ou uma chave de escopo admin. Filtre a lista por profile_id, conversation_id, source_id, kind e por uma janela since/until, e pagine com cursor, no corpo de POST /v1/receipts/search: um id de conversa pode ser um telefone ou um e-mail, e fica fora da URL. GET /v1/receipts aceita os mesmos filtros na query e continua. Cada comprovante da resposta traz, ao lado do profile_id, o pseudonym do perfil, o nome a mostrar a uma pessoa; ele vem do perfil na hora da leitura e não faz parte do comprovante encadeado.
Três perguntas que os comprovantes respondem
Por que o agente disse X? Às 14h07, o agente de voz disse à Marina que o crédito de 40 já tinha sido lançado. O comprovante decall-4471 lista, entre os itens entregues, o id da ação do agente de cobrança das 14h06 (0192f7a2-9d52-7f4b-8a6e-3d5f7a9b1c24); o manifesto mostra que ela veio da ação credit sobre invoice:erp:0823, confirmada pelo evento do ERP. Comprovante, manifesto, item, evento: quatro passos da frase até a origem. GET /v1/lineage/receipt/{receipt_id} percorre esses passos por você e devolve o comprovante, os itens entregues com a origem de cada um e as exclusões.
Quem viu o fato F? GET /v1/lineage/fact/{fact_id} devolve cada comprovante cuja entrega levou aquele fato: cada fonte que o recebeu, com finalidade, nível e horário.
O que foi retido, e por quê? withheld diz quantos itens a política segurou; o manifesto diz qual motivo valeu para cada um (policy, verification ou quarantine). O agente fica sabendo só da contagem, nunca do conteúdo, e entende que verificar o cliente libera mais. A pergunta inversa também tem resposta: um item que um leitor em V1 viu numa categoria que pede V2 leva rule: mirror no manifesto, a prova de que ele viu o que o cliente mesmo disse, não o que a empresa guarda sobre ele.
Comprovantes no seu SIEM
Os comprovantes chegam ao seu SIEM segundos depois de entrar na corrente, pelo mesmo mecanismo de entrega dos webhooks. O fluxo é um endpoint no documento de configuraçãowebhook-endpoints, mudado por um diff aprovado, com format:
ocsf: um evento OCSF 1.3 de API Activity (class_uid6003) por comprovante, um JSON por linha (application/x-ndjson);hec: o mesmo evento dentro do envelope de um HTTP Event Collector (time,source,sourcetypeniadra:ocsf:api_activityeevent), também um por linha.
event_types vão os tipos de comprovante (read, history, analytics, admin, holdout, denied, agent_memory) ou * para todos. O segredo de assinatura e, se o coletor pedir, o token que segue no cabeçalho Authorization (como Splunk <token>) são gravados no cofre da célula por PUT /v1/secrets/webhook/{id}, e o documento aponta para eles como spaces/<id do espaço>/webhook/<id>, em secret_refs e em authorization_ref. Toda referência a segredo (secret_refs, authorization_ref, o credential_ref de uma exportação, o secret_ref de um mapeamento) precisa ficar sob spaces/<o seu espaço>/: o cofre é da célula, compartilhado pelos espaços que ela atende, e a célula recusa uma referência a outro espaço na hora de usar (a entrega falha como secret_outside_space, o webhook responde 403, a exportação e a gravação da credencial são recusadas), e o plano de controle recusa um documento novo que a cite.
webhook-id, webhook-timestamp e webhook-signature, sobre o corpo cru) e tem as mesmas retentativas por 24 horas e a mesma fila de mortos, com reenvio pelo Console. Para conferir o fluxo antes de depender dele, uma entrega de teste manda um evento OCSF marcado com unmapped.niadra.test, fora da corrente. Um fluxo de SIEM nunca é destino de uma regra de aviso: o plano de controle recusa a regra. O evento diz quem leu (a fonte ou a pessoa), a superfície ou a ação, o perfil e o objeto pelos ids, nunca por telefone ou e-mail, a finalidade, o nível, a versão da política, se a leitura foi recusada (status Failure, com o motivo em status_detail) e a posição na corrente em unmapped.niadra.chain (fatia, dia, seq, prev_hash e hash), para o seu SIEM conferir a corrente por conta própria. Como o comprovante, nunca leva o que foi lido.
A exportação contínua também leva a tabela receipts para o seu bucket, na frequência do agendamento.
Comprovantes e apagamento
Quando um titular é esquecido, os comprovantes de leitura não são reescritos: eles já guardam só ids e hashes, então provam que a leitura aconteceu sem guardar o que foi lido. O próprio apagamento deixa um comprovanteadmin, o comprovante de apagamento, que lista o que foi apagado e as execuções de exportação que já continham o dado. As linhas de medição seguem a retenção e a política do comprovante a que pertencem.
Próximos passos
Privacidade, apagamento e exportação
o comprovante de apagamento e a linhagem que ele percorre.
Aproveitamento do contexto
cada entrega medida traz o hash do manifesto que o comprovante da leitura registra.
O contexto e as views
itens retidos e níveis de verificação.
Buscar comprovantes
o endpoint em detalhe.

