docs: README points the tenant table at the registry; the drill-record doctrine and the changelog fragment (#110)

The security-trade paragraph lands verbatim in the README (its twin is in
rig-templates' README, per the issue's docs task), with the 2026-07-24
ruling recorded in place.
This commit is contained in:
claude-bot-andresmgsl 2026-07-24 23:14:40 +00:00
parent e7f31046d9
commit af81f8f4cf
4 changed files with 53 additions and 15 deletions

View file

@ -398,7 +398,7 @@ unattended VM-host appliance) — and `workstation` is the machine at the keyboa
end of all the SSH connections: `root-door=closed`, `join=login`, entering the end of all the SSH connections: `root-door=closed`, `join=login`, entering the
tailnet as *your* device rather than the fleet's. tailnet as *your* device rather than the fleet's.
### `rig bootstrap <claude-box|codex-box|grok-box|kimi-box|staging-box>` — the box tenants ### `rig bootstrap <role>-box` — the box tenants
Run as root, **inside** a [box](https://github.com/heavy-duty/box)-minted Run as root, **inside** a [box](https://github.com/heavy-duty/box)-minted
guest. Convergent — safe to re-run; a second run changes nothing. guest. Convergent — safe to re-run; a second run changes nothing.
@ -419,16 +419,41 @@ same harness as everything else — and re-runnable on an *existing* box to
converge it to a new spec instead of re-minting it. One convergence engine; converge it to a new spec instead of re-minting it. One convergence engine;
the guests were the hole. the guests were the hole.
It is **one mechanism, parameterized per tenant** (`lib/tenant-config.sh` It is **one mechanism, parameterized per DEFINITION** (#110), not four
holds the whole per-tenant table), not four hand-maintained scripts: hand-maintained scripts. The agent-tenant definitions live in the
**[heavy-duty/rig-templates](https://github.com/heavy-duty/rig-templates)
registry** — one directory per role (`template.env`, the allowlisted data
table rig parses and never sources; `install.sh`, the CLI install; `creds.md`,
the per-vendor context paragraph) — so adding an agent tenant is a data PR
there, never a mechanism edit here (#109 was the evidence: adding kimi, pure
data, meant editing six files in this repo). Which `-box` roles exist is the
registry's fact; `rig bootstrap <anything>-box` dispatches on the family
suffix and refuses an unknown role by listing what the resolved registry
actually contains. `staging-box` is the one in-tree tenant — mechanism-adjacent
(sshd hardening through the shared `lib/sshd.sh`, docker, no agent), user
`ops`, box#69's server posture with `root-door=open` acceptance.
| tenant role | user | what lands | **Where the registry comes from — three knobs, precedence high to low:**
|---------------|----------|------------|
| `claude-box` | `claude` | the agent toolbelt (git, gh, tmux, ripgrep, jq, age, unzip, build-essential), docker, node 22, the Claude Code CLI on the system PATH, zsh + oh-my-zsh, and `~/.claude/CLAUDE.md` | | knob | meaning |
| `codex-box` | `codex` | the toolbelt, docker, node 22, `@openai/codex` on the system PATH, and `~/.codex/AGENTS.md` | |------|---------|
| `grok-box` | `grok` | the toolbelt, docker, the grok CLI on the system PATH, and `~/.grok/AGENTS.md` | | `RIG_TEMPLATES_DIR` | a local folder — no fetch: the offline-test path, and "try a template before it exists anywhere" |
| `kimi-box` | `kimi` | the toolbelt, docker, the kimi CLI (uv-managed) on the system PATH, and `~/.kimi/AGENTS.md` | | `RIG_TEMPLATES_REF` | any ref of `RIG_TEMPLATES_REPO` (default `heavy-duty/rig-templates`), fetched as an unauthenticated tarball at bootstrap time |
| `staging-box` | `ops` | box#69's server posture: docker + the same sshd hardening the machine roles get (shared `lib/sshd.sh`, `root-door=open` acceptance) | | *(neither set)* | **the in-tree pin**`RIG_TEMPLATES_PIN` in `commands/lib/templates.sh`, the `BOX_RELEASE` discipline: bumped by ordinary reviewed rig PR, so a rig release freezes the mechanism+registry pair, and a newer rig matches newer templates by default (the #110 ruling) |
**The security trade — in bold, not a footnote.** **A main-tracked
rig-templates repo means every merged PR there executes as root inside every
future mint.** This is acceptable — and an improvement — only because of
three facts together: (1) it *narrows* today's surface, where all of rig is
main-tracked-as-root; (2) the repo is small, single-purpose, and
ceremony-governed with a **human merge** as the gate and the review panel
ahead of it; (3) drills pin the SHA they proved. If any of those three
weakens, the default flips to a pinned `RIG_TEMPLATES_REF`. install.sh diffs
in that repo are the highest-trust review surface in the org — the reviewer
doctrine should say so. *(2026-07-24: the flip this paragraph reserves was
taken, before the migration and by the decider — the default IS the pin
above, so a merged template reaches mints only through a reviewed pin bump
here, or an explicit per-mint `RIG_TEMPLATES_REF`.)*
**The role carries the suffix; the user does not.** A tenant user is the **The role carries the suffix; the user does not.** A tenant user is the
account the box *seed* created (`BOX_USER`) and the agent CLI's own dotdir account the box *seed* created (`BOX_USER`) and the agent CLI's own dotdir
@ -462,8 +487,9 @@ disposability facts, and the guard note — **never run `box setup-host`,
`box teardown-host`, or the drill inside a box; the box you are in is not a `box teardown-host`, or the drill inside a box; the box you are in is not a
host you own**. A nested box stack claims the guest's own uplink subnet and host you own**. A nested box stack claims the guest's own uplink subnet and
silently breaks its networking (box#80). The note lives in silently breaks its networking (box#80). The note lives in
`lib/tenant-config.sh` exactly once, not copy-pasted per template — that was `lib/templates.sh`'s renderer exactly once — mechanism, not template data —
the point of moving it here. never copy-pasted per definition; that was the point of moving it here. Only
the creds paragraph is the definition's (`creds.md`).
**Tenants and the role marker.** A tenant run writes `role=<tenant> tenant=yes **Tenants and the role marker.** A tenant run writes `role=<tenant> tenant=yes
host=no` — no `root-door=`, because a guest has no root-door policy of its own host=no` — no `root-door=`, because a guest has no root-door policy of its own

8
changelog.d/110.md Normal file
View file

@ -0,0 +1,8 @@
### Changed
- Agent-tenant definitions live in heavy-duty/rig-templates, pinned in-tree and overridable per mint (`RIG_TEMPLATES_DIR`/`_REF`/`_REPO`); the in-tree case arms are gone, `staging-box` stays (#110)
### Added
- `rig template-lint` validates role definitions; rig-templates CI runs it on every PR (#110)
- Drill records cite the rig-templates SHA the converge read (#110)

View file

@ -3,8 +3,8 @@
# from, parse a definition's template.env against an allowlist, and lint a # from, parse a definition's template.env against an allowlist, and lint a
# whole definition. Sourced by bootstrap-tenant.sh (the mint-time consumer) # whole definition. Sourced by bootstrap-tenant.sh (the mint-time consumer)
# and template-lint.sh (the registry repo's CI gate) — pure functions plus # and template-lint.sh (the registry repo's CI gate) — pure functions plus
# one pin, no side effects at source time (repo precedent: tenant-config, # one pin, no side effects at source time (repo precedent: runner-config,
# runner-config). # and the tenant-config table this lib replaces).
# #
# The registry moved out of rig's tree so mechanism and data can move at # The registry moved out of rig's tree so mechanism and data can move at
# different cadences (#109 is the evidence: adding kimi — pure data — meant # different cadences (#109 is the evidence: adding kimi — pure data — meant

View file

@ -63,7 +63,11 @@ schedule, in separate sittings. What makes that safe is that every drill
**pins the same fixed set of candidate refs**: rig's drill runs `--host yes` **pins the same fixed set of candidate refs**: rig's drill runs `--host yes`
with `BOX_REF=release/<box-version>`, so it exercises the box that will with `BOX_REF=release/<box-version>`, so it exercises the box that will
actually ship; box's drill mints with `RIG_REF=release/<rig-version>`, so it actually ship; box's drill mints with `RIG_REF=release/<rig-version>`, so it
exercises the rig that will actually ship. Both measure the same pair. exercises the rig that will actually ship. Both measure the same pair. The
record also cites the **rig-templates SHA** the converge read (#110) — the
candidate tree's `RIG_TEMPLATES_PIN` unless the drill was pointed elsewhere
via `RIG_TEMPLATES_REF` — so the mechanism+registry pair a release freezes
is the pair the drill proved.
That — not sequencing — is what dissolves the box↔rig recursion. The refs are That — not sequencing — is what dissolves the box↔rig recursion. The refs are
static identifiers that exist as soon as the release branches do, long before static identifiers that exist as soon as the release branches do, long before