# Parâmetros destrutivos de API: valide antes de excluir

Agentes de IA fazem chamadas destrutivas de API com facilidade demais quando uma solicitação parece sintaticamente correta. Um corpo JSON válido, um nome de conta conhecido e uma busca bem-sucedida não provam que o agente está prestes a excluir o objeto certo. Antes que uma solicitação externa remova, revogue, desconecte, cancele ou sobrescreva dados, valide a identidade, a propriedade, o escopo e a atualidade diretamente no serviço.

Já vi engenheiros cuidadosos interpretarem uma solicitação como «excluir este ambiente de teste», enquanto a API a interpretava como «excluir todos os ambientes desta organização». Em geral, o código não tinha um bug no sentido estrito. Ele aceitava um seletor formado de maneira vaga, resolvia um nome na conta errada ou confiava em dados obtidos antes na execução. Um agente autônomo comete esses erros comuns mais rápido e com mais confiança.

Este não é um caso para pedir ao modelo que seja mais cuidadoso. Coloque uma barreira determinística entre a solicitação proposta pelo agente e a solicitação autenticada. Por padrão, essa barreira deve rejeitar ambiguidades e fazer com que uma pessoa aprove o alvo e o efeito reais.

## Uma solicitação bem formada ainda pode indicar o objeto errado

Uma solicitação só fica segura o suficiente para ser enviada depois que você estabelece quatro fatos separados: o recurso é do tipo correto, seu identificador imutável é o pretendido, ele pertence à conta principal aprovada e a operação afetará o conjunto aprovado. As equipes costumam misturar esses fatos em uma única busca. É nesse atalho que as exclusões dão errado.

Considere um serviço que expõe um nome de exibição e um ID:

```json
{
  "id": "env_7d3a",
  "name": "staging",
  "account_id": "acct_blue",
  "state": "active"
}
```

Um agente que busca por `staging` encontrou um candidato, não uma autorização para excluí-lo. Muitas contas têm um ambiente `staging`. Mesmo dentro de uma conta, os nomes podem ser reutilizados depois que um objeto antigo desaparece. A única solicitação de ação segura é aquela construída com o ID imutável retornado e verificada contra um ID de conta principal esperado.

A distinção importa ainda mais quando uma API oferece um caminho principal como `/accounts/{account_id}/environments/{environment_id}`. Verifique os dois segmentos. Não deduza a propriedade porque o ID apareceu em uma resposta de busca anterior ou porque o agente colocou o mesmo nome de conta no plano. A conta principal no URL da ação faz parte da fronteira de autorização.

O tipo do recurso merece uma verificação própria. As APIs costumam usar um endpoint de busca compartilhado ou retornar registros mistos. Um resultado chamado `staging` pode ser um ambiente, um projeto, um grupo de acesso ou um modelo salvo. Se o serviço tiver endpoints de exclusão diferentes, selecione o endpoint somente depois de verificar o tipo retornado. Não construa um endpoint concatenando uma string de tipo produzida pelo modelo.

Por fim, defina o efeito esperado antes de inspecionar os candidatos. «Remover a implantação antiga» pode significar excluir um registro de implantação, interromper um trabalho em execução, revogar um token emitido para ele ou excluir todo o ambiente. Esses efeitos não podem compartilhar uma operação genérica de `delete`. Deixe o verbo solicitado e o tipo do objeto explícitos no contrato da ação.

## Os nomes ajudam as pessoas, mas os IDs controlam a solicitação

Use um ID imutável para endereçar um recurso, mas mostre à pessoa que aprova contexto humano suficiente para detectar uma escolha errada. Um cartão de aprovação que diga apenas `env_7d3a` incentiva a aprovação automática. Um que diga apenas `staging` cria ambiguidade. Mostre os dois ao operador, junto da conta principal e da consequência da operação.

Um registro de alvo útil tem esta aparência:

```json
{
  "operation": "delete_environment",
  "account": {"id": "acct_blue", "name": "Blue Team"},
  "target": {"id": "env_7d3a", "name": "staging", "type": "environment"},
  "expected_state": "active",
  "effect": "permanently removes this environment and its managed resources"
}
```

O nome de exibição da conta ajuda o operador a perceber que o agente foi parar no tenant errado. O nome do recurso ajuda a reconhecer o objeto. Os IDs tornam a solicitação inequívoca. O efeito declarado evita uma falha comum de aprovação: a pessoa pensa ter aprovado uma ação reversível de interrupção, mas o provedor removerá dados.

Não resolva um nome usando o primeiro resultado da busca. Os endpoints de busca frequentemente ordenam por relevância, retornam correspondências parciais ou usam paginação. Se a tarefa fornecer um nome exato, exija exatamente um candidato depois de filtrar pela conta principal e pelo tipo esperado. Zero candidatos deve causar falha. Mais de um candidato também. Pedir ao agente que escolha um não resolve o problema, porque ele não tem evidências para distingui-los.

O tratamento de maiúsculas e minúsculas também precisa de uma regra específica do serviço. Alguns provedores diferenciam maiúsculas de minúsculas; outros normalizam os nomes. Não normalize os nomes por conta própria e presuma que o provedor agirá da mesma forma. Use o recurso retornado pelo provedor como autoridade e mantenha o rótulo exato retornado no registro de aprovação.

Tags, rótulos e descrições são contexto, não identidade. Eles mudam com frequência e os usuários podem escrever praticamente qualquer coisa neles. Uma tag como `temporary=true` pode restringir uma lista analisada, mas não deve substituir a associação a uma conta ou um ID de recurso imutável.

## O escopo precisa ser concreto antes que o agente peça aprovação

Uma operação destrutiva tem um escopo mesmo quando o corpo da solicitação contém apenas um ID. O escopo inclui a conta principal, os recursos selecionados, os recursos filhos que o provedor remove automaticamente e qualquer filtro que amplie a seleção. Torne esse escopo concreto antes de pedir a aprovação de alguém.

A exclusão de um único objeto tem um contrato simples: um ID imutável, uma conta principal esperada e um tipo de recurso. A exclusão em massa precisa de outro contrato. Primeiro, ela deve produzir um conjunto resolvido; depois, obter aprovação para esse conjunto ou para um resumo limitado que uma pessoa possa inspecionar. Enviar um seletor diretamente a um endpoint destrutivo deixa o serviço externo decidir o escopo depois que a aprovação já ocorreu.

Suponha que um agente proponha esta solicitação:

```json
{
  "account_id": "acct_blue",
  "filter": {"label": "cleanup-candidate"},
  "delete": true
}
```

Esse corpo esconde o único fato de que o operador precisa: quais recursos correspondem ao filtro agora. Expanda o filtro por meio de uma chamada de listagem somente leitura, rejeite qualquer paginação que não tenha sido totalmente inspecionada e normalize o resultado em IDs. Depois, mostre uma contagem e uma pequena amostra com nomes. Se o conjunto for maior que o limite aprovado, interrompa o processo e exija uma nova instrução.

Nunca permita que a ausência de um filtro signifique «todos». Nos esquemas de solicitação, diferencie uma lista vazia obrigatória de um seletor ausente. Melhor ainda, proíba que endpoints destrutivos aceitem filtros na interface de ações do agente. Faça o gateway aceitar apenas uma lista de IDs resolvidos para operações em massa.

Uma estrutura prática é:

```json
{
  "operation": "delete_resources",
  "account_id": "acct_blue",
  "resource_type": "snapshot",
  "resource_ids": ["snap_104", "snap_105"],
  "selection_observed_at": "2025-03-08T14:32:11Z"
}
```

Rejeite um array `resource_ids` vazio, a menos que o fluxo permita isso explicitamente. Rejeite IDs duplicados. Rejeite IDs de outra conta. Aplique um limite máximo compatível com a operação aprovada pela pessoa. Um limite não substitui a análise, mas impede que um loop malformado transforme uma limpeza de dois recursos em um incidente envolvendo mil recursos.

As exclusões em cascata também fazem parte do escopo. Se excluir um projeto também excluir repositórios, chaves de implantação, ambientes ou registros de cobrança, informe isso antes da aprovação. Se o provedor só expuser os detalhes da cascata depois de uma chamada preliminar, preserve essa resposta e exija que o agente a apresente. «Excluir o projeto» é vago demais quando o projeto tem objetos dependentes.

## Leia o serviço duas vezes quando o tempo puder mudar o alvo

Uma leitura preliminar verifica a intenção, mas não congela o objeto. O recurso pode mudar, trocar de conta ou desaparecer entre a validação e a exclusão. Para operações sensíveis, leia o alvo imediatamente antes da mutação e use o controle de concorrência oferecido pelo serviço.

O HTTP fornece um mecanismo padrão para esse padrão. A RFC 9110 define solicitações condicionais com `If-Match`: o servidor executa o método solicitado somente se a representação atual corresponder a uma tag de entidade fornecida pelo cliente. Um `GET` pode retornar um `ETag`, e um `DELETE` posterior pode enviar exatamente esse valor.

```http
GET /v1/accounts/acct_blue/environments/env_7d3a HTTP/1.1
Authorization: Bearer [injected credential]

HTTP/1.1 200 OK
ETag: "v42"
Content-Type: application/json

{"id":"env_7d3a","account_id":"acct_blue","name":"staging","state":"active"}
```

Depois de comparar o corpo com o alvo aprovado, envie:

```http
DELETE /v1/accounts/acct_blue/environments/env_7d3a HTTP/1.1
If-Match: "v42"
Authorization: Bearer [injected credential]
```

Se o serviço retornar `412 Precondition Failed`, trate isso como uma barreira de proteção que funcionou. Não peça ao agente para repetir a exclusão sem uma condição. Busque o recurso novamente, compare-o com os fatos aprovados e peça uma nova aprovação se algum fato relevante tiver mudado. Um conflito de versão é evidência de que a aprovação antiga talvez não se aplique mais.

Alguns serviços usam números de revisão, timestamps de atualização, campos de geração ou tokens de solicitação em vez de ETags HTTP. Use o mecanismo documentado pelo provedor. Se ele não oferecer nenhum, reduza o intervalo entre a leitura final e a gravação, torne a ação serial e aceite que não será possível provar que o alvo permaneceu inalterado. Essa limitação deve influenciar a decisão de permitir exclusões sem supervisão.

Não confunda um `GET` bem-sucedido com permissão para modificar. A credencial de leitura pode enxergar mais do que a credencial de gravação pode alterar, e a autorização pode mudar independentemente do estado do objeto. A resposta da mutação ainda determina se o provedor aceitou a solicitação.

## A validação pertence à fronteira das credenciais

A validação feita apenas em um prompt do agente ou em código gerado é consultiva. O componente que mantém ou injeta a credencial precisa impor as verificações, porque ele é o último ponto capaz de impedir uma solicitação de saída.

Essa fronteira deve receber uma proposta de ação estruturada, não um URL livre e cabeçalhos arbitrários. Uma definição de ação restrita pode exigir campos como ID da conta, ID do recurso, método, tipo esperado e versão esperada. Ela pode construir o caminho de saída a partir de segmentos validados e rejeitar parâmetros de consulta que ampliem o escopo.

Não aceite um URL completo de um agente para depois tentar extrair dele alguma garantia de segurança. Codificação de URL, chaves de consulta repetidas, nomes de host alternativos e normalização de caminhos transformam isso em uma disputa entre analisadores. Aceite campos tipados, valide cada um de acordo com o contrato do provedor e construa o URL por conta própria. A mesma regra vale para os corpos das solicitações. Gere uma estrutura conhecida em vez de repassar um bloco cujos campos não foram inspecionados.

Uma barreira mínima pode impor esta sequência:

1. Confirme que a operação solicitada existe em uma lista permitida e que seu método é destrutivo por definição.
2. Resolva cada alvo declarado com uma chamada de leitura feita sob a mesma conta principal.
3. Compare o ID, o tipo, a conta principal e o estado exigido retornados com a proposta estruturada.
4. Obtenha aprovação para o efeito resolvido, verifique novamente a atualidade e envie a mutação.
5. Registre o resultado, incluindo o ID da solicitação do provedor quando ele for retornado.

Mantenha a lista permitida pequena. Uma saída genérica chamada `raw_http` anula todas as verificações deste artigo, porque o agente pode reintroduzir destinos, métodos e corpos arbitrários. Engenheiros adicionam essas saídas quando falta um endpoint e depois esquecem que elas existem, até que contornam as barreiras que julgavam ter criado.

As credenciais devem permanecer fora do contexto do agente. O agente precisa do resultado de uma ação permitida, não de um token bearer que possa copiar para um comando curl, um log ou uma integração de terceiros. O Sallyport segue esse modelo em suas ações HTTP: mantém a credencial em seu cofre criptografado, executa a solicitação por conta própria e devolve o resultado ao agente.

## DELETE não significa que a solicitação seja simples ou reversível

Os nomes dos métodos HTTP não informam todo o efeito de negócio. A RFC 9110 diz que `DELETE` pede a um servidor de origem que remova a associação entre um recurso alvo e sua funcionalidade atual. A RFC não promete que os dados desaparecerão imediatamente, que os dados relacionados permanecerão ou que uma nova tentativa será inofensiva na sua API específica.

A documentação do provedor precisa definir o efeito real. Algumas APIs marcam um objeto para remoção posterior. Algumas criam um tombstone. Outras o desassociam de uma conta principal. Há também as que removem objetos filhos em cascata. Leia os códigos de resposta e as notas sobre o ciclo de vida do endpoint antes de classificar uma operação como de baixo risco.

Não envie um corpo com `DELETE` a menos que o provedor o documente explicitamente. A RFC 9110 afirma que o conteúdo recebido em uma solicitação `DELETE` não tem semântica geralmente definida e pode fazer com que implementações rejeitem a solicitação. Uma API de exclusão que dependa de filtros no corpo pode ser válida para aquele provedor, mas merece testes adicionais pelo caminho de cliente documentado. Isso não deve servir de desculpa para repassar seletores livres de um agente.

As retentativas exigem o mesmo cuidado. Um timeout de rede cria um resultado desconhecido: o provedor pode ter concluído a exclusão depois que o cliente parou de esperar. Repetir imediatamente pode gerar registros enganosos, provocar um segundo efeito em um endpoint mal projetado ou excluir um recurso substituto se a nova tentativa resolver o alvo pelo nome.

Trate um resultado desconhecido com a regra «inspecionar primeiro». Consulte o ID imutável exato sob a conta principal exata. Se o objeto não existir mais e o modelo de exclusão do provedor permitir essa interpretação, registre a operação como concluída, com a primeira resposta marcada como incerta. Se ele ainda existir, inspecione seu estado e o histórico de solicitações do provedor, quando disponível, antes de decidir se deve tentar novamente. Reutilize uma chave de idempotência nas operações que oferecem suporte a ela, mas não invente idempotência quando o provedor não a oferece.

Um `204 No Content` apenas diz que o servidor aceitou e concluiu a interação HTTP conforme definida por aquele endpoint. Isso não prova que toda a limpeza posterior terminou. Se a próxima ação do agente depender de a exclusão estar completa, consulte o status documentado da operação ou o estado do recurso, em vez de tratar o corpo vazio da resposta como uma garantia.

## A aprovação deve mostrar consequências, não o transporte bruto

As pessoas tomam decisões melhores quando a aprovação descreve o efeito em termos comuns e inclui os identificadores necessários para a verificação. Mostrar um método, um caminho e um corpo JSON é útil para um engenheiro de API, mas transfere trabalho demais de interpretação para a pessoa que deveria detectar um alvo incorreto.

Para um único recurso, a aprovação deve dizer o que mudará, nomear a conta principal, mostrar o nome e o ID do recurso e mencionar efeitos irreversíveis ou em cascata. Para uma operação em massa, mostre a contagem, uma amostra limitada, a regra de seleção usada para criar a lista e o fato de que a ação final usa os IDs congelados, não a regra.

Não peça uma aprovação ampla no início de uma execução longa do agente para usá-la em todas as exclusões posteriores. O conjunto de alvos muda conforme o agente descobre recursos. Vincule a aprovação a uma sessão e à ação resolvida. Se o processo do agente mudar, a aprovação não deve acompanhar silenciosamente um novo processo que pode ter código ou instruções diferentes.

O problema oposto é a fadiga de aprovações. Pedir que alguém clique para cada leitura inofensiva ensina essa pessoa a clicar sem ler e dá a uma exclusão perigosa o mesmo destaque visual. Mantenha as leituras sem interação quando for apropriado, exija autorização de sessão para um agente que acabou de iniciar e reserve a confirmação por ação para credenciais ou ações com efeito destrutivo. Quem vê menos solicitações consegue analisar melhor as que importam.

O registro de aprovação precisa de uma expiração clara. Quanto mais tempo um agente espera depois da validação, menos significa a verificação preliminar. Se a ação não puder ser executada prontamente, faça uma nova resolução e peça aprovação outra vez. Isso pode parecer rígido durante uma tarefa de limpeza. Ainda custa menos do que explicar por que uma aprovação de uma hora atrás foi aplicada a um recurso que havia sido recriado.

## As evidências de auditoria devem reconstruir a decisão sem expor segredos

Um registro de auditoria útil responde a mais do que «uma solicitação aconteceu?». Ele deve permitir reconstruir o que o agente propôs, o que o serviço informou antes da mutação, o que uma pessoa aprovou, o que o gateway enviou e o que o serviço retornou.

Capture os campos normalizados, não apenas uma string de solicitação bruta. Registre o nome da ação, a identidade da sessão do agente, o ID da conta principal, os IDs dos recursos, as versões esperadas, o timestamp da seleção, o efeito aprovado, o horário da aprovação, o método e o caminho enviados, o status da resposta e o ID da solicitação do provedor. Armazene hashes ou formas redigidas do material da solicitação quando ele puder conter valores sensíveis. Um registro de auditoria que copie cabeçalhos de autorização criou um segundo armazenamento de credenciais.

Mantenha a resposta preliminar ou um resumo protegido por integridade dela. Sem isso, um revisor posterior não conseguirá determinar se o agente excluiu o objeto errado porque a validação falhou, porque o objeto mudou depois da validação ou porque o serviço externo se comportou de maneira diferente da documentada. A diferença determina o que precisa ser corrigido.

A evidência contra adulteração importa quando a mesma máquina executa o agente e o gateway de ações. Um registro de texto mutável pode ser editado pelo processo que causou o incidente. O Sallyport gera seus diários de sessões e atividades a partir de um registro de auditoria criptografado e encadeado por hash, e `sp audit verify` pode verificar essa cadeia offline sem uma chave do cofre. Isso não transforma uma aprovação ruim em uma boa, mas torna mais difícil ocultar alterações posteriores no registro.

Teste os registros tanto em solicitações malsucedidas quanto nas bem-sucedidas. Rejeições, aprovações expiradas, conflitos de versão e IDs malformados mostram se os controles realmente bloquearam o trabalho. Um diário cheio de sucessos informa muito pouco sobre a capacidade da barreira de recusar uma solicitação perigosa.

## Crie ações destrutivas como contratos restritos

A ação de API mais segura é estreita e previsível. Ela aceita uma operação conhecida, exige uma conta principal e um ID de objeto conhecidos, executa uma verificação preliminar e tem um efeito declarado. Interfaces genéricas parecem produtivas até que um agente faça uma solicitação inesperada e sua única defesa seja torcer para que um operador perceba um parâmetro sutil.

Comece inventariando as ações que podem excluir, revogar, alternar, desativar, sobrescrever, publicar ou gerar cobranças. Para cada ação, registre os campos de alvo imutáveis, os campos da conta principal, os estados permitidos, o comportamento em cascata, o mecanismo de atualidade, o comportamento de retentativa e o texto da aprovação. Se não conseguir declarar esses fatos, ainda não ofereça a ação a um agente autônomo.

Depois, envie entradas incorretas deliberadas pela barreira: um ID de recurso válido sob a conta errada, um nome de exibição correspondente com dois resultados, um ETag desatualizado, uma lista em massa vazia, um filtro ausente, um alvo recriado com o mesmo nome e um timeout depois do envio. Essas entradas revelam se a fronteira valida o significado ou apenas valida o JSON.

Não resolva a ambiguidade fazendo o agente escrever um plano mais longo. Torne a ambiguidade impossível de representar no contrato da ação. Um agente pode propor uma intenção e reunir evidências. A fronteira das credenciais deve decidir se as evidências identificam um único efeito permitido, neste momento e sob esta conta. Essa divisão cria um sistema que você pode inspecionar quando a solicitação é rotineira e no qual pode confiar quando não é.
