Skip to content

test(golden): lock rendered behavior in a committed snapshot (#154 Phase 0) - #179

Open
defangdevs wants to merge 1 commit into
masterfrom
refactor/phase0-golden-snapshot
Open

test(golden): lock rendered behavior in a committed snapshot (#154 Phase 0)#179
defangdevs wants to merge 1 commit into
masterfrom
refactor/phase0-golden-snapshot

Conversation

@defangdevs

Copy link
Copy Markdown
Owner

Phase 0 of #154: a golden snapshot of every module-generated artifact, committed as a fixture and enforced by a new golden-snapshot flake check, so Phases 1–3 (de-inlining payloads, purging antiquotes, template units) provably keep the rendered configuration byte-stable.

What is snapshotted

Two configurations are rendered into tests/golden/:

  • vm/nixosConfigurations.vm's modules, as named in the issue.
  • web/ — the same plus tests/golden-web.nix. This is an addition to the issue's plan, called out here deliberately: hosts/vm.nix never enables web/selfUpdate, so a vm-only snapshot would leave the entire Caddy/ttyd/settings-daemon/webhook/self-update surface unlocked — most of what Phases 1–3 touch. The overlay pins two terminal users (one codex, exercising sorted ttyd port assignment, rootUser selection and the codex remote-control path) plus selfUpdate.enable.

Per configuration: systemd unit texts (with wantedBy/requiredBy as comment trailers), published /etc files (sudoers, the generated Caddyfile, fail2ban locals + the module's filter, agent guides), the module's tmpfiles rules, and — followed recursively from those texts — the bytes of every /nix/store payload whose name mentions agent-box/agent-web: supervisor, session CLI, env-exec wrapper, attach scripts, password helpers, settings daemon, webhook CLI/spawner, spot monitor, update script, seeds. 60 files.

How it stays arch- and hash-stable

Store hashes are normalized to a fixed placeholder. The golden systems are evaluated for the check's system (on x86_64 the vm entry is exactly nixosConfigurations.vm's eval), and I verified the aarch64 and x86_64 manifests are byte-identical after normalization, so one committed fixture serves CI and Graviton dev boxes alike. Payload contents are in the fixture directly, so a one-byte script change fails the check even though hashes are normalized away.

Workflow

  • Check: nix build -L .#checks.<system>.golden-snapshot (wired into ci.yml after vm-closure, which already realizes the shared closure).
  • Intentional change (or a flake.lock bump, which renames store paths): nix run .#update-golden, review the tests/golden/ diff, commit it with the change. Documented in AGENTS.md.

Checks run

  • checks.aarch64-linux.golden-snapshot (green, matches fixture)
  • checks.aarch64-linux.{multi-user,module-single-file,download-route,webhook-route,module-generated-up-to-date} (green)
  • nixosConfigurations.vm + packages.x86_64-linux.vm drvPath evals (green)
  • cross-system manifest diff after normalization: identical

No behavior change; the module itself is untouched.

Closes nothing; first checkbox of #154.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NPHNnT2DsWHLhbbhsq2Wc7

, Phase 0)

Snapshot every module-generated artifact — systemd units (text plus
wantedBy/requiredBy trailers), published /etc files (sudoers, Caddyfile,
fail2ban locals, agent guides), tmpfiles rules, and every referenced
agent-box/agent-web store payload, followed recursively — from two golden
configurations: nixosConfigurations.vm's modules, and the same plus a
tests/golden-web.nix overlay (vm never enables web/selfUpdate, so the
Caddy/ttyd/settings/webhook/update surface would otherwise go unlocked).

Store hashes are normalized to a fixed placeholder, so the fixture is
identical whichever system renders it (verified: aarch64 and x86_64
manifests are byte-identical after normalization) and content changes in
generated scripts are caught by their bytes in payloads/, not hidden
behind hash churn.

The golden-snapshot flake check diffs the committed tests/golden/ against
a fresh render; `nix run .#update-golden` regenerates the fixture after
an intentional change so the PR diff IS the behavior review. Phases 1-2
of the portability refactor must keep this check green with a
byte-identical fixture; flake.lock bumps regenerate it mechanically.

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