# Como as assinaturas de requisições HTTP limitam chamadas de APIs por agentes de IA

Um agente de IA com um token bearer tem, na prática, a mesma liberdade de qualquer outro processo que consiga ler esse token. Ele pode chamar agora um endpoint permitido, tentar de novo mais tarde, enviar o token para outro host se o código permitir e fazer uma requisição cujo corpo tenha pouca relação com a instrução do usuário que iniciou a execução. O servidor vê a posse da credencial e pouco mais.

As assinaturas de requisições HTTP melhoram essa situação ao vincular a autorização a uma mensagem específica. Um bom projeto pode tornar uma assinatura válida apenas para `POST https://api.example.test/v1/releases/42`, apenas com o corpo exato preparado pelo agente, apenas por um período curto e apenas sob uma identidade de assinatura. Esse é um controle útil. Ele não substitui autorização, aprovação nem isolamento de credenciais.

As equipes erram nisso de duas formas opostas. Algumas mantêm tokens bearer porque assinar parece complicado e depois descobrem que um agente pode usar um token com escopo amplo em qualquer lugar para onde consiga fazer uma requisição de saída. Outras assinam todos os cabeçalhos emitidos pela biblioteca HTTP e constroem um verificador tão frágil que proxies comuns, diferenças de relógio ou uma atualização da biblioteca derrubam a produção. O projeto certo vincula os campos que alteram o significado ou o destino de uma ação e torna a validade e a verificação simples o bastante para operar.

## Assinaturas restringem uma mensagem, enquanto tokens bearer apenas provam a posse

Um token bearer responde a uma pergunta: esta requisição apresentou um segredo aceito no momento? Normalmente, ele não vincula o segredo ao método, destino, corpo ou horário da requisição. Tokens de acesso OAuth podem carregar escopos, audiências e expiração, o que ajuda, mas o detentor ainda pode usar cada escopo permitido até o vencimento.

Uma assinatura de requisição responde a uma pergunta criptográfica mais específica: o detentor desta chave de assinatura autorizou este conjunto definido de componentes da requisição? O servidor reconstrói a entrada assinada, verifica a assinatura com a chave pública registrada ou com um segredo compartilhado, confere os limites de tempo e então aplica a autorização normal. Essa ordem importa. A verificação da assinatura estabelece a integridade da mensagem e a identidade do assinante. A autorização decide se essa identidade pode executar a ação.

Considere um serviço de implantação com um token bearer limitado à criação de releases. Primeiro, um agente cria uma release de staging inofensiva. Depois, uma prompt injection orienta o mesmo agente a criar uma release de produção. O token permite as duas requisições se o escopo abranger os dois ambientes. Trocar o token por uma requisição assinada não corrige esse erro de autorização. Se a identidade de assinatura puder criar releases de produção, ela poderá assinar uma requisição de produção.

As assinaturas oferecem ao serviço proteções que um cabeçalho bearer comum não oferece:

- Uma requisição assinada capturada expira rapidamente e não pode ser repetida para sempre.
- Uma assinatura copiada normalmente não pode ser transferida de `POST /v1/staging/releases` para `POST /v1/production/releases`.
- Um corpo JSON alterado falha na verificação quando o resumo do corpo é assinado.
- O serviço pode identificar uma credencial de assinatura sem aceitá-la como um valor de cabeçalho reutilizável.
- Um verificador pode registrar exatamente quais campos o assinante aprovou.

Não descreva isso como uma substituição de tokens de acesso em toda arquitetura. Muitos sistemas usam os dois. Um token de acesso pode identificar o usuário delegado ou a carga de trabalho, enquanto uma assinatura de requisição vincula a mensagem individual a uma credencial de assinatura específica do agente. Em outros sistemas, uma requisição assinada autentica diretamente o chamador, e o servidor determina as permissões a partir da identidade de assinatura.

A diferença tem uma consequência prática para agentes de IA: uma assinatura transforma a ação em um objeto concreto que pode ser inspecionado, aprovado e registrado. Um token bearer aparece principalmente como uma capacidade disponível no ambiente. Essa diferença torna a revisão possível, mas somente se o limite da ferramenta impedir que o agente extraia o segredo de assinatura.

## Use a RFC 9421 em vez de inventar uma string canônica

A RFC 9421, HTTP Message Signatures, define uma forma estruturada de declarar os componentes cobertos e enviar uma assinatura. Ela evita o formato privado comum em que um lado junta campos com caracteres de nova linha, outro normaliza uma URL de maneira diferente e os dois culpam a criptografia quando a verificação falha.

A RFC separa duas ideias. `Signature-Input` declara um rótulo, os componentes cobertos e parâmetros como `created`, `expires`, `nonce`, `alg` e `keyid`. `Signature` carrega o valor criptográfico resultante sob o mesmo rótulo. O verificador constrói a base da assinatura a partir dos componentes e parâmetros declarados e então a verifica.

Uma requisição compacta pode ser assim:

```http
POST /v1/releases/42?environment=staging HTTP/1.1
Host: api.example.test
Content-Type: application/json
Content-Digest: sha-256=:rPMyV6WTE4Duf0JApE9tXvDYy9EzrgFQbq3e2XTCwbs=:
Signature-Input: sig1=("@method" "@authority" "@path" "@query" "content-digest" "date");created=1735689600;expires=1735689660;keyid="agent-release-17";alg="ed25519"
Signature: sig1=:BASE64_SIGNATURE_BYTES:
Date: Wed, 01 Jan 2025 00:00:00 GMT

{"version":"2025.01.01","notes":"staging validation"}
```

O valor do resumo acima ilustra o formato transmitido, não é o resumo do JSON de exemplo. Um cliente de produção calcula o resumo a partir dos bytes exatos que enviará. Se ele serializar o JSON uma segunda vez depois da assinatura, terá criado uma fonte de falhas.

A RFC 9421 é propositalmente flexível. Isso é útil para intermediários e diferentes versões de HTTP, mas significa que o contrato da sua API precisa definir um perfil exato. Declare o algoritmo permitido, os componentes obrigatórios, a duração máxima da assinatura, o formato de `keyid`, o algoritmo de resumo aceito e se um nonce é necessário. Se o contrato disser apenas que as requisições devem ser assinadas, cada autor de cliente fará suposições diferentes.

Ed25519 é uma boa opção padrão quando o serviço pode registrar chaves públicas. O servidor armazena uma chave pública de verificação, e a perda desse registro público não expõe um segredo de assinatura. Assinaturas HMAC podem funcionar quando um componente confiável e a API compartilham um segredo, mas esse segredo precisa existir nos dois lados. Em fluxos com agentes, isso costuma aumentar o número de lugares onde um segredo reutilizável pode vazar.

Evite um esquema proprietário, a menos que uma restrição de protocolo o exija. Formatos proprietários tendem a assinar a URL bruta em um cliente, o caminho decodificado em outro e uma representação diferente do host no verificador. A RFC 9421 oferece identificadores de componentes definidos e campos estruturados. Use-os e teste o perfil exato que você publica.

## Vincule o método, o destino e a consulta que definem a ação

Um agente deve assinar todos os campos da requisição que alterem para onde ela vai ou qual operação do servidor será chamada. Para a maioria das chamadas de API, o conjunto mínimo útil é `@method`, `@authority`, `@path` e `@query`. Você pode usar `@target-uri` quando quiser um componente que cubra toda a URI de destino, mas não assine os dois formatos sem uma razão que os implementadores consigam explicar.

`@method` impede que alguém reutilize uma assinatura destinada a `GET` como `DELETE`. Isso parece óbvio, mas esquemas montados manualmente frequentemente o omitem porque um engenheiro presume que o caminho determina a operação. APIs REST costumam reutilizar um caminho com métodos diferentes. O método muda a ação.

`@authority` vincula o host e a autoridade da porta. Isso impede que uma assinatura emitida para uma origem de API seja validada contra outra origem que aceite a mesma credencial. Isso importa em organizações com hosts de preview, staging e produção. Uma identidade de assinatura destinada a staging não deve adquirir autoridade sobre produção porque um agente ou redirecionamento alterou o host.

`@path` e `@query` exigem o mesmo cuidado. Muitas APIs colocam parâmetros importantes na string de consulta:

```http
POST /v1/invoices/817/refund?amount=2500&currency=USD
```

Se a assinatura cobrir apenas o caminho, um invasor capaz de alterar a requisição em trânsito poderá mudar o valor ou a moeda. Se o servidor obtém `dry_run`, `environment`, `force`, `page_size`, `include_deleted` ou um seletor de tenant da consulta, esses valores fazem parte da ação. Assine `@query`.

A RFC 9421 também define `@query-param`, que pode cobrir um parâmetro nomeado específico. Ele é útil em protocolos nos quais alguns parâmetros da consulta ficam explicitamente fora da decisão de segurança, como dados de rastreamento. Para uma API interna usada por agentes, assinar a consulta inteira costuma causar menos surpresas. Cada parâmetro passa a fazer parte da requisição aprovada, e os revisores não precisam se lembrar de uma lista de exceções.

Não trate a normalização de URLs de forma casual. O verificador precisa usar a semântica dos componentes especificada pela RFC 9421 e pela biblioteca escolhida. Não decodifique escapes percentuais e os recodifique manualmente. Não ordene parâmetros de consulta repetidos, a menos que a definição do componente selecionado faça isso. O destino de uma requisição são bytes transmitidos pela rede antes de se tornar um objeto conveniente da aplicação.

Estabeleça uma regra firme para redirecionamentos: não carregue automaticamente uma requisição assinada através de um redirecionamento para outra autoridade. Uma assinatura que cubra a autoridade original deve falhar no novo host, e isso está correto. Deixe o cliente receber o redirecionamento, aplicar uma lista de permissões explícita, construir uma nova requisição e assinar essa nova requisição. Para requisições que alteram dados, muitas equipes deveriam rejeitar redirecionamentos completamente.

## Um corpo assinado precisa de um resumo, não de otimismo sobre JSON

Assine `content-digest` quando o corpo influenciar o resultado. Isso inclui quase todas as requisições JSON que alteram dados, uploads multipart, envios de formulários e operações em lote. Assinar `content-type` também pode fazer sentido quando o servidor interpreta os mesmos bytes de forma diferente conforme o tipo de mídia.

A IETF define `Content-Digest` na RFC 9530. Ele carrega um resumo do conteúdo da mensagem HTTP usando a sintaxe de Structured Fields. A assinatura cobre o cabeçalho de resumo, em vez de cobrir diretamente um corpo enorme, enquanto o destinatário calcula o resumo do corpo e o compara antes de aceitar a assinatura. Assim, a assinatura usa uma representação de tamanho fixo do conteúdo exato.

A sequência segura de envio é simples e precisa permanecer nesta ordem:

1. Monte o objeto final da requisição, incluindo parâmetros de consulta e cabeçalhos que afetem a interpretação.
2. Serialize o corpo uma única vez em bytes e mantenha esses bytes para a transmissão.
3. Calcule `Content-Digest` sobre esses bytes.
4. Crie `Signature-Input` sobre os componentes escolhidos e assine sua base de assinatura.
5. Envie os mesmos bytes e cabeçalhos, sem alterações.

A falha comum é mais banal que um ataque criptográfico. A aplicação serializa um objeto para calcular o resumo, assina o resultado e depois um auxiliar HTTP serializa o objeto novamente. A ordem dos membros do objeto JSON, os escapes, os espaços, a formatação numérica ou um campo de horário mudam. O verificador informa corretamente que o resumo não corresponde. Os desenvolvedores então removem a proteção do corpo para conseguir fazer a release. Esse é o conserto errado.

Passe um buffer de bytes, stream ou corpo de requisição imutável ao transporte. Se o streaming impossibilitar calcular um resumo completo antes da transmissão, use um protocolo criado para esse caso e teste-o cuidadosamente. Não omita silenciosamente o resumo do corpo de uma operação de alto impacto porque o streaming era inconveniente.

Os cabeçalhos exigem uma regra mais restrita. Assine um cabeçalho quando o destinatário ou intermediário puder usá-lo para alterar o significado de segurança da requisição. `content-type` é um candidato. Um cabeçalho de tenant também é, se o servidor o usar para escolher uma conta. Um cabeçalho de idempotência é candidato quando retries e efeitos duplicados importam. Um cabeçalho de diagnóstico normalmente não é.

Assinar `user-agent`, `accept`, IDs de rastreamento, cabeçalhos de conexão e todos os cabeçalhos emitidos pela biblioteca cria clientes frágeis. Proxies podem adicionar, combinar ou reescrever cabeçalhos comuns. O HTTP permite transformações legítimas. Você quer que a assinatura rejeite mudanças semânticas, não que transforme uma variação inofensiva do transporte em uma indisponibilidade.

## Janelas de validade devem tolerar diferenças, mas rejeitar tarefas em fila

Limites de tempo fazem as assinaturas capturadas durarem pouco. Eles também causam incidentes desnecessários quando as equipes fingem que toda estação de trabalho, container e VM tem horário perfeito. A resposta é uma regra de aceitação limitada e uma boa sincronização de relógio, não uma tolerância de duas horas.

Use `created` e `expires` em `Signature-Input`. Uma duração de sessenta segundos funciona bem para chamadas interativas quando o agente assina imediatamente antes do envio. Alguns minutos podem ser adequados para uma rede instável ou um fluxo que tenta novamente depois de uma falha temporária. A API deve documentar uma duração máxima e aplicá-la. Não permita que os clientes escolham uma expiração arbitrária só porque consideram a expiração inconveniente.

O verificador deve avaliar três casos separadamente:

- Rejeitar uma requisição cujo horário `created` esteja muito no futuro, além de uma pequena tolerância configurada.
- Rejeitar uma requisição cujo horário `expires` já tenha passado.
- Rejeitar uma requisição cuja duração, `expires - created`, exceda o máximo da API, mesmo que ela ainda não tenha expirado.

Um servidor pode aceitar um relógio do cliente ligeiramente atrasado ou adiantado sem aceitar trabalho antigo. Por exemplo, um serviço pode permitir uma pequena diferença no futuro e um intervalo curto de expiração. Os valores exatos dependem de onde os clientes executam, mas o princípio não muda: tolerância de horário não é uma janela de replay deixada aberta durante toda a tarde.

Não use o cabeçalho HTTP `Date` como único mecanismo de validade. Ele pode ser útil como componente coberto para compatibilidade e diagnóstico, mas `created` e `expires` vivem diretamente nos parâmetros da assinatura e são menos ambíguos. Se você assinar os dois, declare quais valores o servidor usa para aplicar a regra quando houver divergência. Um verificador que aceita qualquer um deles dá uma vantagem desnecessária aos invasores.

Tarefas de agentes colocadas em fila expõem um erro de projeto oculto. Suponha que um agente crie requisições assinadas às 09:00, uma aprovação humana espere até 09:20 e um worker envie a requisição antiga depois da aprovação. O serviço deve rejeitá-la. A tarefa precisa de um novo evento de assinatura após a aprovação, porque a ação aprovada deve ter um horário atual e um destino atual significativos.

Para operações que podem ser repetidas, armazene um identificador de idempotência em um cabeçalho ou campo do corpo assinado e cubra-o com a assinatura. O cliente pode criar uma assinatura nova a cada retry, enquanto o servidor reconhece a operação lógica e evita efeitos duplicados. Reutilizar uma requisição assinada expirada não é uma estratégia de retry.

## Nonces interrompem replay apenas quando o servidor se lembra deles

Uma expiração curta limita o replay, mas não impede que um invasor repita várias vezes uma requisição capturada durante essa janela. A importância disso depende do endpoint. Repetir uma leitura inofensiva tem pouco efeito. Repetir uma transferência de dinheiro, exclusão de conta ou alteração de infraestrutura pode ser grave.

Um nonce trata esse risco quando o servidor considera cada nonce de uso único para uma identidade de assinatura. O cliente gera um valor imprevisível, coloca-o nos parâmetros da assinatura ou em um cabeçalho coberto, e o servidor registra o uso bem-sucedido até a assinatura expirar. Uma segunda requisição com o mesmo assinante e nonce falha, mesmo que a assinatura ainda seja válida.

Essa é a parte que as equipes ignoram quando dizem que usam nonces. Um nonce que o servidor não guarda é apenas uma string aleatória extra. Ele não prova unicidade. Um cache ou banco compartilhado precisa de uma operação atômica de criação para que replays concorrentes não passem ambos pela verificação.

Use um armazenamento de nonces quando o dano potencial do replay justificar o custo operacional. Você precisa escolher o período de retenção, os limites de tamanho, o comportamento em caso de falha e o particionamento. Mantenha um nonce aceito até o último momento em que o servidor poderia aceitar a requisição. Identifique os registros pelo conjunto identidade do assinante e nonce, não apenas pelo nonce, porque identidades diferentes podem gerar o mesmo valor sem impacto de segurança.

Não torne um nonce obrigatório para toda chamada de baixo risco e alto volume apenas porque isso parece mais seguro. Essa escolha pode transformar uma falha no armazenamento de nonces em uma indisponibilidade para leituras inofensivas. Um perfil prático pode exigir nonce para alterações irreversíveis e depender de expiração curta e controles de idempotência em outros casos. Escreva essa regra endpoint por endpoint.

As verificações de nonce também não substituem a idempotência. O nonce diz que esta mensagem assinada deve ser aceita uma vez. Um identificador de idempotência diz que várias tentativas de retry, cada uma assinada separadamente, representam uma única operação comercial pretendida. Eles resolvem falhas diferentes.

## A verificação deve falhar de forma segura antes que o código da aplicação veja a requisição

O gateway da API ou o ponto de entrada da aplicação deve verificar a requisição antes que um handler de rota interprete parâmetros de ação, inicie um job ou consulte serviços downstream. Um handler que lê um corpo e executa trabalho antes da verificação já abriu mão da propriedade de segurança que a assinatura deveria oferecer.

Um verificador precisa de uma sequência previsível:

1. Analise `Signature-Input` e `Signature` como Structured Fields, rejeitando sintaxe malformada e ambiguidades causadas por duplicatas.
2. Selecione um rótulo de assinatura permitido e rejeite algoritmos desconhecidos, componentes obrigatórios ausentes ou combinações proibidas de componentes.
3. Resolva `keyid` para uma identidade de assinatura ativa e obtenha seu material de verificação.
4. Reconstrua a base da assinatura conforme a RFC 9421, usando a requisição recebida, não uma URL da aplicação reconstruída.
5. Verifique a assinatura criptográfica, o resumo do corpo, os limites de tempo, o estado do nonce quando necessário e, depois, a autorização.

Mantenha separados nos logs os erros criptográficos e os erros de autorização. As respostas públicas podem continuar deliberadamente simples. Um `401` ou `403` com um código de erro estável é suficiente para os chamadores. Internamente, registre se o serviço rejeitou a requisição por `keyid` desconhecido, assinatura expirada, resumo inválido, autoridade incompatível, nonce reutilizado ou permissão insuficiente.

Não registre os bytes da assinatura como se fossem material inofensivo de depuração. Assinaturas de chave pública não são segredos como as credenciais HMAC, mas logs completos de requisições costumam conter cabeçalhos de autorização, dados pessoais e corpos. Registre um identificador da requisição, a identidade do assinante, os nomes dos componentes cobertos, um valor de resumo se a política de retenção permitir e a decisão. Limite a captura bruta a um procedimento deliberado de incidente.

Vetores de teste importam mais que prosa. A RFC 9421 inclui exemplos, mas o perfil da sua API precisa dos próprios fixtures. Mantenha requisições que devem ser verificadas, além de mutações que devem falhar: método alterado, consulta alterada, byte do corpo alterado, assinatura expirada, valor `created` no futuro, autoridade errada, `keyid` alterado e nonce repetido. Execute esses testes em todas as implementações de cliente compatíveis.

Um verificador de assinatura deve rejeitar ambiguidades, mesmo quando um parser permissivo pudesse adivinhar a intenção do remetente. Cabeçalhos duplicados, serialização inconsistente de componentes e algoritmos não suportados são erros de protocolo. Um agente não precisa que o servidor seja prestativo. Precisa que ele seja exato.

## Mantenha o material de assinatura fora do contexto do agente

Dar a um agente de programação de IA uma chave privada de assinatura ou um segredo HMAC anula grande parte do propósito da assinatura. A chave pode aparecer na saída de uma ferramenta, no histórico do shell, em arquivos temporários, relatórios de erro ou em um prompt que instrua o agente a imprimir o ambiente. Mesmo um agente bem-comportado tem uma superfície indireta grande demais para uma credencial reutilizável.

Em vez disso, exponha um limite de ação restrito. O agente fornece o método, o destino permitido, os cabeçalhos e o corpo a um componente local ou remoto confiável. Esse componente valida o destino permitido, obtém aprovação quando o fluxo exigir, monta a lista de componentes cobertos, assina imediatamente antes do envio e devolve a resposta. O agente não recebe um segredo em texto simples nem um marcador falso que possa encaminhar por acidente.

Esse limite também torna concreta a revisão da autoridade. Uma identidade de assinatura pode ser limitada a um serviço, ambiente, família de rotas e classe de ação. Se o agente precisa apenas abrir uma release de staging, não dê a ele uma credencial capaz de assinar ajustes de cobrança ou chamadas de exclusão em produção. A autorização do servidor continua responsável por aplicar esses limites depois da verificação da assinatura.

O Sallyport segue essa separação para ações HTTP: o aplicativo mantém as credenciais da API em seu cofre criptografado e executa a chamada HTTP, de modo que um agente compatível com MCP recebe o resultado, não a credencial em texto simples.

Não confunda um gateway de ações com um padrão de assinatura de requisições. A RFC 9421 diz a duas partes HTTP como autenticar componentes selecionados de uma mensagem. Um gateway de ações decide onde fica o material de assinatura, quando uma pessoa vê uma aprovação e qual registro de auditoria existe em torno de uma execução do agente. Você pode usar um sem o outro, mas a combinação é útil quando ferramentas autônomas atuam sobre APIs importantes.

Se você depende de um assinante local, trate sua interface local como um limite de autorização. Vincule as requisições ao processo chamador quando possível, rejeite destinos arbitrários e garanta que um processo de agente não possa usar silenciosamente a sessão aprovada de outro processo. Um serviço local que assina qualquer URL enviada por qualquer programa local apenas moveu uma capacidade bearer para trás de um socket.

## Aprovação e assinaturas respondem a perguntas diferentes

Uma aprovação humana registra que alguém permitiu determinada classe de ação do agente. Uma assinatura de requisição registra que uma identidade de assinatura autorizou uma mensagem HTTP definida. Nenhum dos dois registros prova o outro, a menos que o projeto faça essa vinculação explicitamente.

Para chamadas de alto impacto, faça a tela de aprovação mostrar os campos que a assinatura cobrirá: método, autoridade, caminho, parâmetros relevantes da consulta, resumo do corpo ou um resumo legível do corpo, identidade de assinatura e expiração. Se um usuário aprova `POST /v1/releases/42?environment=staging`, o assinante não pode depois substituir staging por produção através de um parâmetro de consulta sem assinatura.

É aqui que resumir apenas um corpo opaco pode prejudicar a revisão humana. O resumo criptográfico prova a identidade dos bytes, mas quase não diz nada a uma pessoa. Mantenha os dois artefatos: uma representação canônica da requisição para revisão e um resumo para integridade. A tela de revisão deve derivar do mesmo objeto imutável exato que o assinante enviará, não de um plano renderizado separadamente.

A aprovação de uma sessão pode ser adequada para uma execução curta de agente com muitas chamadas de baixo impacto. A aprovação por chamada é melhor para exclusões, publicação externa, alterações financeiras ou qualquer operação que um invasor possa esconder entre o tráfego rotineiro. Não peça aprovação para cada leitura apenas para alegar controle humano. As pessoas clicarão automaticamente, e você terá criado fadiga de aprovação sem uma decisão significativa.

O registro de auditoria deve capturar a identidade do assinante, os componentes cobertos, a duração da assinatura, a decisão de autorização, a referência da aprovação quando houver, o status da resposta e um identificador da requisição. Um histórico de auditoria legível ajuda o operador a responder a uma pergunta simples depois de um incidente: o que o agente enviou, sob autoridade de quem e o servidor aceitou?

## As falhas que vale a pena ensaiar são principalmente falhas comuns de engenharia

Os bugs de implementação mais perigosos não estão em curvas elípticas quebradas. Eles são campos sem assinatura, canonicalização incompatível, trabalho antigo e segredos colocados onde os agentes conseguem lê-los.

Uma falha aparece quando uma equipe assina `@method`, `@path` e `date`, mas deixa `@query` de fora. A API de releases aceita `?environment=staging` no uso normal. Mais tarde, uma alteração de manutenção acrescenta `?environment=production` ao mesmo endpoint. Um bug de proxy ou um componente local hostil muda o parâmetro depois da assinatura. A assinatura é validada, o handler vê produção e o registro de auditoria afirma, de forma enganosa, que o agente enviou uma requisição assinada válida. A assinatura fez exatamente o que a lista de componentes pediu. A lista estava incompleta.

Outra falha aparece quando os desenvolvedores aceitam assinaturas de dez minutos para reduzir chamados relacionados a relógios. Um agente assina uma requisição de exclusão, grava todos os cabeçalhos em um log de depuração e um desenvolvedor copia o log para um issue. Qualquer pessoa com acesso a esse issue pode repetir a requisição durante a maior parte do dia de trabalho. Uma expiração curta não apaga o vazamento original, mas limita muito sua utilidade. Exigir um nonce para exclusões remove a janela de replay restante depois da primeira aceitação.

Uma terceira falha ocorre com credenciais HMAC compartilhadas. Vários agentes usam o mesmo segredo porque provisionar identidades individuais parecia trabalhoso. Quando uma auditoria encontra uma chamada destrutiva, a equipe consegue identificar a integração compartilhada, mas não a execução do agente, a aprovação do usuário nem o processo que a originou. Dê identidades de assinatura distintas a limites de autoridade distintos. A atribuição faz parte da resposta a incidentes, não é um luxo de relatórios.

Comece com um endpoint que altera dados e escreva o perfil antes de escolher uma biblioteca. Especifique sua autoridade permitida, componentes obrigatórios, regra do resumo do corpo, duração da assinatura, tolerância de horário, regra de replay, algoritmo de assinatura e mapeamento de autorização. Depois crie testes negativos que alterem cada campo coberto. Se um teste conseguir alterar um campo relevante da requisição e ainda assim passar pela verificação, não publique o perfil.

Uma requisição assinada deve ser fácil de rejeitar pelo motivo certo. Esse padrão conduz o projeto a uma autoridade restrita, mensagens de curta duração, corpos imutáveis e logs que mostram o que aconteceu depois que o agente agiu.
