Autonomous Loop Security|INEMA.CLUB-PRO

Lesson 7 · 20 min

Irreversible needs a human; run outside the terminal without increasing the blast radius

Sending, publishing, deleting, and spending can't be undone. In the loop, these actions become requests that wait at a gate that only you open, seeing the destination and content. And when the loop leaves the terminal for systemd, it takes the cap, the sandbox, and the gate with it, not your whole session.

Start the lesson
Two metal keys in two separate locks on an industrial vault panel.

In this lesson you will

  1. 1porta.py: request, approve with hash, run once
  2. 2A real irreversible-action policy, anonymized
  3. 3systemd with a time and memory cap and the Codex sandbox inside
  4. 4Cloud Routines: the same care, without confirming details

Goal: put sending, push, and deleting behind a gate that only the human opens, and run the loop under systemd with a cap and sandbox.

01The gate to the irreversible

Click each step.

Click each block in the diagram to see what it does.

It's N1 of the POLITICA (lesson 4): the agent prepares, the human executes.

02Watch the queue stop at the gate

The loop's nightly cycle. The send action is irreversible: on the first run it stops and waits. Approve (resume) and it goes on.

queued

running

done

waiting for human

Illustrative simulation. The real gate is in the rehearsal just below.

03Rehearsal: the gate from start to finish

Request, try without approval, approve without a terminal, approve "as a human", tamper afterward, approve again, execute, and try to reuse. No model; the send is a line in saida.log.

Terminal · gate rehearsal
bash ~/projetos/loop-r-eng-seguranca-v72/kit/porta/ensaio-porta.sh 2>&1
Example from the repository
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

Four refusals and one execution; the 1 at the end is the only line in saida.log. The ids change on every run.

04A real policy, anonymized

Irreversible-action rules from the global CLAUDE.md of an INEMA machine, and lessons that became rules.

1. Removing asks, every time

A published deletion or removal requires individual approval for each one, with the target identified beforehand. Generic, batch, or publishing authorization does not count as deletion approval.

Sending email and deleting an event are irreversible: confirm first.

05Outside the terminal: cap and sandbox together

systemd gives the cap (time, memory); the Codex sandbox, inside it, gives the isolation that the user systemd did not provide on this machine (lesson 6).

Terminal · cap and isolation in 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: $?"
File · kit/systemd/loop-seguro.service (template; comments translated for reading)
# loop-seguro.service — user unit template for running one agent cycle outside the terminal
# without increasing the blast radius. Replace MEU-PROJETO and check with prova-isolamento.sh BEFORE turning it on.
#   cp loop-seguro.service ~/.config/systemd/user/ && systemctl --user daemon-reload
#   systemctl --user start loop-seguro.service && journalctl --user -u loop-seguro -n 20
#
# What really holds (tested on 19/10/2026, systemd 255, Ubuntu, kernel with
# apparmor_restrict_unprivileged_userns=1):
#   - caps: MemoryMax, TimeoutStartSec (oneshot does not accept RuntimeMaxSec), timeout and flock (they work in systemd --user)
#   - isolation: the Codex sandbox (-s workspace-write) INSIDE the service
# What did NOT hold on this machine: PrivateNetwork=, ProtectHome=, IPAddressDeny= in systemd --user.
# The journal says "proceeding without" and the service runs without the lock. Don't count on them without proof.
[Unit]
Description=One cycle of the agent loop (Autonomous Loop Security course)

[Service]
Type=oneshot
WorkingDirectory=%h/projetos/MEU-PROJETO
# Fixed PATH: the service does not inherit your shell (or your keys). Do not put an EnvironmentFile with a secret.
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
Example from the repository
## 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

The sleep 10 was killed at 3 s (exit 1). Inside the same systemd-run, the Codex sandbox blocked writes outside and the network.

06Routines and other schedulers

What can be said with confidence.

1. What is known

There are reports (secondary source, not confirmed in the docs) of scheduled agents in the Claude Code cloud, the routines, triggered by a schedule, an API call, or a GitHub event.

The current limits were not confirmed for this course: treat it as a feature to check in the docs before using it.

07Practice

The gate, systemd, and your list of irreversible actions.

E18 · The gate in the rehearsal

10 min

Run the gate rehearsal. Then approve a request yourself, in your own terminal: python3 porta.py pedir, aprovar and executar.

Done when: the rehearsal shows four RECUSADO lines, one EXECUTADO, and ends with 1; your executar prints EXECUTADO once and, when repeated, sem aprovação humana.

E19 · Cap and sandbox in systemd

10 min

Run the systemd block on your machine (Linux with systemd).

Done when: the first step ends with saída: 1 (killed by the cap) and the second with ISOLAMENTO: OK and saída: 0.

E20 · The list of your irreversible actions

15 min

Write in the project's AGENTS.md (or CLAUDE.md) the list of actions in your loop that can't be undone and the path for each one: porta.py, the deny from lesson 4, or the guard from lesson 5.

Done when: grep -ci "irreversível" AGENTS.md → a number greater than 0, and each action on the list appears in a deny, in the guard, or in a porta.py pedir.

08Lesson quiz

Question 1 of 4

Why does the approval store the hash of the content?skill

09In three sentences

Asking ≠ executingThe agent asks; you approve the exact content; it runs once.
A boundary, not a spineThe approval lives where the agent can't write.
Take the cap with youOutside the terminal: timeout, MemoryMax, proven sandbox and the gate.

Going further

Previous lessonNext lesson