Stop proxying incus one verb at a time: a rule for what claudebox owns, a table to add it, and a door out #11
Labels
No labels
blocked
blocker:ci-red
blocker:conflict
blocker:drill-pending
blocker:unrequested
bug
claimed
documentation
enhancement
epic
merge-next
needs-triage
ready
release
scope:cli
scope:drill
scope:host
scope:installer
scope:templates
scope:tiers
stale
state:addressing
state:bots-reviewing
state:building
state:needs-human
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: heavy-duty/box#11
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
Feature requests are arriving as "wrap this incus verb" —
renamethis week,incus infobefore it — and each one lands as a new hand-written function, a newcasearm, a new help entry, and a new synopsis string. That's a treadmill, andit grows a CLI that is mostly a worse
incus.Two things are actually going wrong, and they want different fixes.
1. There is no rule for what belongs in claudebox. So every request is
argued from scratch, and the honest answer ("that's just incus") feels like a
brush-off even when it's correct.
2. Adding a thin command costs four edits in three places. The dispatch
case, the help text, the synopsis, the README — hand-maintained, and theydrift. That drift is not hypothetical: it is the root cause of #8 (the help
advertised
status <box>, which the code ignored, and a--forcethat didnothing). Any fix that leaves the surface hand-maintained will drift again.
The rule
Proposed, to live in
docs/claudebox-design.md:This is a real filter, not a platitude:
rename— ours. Not because it adds logic toincus rename, but becauseresolving a box name is the logic: check the tag, apply the
--remoteprefix, and notice the box is running (incus refuses to rename a running
instance) so we can say "stop it first" instead of leaking an incus error.
info— ours, and mostly already built:list <box>in #9 shows state,type, IP and snapshot labels. Raw
incus infodumps instance internals nobodyasked for. (See the naming fix below.)
incus config set security.nesting=false— not ours. It breaks the trustboundary; wrapping it would imply we bless it.
The mechanism: one table, not N functions
Make the thin commands data, and generate dispatch and help from the same
table — so the help can never again describe a command that doesn't exist:
One resolver (tag check →
--remoteprefix → precondition), one dispatch loop,help rendered from the table. Adding a verb becomes a one-line data change, and
#8's whole bug class — a help text that disagrees with the code — stops being
possible by construction.
The escape hatch: so we can say no
Documents what is already true — boxes are plain incus instances tagged
user.claudebox=1— and gives the long tail a door, so "can you proxy X" gets aone-line answer instead of a PR. It should warn, not block, when the
passthrough touches something that can break isolation (
profile assign, addinga nic,
security.*): you're allowed to leave the guardrails, you just get toldyou did.
Naming:
listlists,infoshows one#9 currently overloads
list <box>as the detail view. That's the wrong shape —and it's what sent people to
incus infoin the first place. Splitting it:claudebox list— all your boxes. No positional argument.claudebox info <box>— one box: state, type, IP, snapshot labels,--fromline.claudebox list <box>— an error that points atinfo, not a silent surprise.Folding this into #9 before it merges rather than aliasing over it after.
Scope
docs/claudebox-design.md.list/infosplit (folded into #9).help by hand — the table replaces that hand-maintenance).
rename, via the table (stop-first precondition).claudebox incus <box> -- …escape hatch, with the isolation warning.user.claudebox=1; here is the door.