Irreversível pede humano; rodar fora do terminal sem aumentar o raio de dano
Enviar, publicar, apagar e gastar não têm volta. No loop, essas ações viram pedidos que esperam numa porta que só você abre, vendo destino e conteúdo. E quando o loop sai do terminal para o systemd, ele leva junto o teto, o sandbox e a porta, não a sua sessão inteira.
1porta.py: pedir, aprovar com hash, executar uma vez
2Uma política real de ação irreversível, anonimizada
3systemd com teto de tempo e memória e o sandbox do Codex dentro
4Routines na nuvem: o mesmo cuidado, sem confirmação de detalhes
Objetivo: pôr envio, push e apagar atrás de uma porta que só o humano abre e rodar o loop no systemd com teto e sandbox.
01 · A porta do irreversível
Clique em cada etapa.
Clique em cada bloco do diagrama para ver o que ele faz.
É o N1 da POLITICA (aula 4): o agente prepara, o humano executa.
02 · Veja a fila parar na porta
Ciclo noturno do loop. A ação de envio é irreversível: na primeira execução ela para e espera. Aprove (retomar) e ela segue.
na fila
rodando
feito
esperando humano
Simulação ilustrativa. A porta de verdade está no ensaio logo abaixo.
03 · Ensaio: a porta do começo ao fim
Pedir, tentar sem aprovação, aprovar sem terminal, aprovar "como humano", adulterar depois, aprovar de novo, executar e tentar reusar. Nenhum modelo; o envio é uma linha em saida.log.
pedido 20261019-065013-4181: enviar-email → cliente@exemplo.invalid (30 caracteres). Aguardando aprovação humana.
RECUSADO: 20261019-065013-4181 sem aprovação humana
saída: 1
RECUSADO: aprovar exige um terminal humano (stdin não é tty)
saída: 1
APROVADO 20261019-065013-4181 (hash 50a9d2859698c516)
RECUSADO: o conteúdo de 20261019-065013-4181 mudou depois da aprovação
saída: 1
APROVADO 20261019-065014-b7be (hash 50a9d2859698c516)
EXECUTADO 20261019-065014-b7be: enviar-email → cliente@exemplo.invalid
saída: 0
RECUSADO: 20261019-065014-b7be sem aprovação humana
saída: 1
1
Quatro recusas e uma execução; o 1 no fim é a única linha em saida.log. Os ids mudam a cada rodada.
No ensaio, o script finge digitar o id num pseudo-terminal. Na vida real, você roda python3 porta.py aprovar [id] no seu terminal, lê o conteúdo e digita. Troque o "executar" do ensaio pelo seu envio de verdade.
04 · Uma política real, anonimizada
Regras de ação irreversível do CLAUDE.md global de uma máquina INEMA, e lições que viraram regra.
1. Remover pede, cada vez
Exclusão ou remoção publicada exige aprovação individual para cada uma, com o alvo identificado antes. Autorização genérica, em lote ou de publicação não serve como aprovação de exclusão.
Enviar e-mail e apagar evento são irreversíveis: confirmar antes.
2. Chave não é permissão
Nenhuma API sem autorização explícita daquele serviço e finalidade. Ter a credencial no .env não autoriza usá-la; pedido de resultado ("faça", "continue") também não.
A regra vale para scripts, subagentes e qualquer ferramenta intermediária.
3. Parar e chamar
Num loop longo, para e chama o humano: gasto de crédito ou API, ação irreversível ou externa, credencial ausente, decisão de negócio.
E duas regras de convivência: não apague o que você não criou; não mate processo que você não criou.
Lição real (15/10/2026)Matar processo só depois de readlink /proc/[pid]/cwd mostrar que é seu: o servidor de outra sessão foi derrubado por engano, achando que era o próprio.
4. Volta não é desfazer
git checkout [arquivo] volta ao último commit, não ao estado de antes do teste: em 05/10/2026 apagou regras não commitadas. Teste destrutivo: commit antes ou cópia fora.
Por isso a guarda da aula 5 nega checkout -- . e reset --hard.
05 · Fora do terminal: teto e sandbox juntos
O systemd dá o teto (tempo, memória); o sandbox do Codex, dentro dele, dá o isolamento que o systemd do usuário não deu nesta máquina (aula 6).
Terminal · teto e isolamento no systemd
P=~/projetos/loop-r-eng-seguranca-v72/kit/prova-isolamento.sh
W=/tmp/ensaio-seg/iso; mkdir -p $W
echo "## teto de tempo: RuntimeMaxSec=3 num sleep 10"
systemd-run --user --wait --pipe --quiet -p RuntimeMaxSec=3 sleep 10; echo "saída: $?"
echo "## fora do terminal, com teto E sandbox do Codex dentro"
bash $P systemd-run --user --pipe --wait --quiet -p MemoryMax=1G -p RuntimeMaxSec=60 -- \
codex sandbox -P :workspace -C $W --
echo "saída: $?"
# loop-seguro.service — modelo de unit de usuário para rodar um ciclo do agente fora do terminal
# sem aumentar o raio de dano. Troque MEU-PROJETO e confira com o prova-isolamento.sh ANTES de ligar.
# cp loop-seguro.service ~/.config/systemd/user/ && systemctl --user daemon-reload
# systemctl --user start loop-seguro.service && journalctl --user -u loop-seguro -n 20
#
# O que segura de verdade (testado em 19/10/2026, systemd 255, Ubuntu, kernel com
# apparmor_restrict_unprivileged_userns=1):
# - tetos: MemoryMax, TimeoutStartSec (oneshot não aceita RuntimeMaxSec), timeout e flock (funcionam no systemd --user)
# - isolamento: o sandbox do Codex (-s workspace-write) DENTRO do serviço
# O que NÃO segurou nesta máquina: PrivateNetwork=, ProtectHome=, IPAddressDeny= no systemd --user.
# O journal diz "proceeding without" e o serviço roda sem a trava. Não conte com elas sem prova.
[Unit]
Description=Um ciclo do loop do agente (curso Segurança do Loop Autônomo)
[Service]
Type=oneshot
WorkingDirectory=%h/projetos/MEU-PROJETO
# PATH fixo: o serviço não herda o seu shell (nem as suas chaves). Não ponha EnvironmentFile com segredo.
Environment=PATH=%h/.npm-global/bin:/usr/local/bin:/usr/bin:/bin
StandardInput=file:%h/projetos/MEU-PROJETO/longrun/prompt.md
ExecStart=/usr/bin/flock -n %t/loop-seguro.lock timeout 2h codex exec -s workspace-write --skip-git-repo-check -C %h/projetos/MEU-PROJETO -
MemoryMax=4G
TimeoutStartSec=3h
NoNewPrivileges=yes
Exemplo do repositório
## teto de tempo: RuntimeMaxSec=3 num sleep 10
saída: 1
## fora do terminal, com teto E sandbox do Codex dentro
escreve-dentro ABERTO
escreve-fora BLOQUEADO
rede BLOQUEADO
le-segredo ABERTO
aviso: lê arquivos fora da pasta; tire segredos do alcance ou corte a rede
ISOLAMENTO: OK
saída: 0
O sleep 10 foi morto aos 3 s (saída 1). Dentro do mesmo systemd-run, o sandbox do Codex bloqueou escrita fora e rede.
Num serviço Type=oneshot, RuntimeMaxSec= não tem efeito: o systemd-analyze --user verify avisa "RuntimeMaxSec= has no effect in combination with Type=oneshot. Ignoring." No modelo de unit, o teto é TimeoutStartSec= mais o timeout na linha do comando.
06 · Routines e outros agendadores
O que dá para dizer com segurança.
1. O que se sabe
Há relatos (fonte secundária, não confirmada na doc) de agentes agendados na nuvem do Claude Code, as routines, com gatilho por agenda, API ou evento do GitHub.
Os limites atuais não foram confirmados para este curso: trate como recurso a conferir na doc antes de usar.
2. A mesma regra
Onde quer que o loop rode, ele leva só o que a etapa precisa: sem as suas chaves, sem rede onde lê dado privado, sem ação irreversível fora da porta.
Agendar não muda a Regra de Dois; só tira você de perto. Mais motivo para a porta.
07 · Prática
A porta, o systemd e a sua lista de irreversíveis.
E18 · A porta no ensaio
10 min
Rode o ensaio da porta. Depois aprove um pedido você mesmo, no seu terminal: python3 porta.py pedir, aprovar e executar.
Pronto quando: o ensaio mostra quatro linhas RECUSADO, uma EXECUTADO e termina em 1; o seu executar imprime EXECUTADO uma vez e, repetido, sem aprovação humana.
E19 · Teto e sandbox no systemd
10 min
Rode o bloco do systemd na sua máquina (Linux com systemd).
Pronto quando: o primeiro passo termina em saída: 1 (morto pelo teto) e o segundo em ISOLAMENTO: OK e saída: 0.
E20 · A lista dos seus irreversíveis
15 min
Escreva no AGENTS.md (ou CLAUDE.md) do projeto a lista das ações do seu loop que não têm volta e o caminho de cada uma: porta.py, deny da aula 4 ou guarda da aula 5.
Pronto quando:grep -ci "irreversível" AGENTS.md → um número maior que 0, e cada ação da lista aparece num deny, na guarda ou num porta.py pedir.
08 · Teste da aula
Pergunta 1 de 4
Por que a aprovação guarda o hash do conteúdo?competência
Correto
Você aprova o que leu. Se alguém (ou o agente) muda o texto depois, o executar recusa: "o conteúdo mudou depois da aprovação".
Não é essa
Você aprova o que leu. Se alguém (ou o agente) muda o texto depois, o executar recusa: "o conteúdo mudou depois da aprovação".Rever: A porta do irreversível
Pergunta 2 de 4
O tty exigido no aprovar é a fronteira de segurança?competência
Correto
Um pseudo-terminal finge um tty (o ensaio usa script). O que segura é o agente não conseguir escrever a aprovação, porque a pasta está fora do sandbox dele.
Não é essa
Um pseudo-terminal finge um tty (o ensaio usa script). O que segura é o agente não conseguir escrever a aprovação, porque a pasta está fora do sandbox dele.Rever: A porta do irreversível
Pergunta 3 de 4
O loop vai para o systemd. O que precisa ir junto?
Correto
Fora do terminal você não está olhando. O raio de dano tem de caber no teto, no sandbox e na porta, não na sua sessão.
Não é essa
Fora do terminal você não está olhando. O raio de dano tem de caber no teto, no sandbox e na porta, não na sua sessão.Rever: Ensaio: a porta do começo ao fim
Pergunta 4 de 4
Num Type=oneshot, qual teto de tempo o systemd respeita?
Correto
O systemd-analyze avisa que RuntimeMaxSec é ignorado em oneshot. MemoryMax é teto de memória, não de tempo.