diff --git a/CHANGELOG.md b/CHANGELOG.md index 38e4d22..65dc1ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,27 @@ which records not just what changed but what each drill run proved. ## Unreleased +### Added + +- **Server-class boxes: the `staging` template** (#68) — Debian 13 VM with + docker + rig (+ tmux, the #65 contract) preinstalled and *nothing* that + joins or admits: tailscale, sshd and every credential are rig's to install + at bootstrap time (`box shell` → `sudo rig bootstrap workload`), inside + the guest — box stays creds-free. Two new optional `box.env` keys carry + the posture: `BOX_REQUIRE_VM=1` (no container fallback, and `--container` + is refused — the VM is the trust boundary and the guest runs docker) and + `BOX_AUTOSTART=1` (`boot.autostart=true`, so the box returns from a host + reboot without an operator; clones inherit it via `incus copy`). Still no + key for a network or a `security.*` flag. The design doc gains the + overlay-join clarification and the snapshot-before-join rule. +- **Template test suite** — `test/cli.sh`'s template coverage is dynamic + over `templates/*/`, so a new template cannot ship unseen: `box.env` is + driven through the real, extracted `load_template` (unknown keys and + missing `BOX_IMAGE`/`BOX_USER` fail), `user-data.yaml` must exist, declare + `#cloud-config`, parse as YAML and install tmux; staging additionally + proves its boot demands, docker + rig, and the creds-free refusal (no + tailscale/authkey/ssh in effective cloud-init lines). + ## 0.6.0 — 2026-07-18 ### Added diff --git a/docs/plans/2026-07-17-staging-template.md b/docs/plans/2026-07-17-staging-template.md index 5fd67fc..b7fbbee 100644 --- a/docs/plans/2026-07-17-staging-template.md +++ b/docs/plans/2026-07-17-staging-template.md @@ -132,3 +132,35 @@ pass before merge: - [ ] Grep assertions: `BOX_REQUIRE_VM`/`BOX_AUTOSTART` appear in the allowlist; `boot.autostart` is stamped only under the `BOX_AUTOSTART` guard; no template other than `staging` sets either key. + +--- + +## Addendum (2026-07-18): rebased onto main; the template test suite + +The branch was rebased onto main, which had since gained the restricted tier +(#74), a CI workflow, and `test/cli.sh`. What that changed here: + +- **`load_template` conflicts** — main replaced the `[ -n … ] && [ -n … ] || + die` required-keys idiom with the spelled-out `if [ -z … ]` form (SC2015) + and grew the SC2034 directive block; the two new key arms were re-applied + onto that version, both intact. +- **`cmd_new`** — main added a tier-aware box-net pre-flight at the top of + the function; the `BOX_REQUIRE_VM` refusal stays in the fresh-mint branch, + after `pick_mode` (it must read the *effective* mode). Its message holds + for both tiers: `/dev/kvm` is a host fact, and admin and restricted mints + go through the same daemon, so the fix is the same — a KVM host, not a + grant. +- **tmux** — `box tmux` is a contract every template honors (#65, asserted + by `test/cli.sh`), so the staging package list carries tmux; the operator + babysits `rig bootstrap workload` through it. +- **The template test suite** (maintainer request): `test/cli.sh`'s template + coverage is now *dynamic* over `templates/*/` — a new template cannot ship + unseen. Per template: `box.env` driven through the real, extracted + `load_template` (unknown keys and missing `BOX_IMAGE`/`BOX_USER` fail); + `user-data.yaml` exists, declares `#cloud-config`, parses as YAML + (python3+pyyaml, loudly skipped where absent), installs tmux. + Staging-specific: both boot demands proven through the parser, docker + + rig present, and a creds-free grep-refusal (no tailscale/authkey/ssh in + effective cloud-init lines). Grep guards pin the `cmd_new` half: the + refusal orders after `pick_mode`; `boot.autostart` is stamped only under + the `T_AUTOSTART` guard.