8 min de leitura

Endpoints de rollback para implantações autônomas sem colisões

Projete endpoints de rollback para implantações autônomas que restaurem a release correta, rejeitem estados desatualizados e preservem alterações de produção sem relação.

Endpoints de rollback para implantações autônomas sem colisões

Agentes autônomos de implantação precisam de permissão para falhar com segurança, não de permissão para adivinhar. O rollback perigoso raramente é um comando que falha. É um comando que funciona depois que o mundo mudou e restaura um artefato antigo sobre uma release que o agente não criou.

Uma ação segura de rollback identifica uma tentativa específica de implantação, nomeia uma release anterior específica e se recusa a agir quando sua visão do estado atual ficou desatualizada. Trate o rollback como uma transição de estado protegida, não como um atalho para «a última versão boa». Essa distinção decide se o agente corrige o próprio trabalho ou apaga o trabalho de outra pessoa.

Um rollback deve pertencer a uma única tentativa de implantação

Os endpoints de rollback precisam vincular a reversão à tentativa de implantação que causou a falha suspeita. Um número de versão, sozinho, não cumpre esse papel.

As equipes costumam armazenar uma sequência como 1.8.4, 1.8.5 e 1.8.6 e depois expor uma operação que diz «implantar 1.8.4 em produção». Um agente implanta 1.8.5, recebe um alerta e chama essa operação. Enquanto isso, uma pessoa engenheira implantou a release urgente 1.8.6. O endpoint de rollback aceita a solicitação porque 1.8.4 existe. Agora a produção executa um artefato anterior às duas alterações. A API fez exatamente o que foi solicitado, e esse é o problema.

Mantenha estas identidades separadas:

  • Uma release é um pacote imutável de código, referências de configuração e metadados. Dê a ela um ID durável e um digest do artefato.
  • Uma tentativa de implantação é uma solicitação para colocar uma release em um destino nomeado. Ela tem um ID de implantação, um ator e um ciclo de vida.
  • O estado do destino é o que o ambiente executa naquele momento. Ele inclui uma revisão ou geração que muda a cada transição aceita.
  • Uma intenção de rollback diz que a tentativa de implantação D pode restaurar a release R do destino somente se D ainda for proprietária do estado atual.

O campo que costuma ser esquecido é o vínculo de propriedade. Quando a implantação dep_842 promove a release rel_105, registre que dep_842 criou a geração atual do destino, gen_913. Um rollback vinculado a dep_842 só pode prosseguir enquanto gen_913 continuar atual. Se uma implantação posterior criar gen_914, o serviço deve recusar a solicitação antiga.

Não infira a propriedade comparando registros de data e hora. A ordem dos relógios falha com novas tentativas, workers em fila, reparos manuais e qualquer sistema que permita ao usuário selecionar uma release mais antiga. Armazene a relação direta quando aceitar a promoção.

Isso também responde a uma questão operacional incômoda: um agente pode reverter a implantação de outro agente? Normalmente, não. Uma autoridade separada pode autorizar explicitamente essa intervenção, mas a capacidade comum de rollback deve abranger apenas as ações iniciadas pelo próprio solicitante. Uma autoridade ampla parece conveniente até que dois ciclos de implantação reajam ao mesmo incidente.

A proveniência imutável torna a release anterior conhecida

O serviço precisa capturar a proveniência do rollback antes de alterar o destino, porque depois da promoção a palavra «anterior» se torna ambígua. Consultar o histórico de releases depois de um alerta é uma receita para selecionar o que quer que esteja próximo em uma lista.

Quando um serviço de implantação aceita uma promoção, deve criar um registro que inclua a release estável anterior escolhida naquele momento. Essa release pode ser diferente do evento imediatamente anterior. Por exemplo, um canário pode promover rel_105 enquanto rel_103 continua sendo a base estável e rel_104 foi um experimento interrompido. O destino correto da recuperação pode ser rel_103, não a linha diretamente anterior a rel_105.

Um registro mínimo pode ser assim:

{
  "deployment_id": "dep_842",
  "environment": "production",
  "release_id": "rel_105",
  "artifact_digest": "sha256:8b2c...",
  "source_revision": "4f1d9c7",
  "config_digest": "sha256:1a06...",
  "prior_release_id": "rel_103",
  "created_target_generation": "gen_913",
  "migration_set_id": "mig_77",
  "actor_id": "agent-run-27"
}

O prior_release_id é uma decisão, não um campo de conveniência. Seu controlador de promoção deve escolhê-lo usando regras que as pessoas responsáveis pela operação possam consultar: a última release estável verificada para aquele destino, talvez com configuração e requisitos de migração compatíveis. A operação de rollback consome essa decisão salva. Ela não a recalcula porque a tabela de histórico mudou.

A identidade do artefato precisa de mais do que um rótulo de release compreensível por pessoas. Tags podem mudar de lugar. Rótulos de build podem ser reutilizados por acidente. Um rollback deve implantar o endereço de conteúdo ou outra referência imutável do artefato registrada na tentativa original. Se o registro permitir que uma tag aponte para bytes diferentes depois, o ID da release do destino deve resolver para um digest capturado no momento da promoção.

A configuração exige a mesma disciplina. Reverter os bytes da aplicação e deixar alterados um recurso de funcionalidade, uma referência a segredo de execução, uma política de pull da imagem ou uma configuração de recursos pode criar um sistema que nunca existiu nos testes. Você não precisa duplicar todos os valores no registro da implantação, mas deve registrar uma revisão ou digest imutável da configuração e definir se o rollback a restaura.

O estado do banco de dados cria uma fronteira separada. Uma release que apenas adiciona colunas que aceitam valores nulos geralmente permite um rollback da aplicação. Uma release que remove uma coluna, reescreve valores ou muda semântica pode não permitir. Não prometa um «rollback completo» genérico se o planejador de releases não puder provar a compatibilidade. Marque a implantação como reversível na aplicação, reversível no tráfego ou exigindo reparo. Uma recusa é menos constrangedora do que executar código antigo contra um esquema que ele não entende.

O endpoint precisa da release atual esperada

Uma solicitação de rollback deve transportar tanto a release desejada quanto o estado ativo que ela espera substituir. Sem essa pré-condição, o endpoint não consegue distinguir uma recuperação válida de uma instrução desatualizada.

Use um contrato de solicitação com este formato:

POST /v1/environments/production/rollbacks
Idempotency-Key: 7e4cd1ee-62cb-4efa-985f-4ee0b77d577b
Content-Type: application/json

{
  "origin_deployment_id": "dep_842",
  "expected_current_release_id": "rel_105",
  "expected_target_generation": "gen_913",
  "restore_release_id": "rel_103",
  "reason": "error rate exceeded release threshold",
  "approval_id": "apr_551"
}

O serviço deve derivar restore_release_id de origin_deployment_id quando possível e depois comparar o valor enviado com o prior_release_id armazenado. Manter os dois campos na solicitação ajuda os auditores a ver a intenção declarada pelo agente, mas o registro do servidor prevalece. Nunca permita que um solicitante transforme sua própria implantação em autorização para escolher qualquer artefato histórico.

Em caso de sucesso, retorne a nova tentativa de implantação criada e a nova geração do destino. Não retorne uma resposta vaga com accepted se o sistema puder reservar a transição de forma síncrona.

{
  "rollback_deployment_id": "dep_849",
  "reverted_deployment_id": "dep_842",
  "previous_release_id": "rel_105",
  "current_release_id": "rel_103",
  "target_generation": "gen_914",
  "status": "running"
}

Se o destino ativo não corresponder, retorne uma resposta de conflito. O corpo deve incluir informações suficientes para que o agente relate o ocorrido, mas não autoridade suficiente para improvisar uma nova ação.

HTTP/1.1 409 Conflict
Content-Type: application/json

{
  "error": "stale_rollback",
  "origin_deployment_id": "dep_842",
  "expected_target_generation": "gen_913",
  "observed_target_generation": "gen_914",
  "observed_release_id": "rel_106"
}

Um 409 é um resultado de segurança bem-sucedido. Ensine o agente a parar nesse resultado, anexar a resposta ao registro do incidente e pedir uma nova decisão. Não ofereça uma instrução alternativa como «tente novamente sem a geração esperada». Essa alternativa transforma sua proteção em encenação.

Algumas equipes usam um cabeçalho HTTP If-Match com um ETag em vez de um campo JSON. Isso funciona se o ETag representar o estado do destino e mudar a cada transição. O mecanismo importa menos do que a regra: o comando precisa nomear o estado que pode substituir.

A serialização impede a colisão de duas solicitações válidas

Uma verificação de pré-condição, sozinha, não protege um destino se dois workers puderem passar pela verificação antes que qualquer um confirme a alteração. O serviço de implantação deve serializar as mudanças no mesmo ambiente e usar uma comparação e troca atômica no armazenamento de estado.

Suponha que o destino atual seja (rel_105, gen_913). Um agente envia um rollback e uma pessoa operadora envia rel_106. As duas solicitações leem gen_913. Se o serviço verificar na memória da aplicação e depois gravar sem condição, ambas poderão declarar sucesso. A última gravação vence, e seu histórico de auditoria registra um estado que talvez nunca tenha existido para os usuários.

Coloque a comparação e a alteração na mesma transação ou em uma gravação condicional. Uma implementação relacional poderia emitir este padrão:

UPDATE environment_targets
SET release_id = :restore_release_id,
    generation = generation + 1,
    active_deployment_id = :rollback_deployment_id,
    updated_at = CURRENT_TIMESTAMP
WHERE environment = :environment
  AND generation = :expected_generation
  AND release_id = :expected_release_id;

O serviço verifica o número de linhas afetadas. Uma linha alterada reserva a transição de estado. Zero linhas significa conflito. Em seguida, ele deve ler o destino atual e retornar os valores observados na resposta 409.

Uma fila não substitui essa condição. Filas reduzem a chance de trabalho concorrente, mas uma entrega duplicada, um caminho manual fora da fila ou uma nova tentativa de um worker ainda podem gerar comandos concorrentes. Mantenha a gravação condicional no local onde o estado vive.

A idempotência resolve uma falha diferente. Um agente pode perder a resposta depois que o serviço aceita o rollback. Se repetir a solicitação com a mesma chave de idempotência, o serviço deve retornar a implantação e o status do rollback original. Ele não deve reservar outra geração nem iniciar uma segunda execução.

Limite a idempotência ao solicitante e ao endpoint, registre um digest do corpo da solicitação e rejeite uma chave reutilizada com um corpo diferente. Caso contrário, um cliente com defeito poderá associar uma intenção nova a uma solicitação anterior ao reutilizar um identificador.

Um rollback pode preservar um estado ruim de dependência

Mantenha as chaves SSH fora do agente
Encaminhe os comandos de implantação SSH pelo Sallyport para que o agente nunca receba a chave SSH.

O rollback da aplicação e a recuperação do ambiente são operações separadas. Um endpoint que implanta código antigo não consegue tornar automaticamente todas as dependências compatíveis outra vez.

Já vi a versão previsível dessa falha: a release rel_105 introduziu código que grava um novo valor de enumeração. Depois, uma migração restringiu uma limitação do banco de dados para permitir apenas os novos valores. A release falhou por um motivo não relacionado, e a pessoa operadora restaurou rel_103. O código antigo gravou o valor anterior, o banco o rejeitou e o incidente cresceu porque o rollback parecia completo no painel de implantação.

O endpoint não causou a alteração do esquema, mas sua resposta de sucesso fez uma afirmação falsa. Evite essa afirmação exigindo metadados da release que descrevam a compatibilidade em termos concretos. No mínimo, registre se a release restaurada pode ler os dados atuais, gravar dados atuais e operar com a revisão de configuração do destino.

O gerenciamento de tráfego tem sua própria armadilha. Um rollback de canário normalmente deve alterar apenas a alocação de tráfego pertencente àquele canário. Se uma release sem relação tiver ajustado o pool estável ou outro controlador tiver alterado uma regra de roteamento, um endpoint de rollback que grave um documento inteiro de roteamento poderá apagar essas mudanças. Use versões no nível do recurso ou altere apenas os campos de alocação reservados pela implantação.

O mesmo princípio vale para a infraestrutura. Se uma release criou uma fila, um bucket, uma função ou uma regra de firewall que um trabalho posterior adotou, excluí-los durante a reversão pode prejudicar outro serviço. A limpeza exige um registro de propriedade do recurso e uma verificação de que nenhuma implantação posterior o reivindicou. Se não puder estabelecer essa propriedade, deixe o recurso no lugar e crie uma tarefa de reparo.

Para operações irreversíveis, escolha uma correção posterior. O agente pode desativar um recurso de funcionalidade, desviar o tráfego ou implantar uma release corretiva. As pessoas operadoras não gostam dessa resposta porque «rollback» parece mais rápido, mas uma reversão visualmente limpa que destrói dados posteriores custa mais tempo do que um plano de reparo.

Os agentes precisam de autoridade restrita e de um ponto de parada visível

Um agente autônomo deve receber a menor autoridade de ação capaz de concluir a implantação atribuída. Ele não precisa de credenciais brutas de nuvem, de um shell geral com acesso à produção nem de um endpoint que aceite IDs de release arbitrários.

Dê ao agente um identificador de implantação quando ele iniciar uma release. Esse identificador pode autorizar leituras de status, verificações de integridade, alterações de tráfego dentro da alocação da implantação e um rollback que nomeie a implantação original. Faça-o expirar quando a implantação chegar a um estado final ou quando uma pessoa revogar a execução. O serviço de implantação ainda precisa impor a propriedade no servidor, porque um identificador pode ser copiado ou um cliente pode apresentar falhas.

A aprovação humana deve ocorrer antes da fronteira irreversível, não depois que o agente já montou um comando irreversível. Uma política sensata pede aprovação quando um agente inicia uma implantação em produção e depois permite que ele reverta exatamente essa implantação enquanto a pré-condição de propriedade for válida. Se o agente encontrar uma release posterior, precisará de uma nova aprovação para qualquer intervenção. Esse é um bom momento para desacelerar, porque alguém mudou a situação.

O Sallyport pode manter as credenciais HTTP e SSH fora do processo do agente enquanto uma pessoa aprova a execução do agente ou marca uma credencial para aprovação a cada uso. Esse controle ajuda a proteger o caminho da ação, mas o serviço de rollback ainda precisa de suas próprias verificações de release e geração; a custódia das credenciais não define a propriedade da implantação.

Evite nomes de capacidade como production:rollback:any. Eles convidam o solicitante a escolher o escopo em tempo de execução. Prefira uma capacidade emitida pelo servidor e vinculada a dep_842, ao ambiente production e à rota específica de rollback. Se o agente solicitar um destino sem relação, a camada de autorização deve rejeitá-lo antes que o controlador de implantação avalie a solicitação.

Registre a identidade do processo ou da carga de trabalho do agente em todas as solicitações. Uma pessoa deve conseguir responder quem iniciou dep_842, qual código assinou ou autenticou o solicitante, qual aprovação o cobriu e se alguém revogou o acesso antes do fim da execução. Contas de automação anônimas transformam todo incidente em trabalho arqueológico.

A verificação deve testar a release restaurada, não a solicitação

Proteja o endpoint de rollback
Insira credenciais bearer, básicas ou de cabeçalho personalizado na chamada HTTP protegida de rollback.

Um rollback só chega ao fim depois que o destino executa a release pretendida e o serviço verifica as condições que justificaram a recuperação. HTTP 202, uma saída de comando bem-sucedida ou um evento do controlador dizendo «aplicado» não prova que a release antiga atende ao tráfego corretamente.

Defina a verificação de acordo com o modo de falha real da implantação. Se latência ou erros dispararam o rollback, observe o serviço restaurado pelo mesmo caminho de medição depois que o tráfego chegar até ele. Se uma release de worker consumiu jobs malformados, verifique a versão do worker e uma carga controlada. Se um erro de configuração causou falhas na inicialização, inspecione as instâncias prontas e a revisão de configuração que carregaram.

Mantenha uma janela de observação limitada e registre o resultado. O endpoint pode informar verifying e depois succeeded, failed ou needs_operator. Não espere indefinidamente por uma métrica que pode estar indisponível. Um limite de tempo deve produzir um resultado inconclusivo explícito, seguido de uma decisão da pessoa operadora.

O evento de auditoria deve conectar todas as etapas: o alerta ou regra que solicitou a reversão, a implantação de origem, o estado esperado, a reserva condicional, os eventos de execução, as evidências de integridade, o estado final e qualquer revogação. Os eventos precisam de controles de ordenação e integridade, porque uma linha do tempo amigável de implantação não é suficiente durante uma disputa.

O Sallyport registra execuções de agentes e ações individuais em um registro de auditoria criptografado e encadeado por hash, e sp audit verify verifica essa cadeia offline sem uma chave do cofre. Use esse tipo de evidência para mostrar que um agente solicitou uma ação e mantenha os próprios registros de transição de estado e verificação do serviço de implantação como a fonte autorizada sobre o que mudou.

Comandos conhecidos de rollback precisam de um wrapper mais seguro

Proteja as credenciais de rollback
O Sallyport executa chamadas à API de rollback enquanto as credenciais de produção permanecem criptografadas no cofre.

kubectl rollout undo é útil para uma pessoa operadora trabalhando diretamente em um Kubernetes Deployment, mas não é um contrato completo para recuperação autônoma. A documentação do Kubernetes informa que kubectl rollout undo reverte para a revisão anterior da implantação, a menos que o solicitante forneça --to-revision. Esse padrão faz sentido durante um diagnóstico manual. Ele não prova que a revisão anterior pertence à execução do agente que falhou.

Um Kubernetes Deployment acompanha o histórico de revisões em ReplicaSets, enquanto revisionHistoryLimit controla quanto desse histórico o Kubernetes retém. Esse histórico é um artefato do controlador, não o registro empresarial da base aprovada de uma release, da compatibilidade da configuração ou da propriedade do agente. Quando o histórico é eliminado, o «undo» também pode não encontrar a revisão esperada por um processo externo de implantação.

Não entregue ao agente uma credencial geral do kubectl e chame o comando de seu endpoint de rollback. Coloque um controlador ou serviço de implantação entre o agente e o cluster. O serviço deve resolver o registro da implantação de origem, comparar a geração ativa do destino, reservar a alteração de estado e chamar a plataforma subjacente somente depois de passar por essas verificações.

A mesma crítica vale para comandos de provedores de nuvem que dizem «implantar a revisão X» ou controles de CI que dizem «executar novamente a release anterior». Eles operam sobre um recurso da plataforma. Não sabem se uma release está relacionada ao incidente atual do agente, a menos que seu plano de controle forneça esse contexto.

Mantenha o comando da plataforma restrito também. Se o serviço puder alterar a revisão de uma carga de trabalho nomeada, evite conceder a ele mutação em todo o cluster. Um wrapper que preserva credenciais amplas apenas escondeu o perigo atrás de outra API.

Crie um registro de releases antes de automatizar a recuperação

Você pode introduzir um rollback protegido sem substituir todos os sistemas de implantação. Comece tornando o registro de releases a fonte autorizada para um destino de produção e faça os caminhos humano e do agente passarem pela mesma transição condicional.

Uma sequência prática de adoção tem cinco partes:

  1. Atribua IDs imutáveis às releases e às tentativas de implantação, depois registre a release anterior aprovada e a geração do destino no momento da promoção.
  2. Adicione um endpoint que exija origin_deployment_id, a release esperada, a geração esperada e uma chave de idempotência.
  3. Torne condicional a atualização do destino no banco de dados ou no armazenamento de controle e retorne 409 para toda divergência.
  4. Classifique cada release quanto à reversibilidade da aplicação, da configuração, dos dados e do tráfego antes da promoção.
  5. Exija evidências de verificação antes que o controlador marque um rollback como concluído.

Execute esse contrato em modo de relatório antes de permitir que os agentes o executem. Deixe o serviço calcular o que restauraria e se rejeitaria a solicitação. Compare essas decisões com as ações reais dos incidentes. Isso revela registros de proveniência ausentes e caminhos manuais ocultos sem dar à automação a chance de sobrescrever a produção.

Depois, torne a rejeição algo rotineiro. Um rollback desatualizado deve criar um item de incidente compreensível com a release e a geração observadas, não uma falha misteriosa que incentive alguém a contornar o endpoint. O endpoint conquista confiança quando recusa uma solicitação insegura de forma consistente, inclusive quando a solicitação vem das pessoas que o criaram.

O primeiro campo a adicionar não é force. É expected_target_generation. Quando suas implantações carregarem esse fato e preservarem a base original, um agente poderá reverter sua própria release com um limite claro. Até lá, o rollback autônomo será um comando de implantação antigo apontado para um alvo em movimento.

FAQ

Qual deve ser o alvo de um rollback de implantação?

Um rollback de implantação deve identificar um artefato anterior e a instância exata da implantação que o introduziu. «Versão anterior» é vago demais, porque outra release pode ter alterado o destino depois que o agente começou seu trabalho.

Como impedir que um rollback substitua uma implantação mais recente?

Use uma pré-condição de comparação e troca, como expected_current_release_id. O serviço deve rejeitar a solicitação quando a release ativa for diferente, porque continuar substituiria uma implantação posterior de outra pessoa.

É seguro permitir que um agente de IA chame uma API de rollback?

Somente quando o destino tiver um único gravador autorizado, as revisões forem imutáveis e o endpoint verificar a revisão atual antes de alterar qualquer coisa. Um endpoint simples que aceita um ambiente e uma versão não consegue garantir isso.

Quais dados preciso armazenar para oferecer rollbacks seguros?

Mantenha um catálogo imutável de releases com o digest do artefato, a revisão do código-fonte, o digest da configuração, o conjunto de migrações, o ID da implantação, o ator e os registros de data e hora. Armazene o ID real da release anterior em vez de pedir ao serviço de rollback que infira o histórico no momento da solicitação.

Um rollback deve reverter migrações do banco de dados?

Não. Um rollback pode restaurar o código da aplicação, pesos de tráfego ou um valor de configuração, mas alterações destrutivas de esquema geralmente exigem uma correção posterior separada. Trate a compatibilidade do banco de dados como uma propriedade da release, não como um efeito automático do rollback da aplicação.

O que um agente deve fazer depois de um conflito de rollback?

Ele deve retornar um conflito explícito, como HTTP 409, com o ID da release atual observada e a pré-condição solicitada. O agente deve parar, relatar o conflito e aguardar uma pessoa autorizada ou um novo plano de implantação.

Posso usar kubectl rollout undo para um rollback autônomo?

kubectl rollout undo pode ser útil para uma pessoa investigando um Deployment, mas seu comportamento padrão, que usa a revisão anterior, não vincula a solicitação à release que o agente pretende reverter. Coloque um serviço de implantação na frente desse comando e aplique ali as verificações de propriedade e revisão.

Como as solicitações de rollback devem lidar com novas tentativas?

Use uma única chave de idempotência para uma intenção de rollback e armazene o resultado final associado a ela. Se o agente repetir a solicitação depois de um timeout, o serviço deve retornar o resultado anterior em vez de iniciar outro rollout.

O que um registro de auditoria de uma implantação autônoma deve conter?

Registre a solicitação, a identidade do ator, os IDs de release esperados e observados, o destino escolhido, a aprovação, os eventos de execução e o resultado da verificação. Mantenha evidências suficientes para explicar tanto uma alteração bem-sucedida quanto uma recusa em alterar qualquer coisa.

Quais campos pertencem a um endpoint de rollback?

Um endpoint útil transporta a release atual esperada, uma release anterior identificada, o motivo, uma chave de idempotência e uma referência de aprovação. Se uma API não aceitar esses campos, mantenha-a atrás de um controlador que aceite.

Sallyport

O Sallyport executa chamadas de API e comandos SSH pelo seu agente de IA. As chaves ficam em um cofre local no seu Mac; você aprova cada execução e toda ação vai para um registro selado.

© 2026 Sallyport · Código aberto sob Apache-2.0 · Oleg Sotnikov