Skip to content

refactor(module): purge Nix antiquotes from payload bodies (#154 Phase 2) - #182

Open
defangdevs wants to merge 3 commits into
refactor/phase1-deinline-payloadsfrom
refactor/phase2-purge-antiquotes
Open

refactor(module): purge Nix antiquotes from payload bodies (#154 Phase 2)#182
defangdevs wants to merge 3 commits into
refactor/phase1-deinline-payloadsfrom
refactor/phase2-purge-antiquotes

Conversation

@defangdevs

Copy link
Copy Markdown
Owner

Phase 2 of #154, stacked on #181 (Phase 1); retarget after it merges. This is the content-review PR of the series: every modules/src/ payload becomes a genuine, backend-neutral file — real shell/python/markdown/Caddyfile, zero ${pkgs.*}/${cfg.*} — and the committed tests/golden/ diff in this PR is the exact rendered-behavior delta for review.

Conventions applied (from the issue)

  • Binaries from unit PATH: attach script (ttyd unit gains tmux), webhook spawner (daemon unit gains jq/coreutils/agent-box-session), spot monitor (unit gains curl tmux jq util-linux systemd coreutils), supervisor/CLIs use jq/tmux/bash already on the agent PATH.
  • AGENT_BOX_*_BIN env where a binary is deliberately not on the agent PATH: grep/find (transcript lookups), hostname (codex UTS re-exec). Keeping them off the agent-visible PATH avoids a behavior change for sessions.
  • AGENT_BOX_* config env: unit environment for daemons (spot monitor's USERS/GRACE/POLL/MSG — with %%% escaping, a hazard the baked-in path never had); a two-line generated wrapper exports config for the user-invoked CLIs.
  • Supervisor is now ONE user-independent script (agent-box-supervisor replaces per-user agent-box-<user>-start). Its whole per-user contract is unit env: AGENT_BOX_SESSIONS_SEED, AGENT_BOX_AGENT_BINS (name=path pairs replacing the generated case arms), AGENT_BOX_HOST_LABEL, AGENT_BOX_ENV_EXEC, AGENT_BOX_CODEX_RC, AGENT_BOX_AGENTS_POINTER, AGENT_BOX_WEBHOOK_REPO (doubles as the webhook flag). This is precisely the surface Phase 3's agent-box@.service template unit + drop-ins will consume. env-exec and attach are likewise now singletons.
  • Caddyfile fragments are plain @TOKEN@ templates (@USER@, @USER_ENV@, @SETTINGS_SOCKET@, @DOWNLOADS_DIR@, @TTYD_PORT@, @WEBHOOK_PATH@, @WEBHOOK_SOCKET@, @DOMAIN@) bound by one replaceStrings each — the placeholder contract the Phase 4 native renderer reuses. Rendered Caddyfile is byte-identical.
  • default AGENTS.md is plain markdown + @WEBHOOK_SECTION@; rendered guides byte-identical in both webhook-on and -off configs.
  • Security exception, on purpose: the password helper keeps HASH_FILE/COOKIE_FILE/ENV_SUFFIX/CADDY compiled into the store script (generated tail after the real-python body). It runs via sudo — env-supplied paths would hand the caller a root-write redirect primitive.
  • update.sh kept its pre-existing REPO/CURRENT_REV/PIN_FILE env names (unit-internal; renaming would be churn). The webAuthSecretsService script body (a per-user eval-time loop) is deferred to the Phase 3 unit redesign, where it needs restructuring anyway.

Verification

  • All src scripts pass bash -n / py_compile; flake8 still gates the assembled settings daemon & password helper via writePython3Bin.
  • Byte-identical where no change was intended: Caddyfile, AGENTS.md guides, sudoers, tmpfiles, update script, webhook/settings sockets.
  • Green: golden-snapshot (fixture regenerated & reviewed), module-generated-up-to-date, multi-user, module-single-file, download-route, webhook-route (aarch64). The x86_64 VM tests in CI (sessions, webhook, settings-page, download-files, self-serve-domain) execute all converted scripts end-to-end.

Third checkbox of #154.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NPHNnT2DsWHLhbbhsq2Wc7

lionello and others added 2 commits August 4, 2026 11:44
… Phase 2)

Every modules/src/ payload is now a genuine, backend-neutral file — real
shell/python/markdown/Caddyfile with no ${pkgs.*}/${cfg.*} — spliced via
the escaping @@include:@@ marker. Values reach the scripts per the issue's
conventions:

- binaries: bare names on the owning unit's PATH (ttyd unit gains tmux;
  the webhook daemon unit gains jq/coreutils/agent-box-session; the spot
  monitor unit gains curl/tmux/jq/util-linux/systemd/coreutils), or
  AGENT_BOX_*_BIN unit env where deliberately NOT on the agent PATH
  (grep/find, hostname).
- config: AGENT_BOX_* env — on the unit for daemons, exported by a
  two-line generated wrapper for the user-invoked CLIs (agent-box-session,
  agent-box-webhook).
- the supervisor is ONE user-independent script (agent-box-supervisor):
  per-user values (sessions seed, agent→binary map, host label, env-exec
  wrapper, codex-rc wrapper, AGENTS.md pointer, webhook repo/flag) are now
  its unit-environment contract — the exact surface Phase 3's template
  units + drop-ins need.
- Caddyfile fragments are plain @token@ templates bound by one
  replaceStrings call each — the placeholder contract for the Phase 4
  native renderer. Rendered Caddyfile is BYTE-IDENTICAL.
- default AGENTS.md is plain markdown with a @WEBHOOK_SECTION@ token;
  rendered guides are BYTE-IDENTICAL.
- password helper keeps its per-user paths COMPILED IN (sudo boundary —
  env-supplied paths would be a root-write redirect primitive); they moved
  to a generated tail after the real-python body.

Byte-stable where required: Caddyfile, AGENTS.md guides, update script,
sudoers, tmpfiles all identical. The reviewed golden diff is confined to
unit env/PATH additions and the script bodies themselves (store-path
references → PATH/env lookups).

All src scripts pass bash -n / py_compile; eval checks green
(golden-snapshot, module-generated-up-to-date, multi-user,
module-single-file, download-route, webhook-route).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPHNnT2DsWHLhbbhsq2Wc7
…bel in tests

The Phase 2 rename to one shared agent-box-supervisor script broke the
settings daemon's /proc argv scan (it looked for agent-box-<user>-start),
so the page's "restart" button silently degraded from a unit bounce to a
session bounce — caught by the settings-page VM test's MainPID-change
wait, exactly what that assertion exists for. The scan's own-uid
restriction is what scopes the now-shared name to the right unit.

sessions.nix likewise asserted the old baked-in literals; the host label
now rides the unit environment and the Remote Control name derives from
$USER, so assert those.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPHNnT2DsWHLhbbhsq2Wc7
…n the miss

The Phase 2 rename to the shared agent-box-attach left the sessions
test's grep -o matching nothing; the empty substitution turned
`grep -q '-T hyperlinks'` into a stdin read on the backdoor shell, which
hung the run to the 25-minute CI cap (conclusion "cancelled", no
assertion output). Point it at the new name and guard the substitution
with `|| echo /missing` + head -n1 so a future rename fails in seconds
instead. Footgun filed as #183.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPHNnT2DsWHLhbbhsq2Wc7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants