A least-privilege obstacle course: the player crosses a scrolling corridor of walls, each with a few gaps — “gates” labeled by tool type (read / write / network / shell) and a declared cost. Line up with an opening to pass through it and the declared cost is spent from a shrinking capability budget. A few gates are disguised: the cost revealed only after crossing is higher than what was declared. The goal isn’t speed — it’s reaching the end having spent the least privilege, without a disguised gate blowing the budget.
Riffs on agent sandboxing and least-privilege tool design: an agent picking which capability to invoke next, unable to fully trust what a tool claims it’ll cost until it’s already committed.
Reuse
The mechanic lives in src/capability-run.js as a framework-free ES module:
createCapabilityRun(level, opts)— returns a state object; callupdate(dt, input)each frame withinput: { x, y }in -1..1.defaultLevel()— a hand-tuned 6-checkpoint corridor with declared/actual costs baked in; pass your own{ worldHeight, budget, goalX, checkpoints }for a different run.GATE_TYPES— color/label metadata for the four tool types, shared by the demo’s renderer.- State exposes
pos,budgetLeft,startingBudget,resolved(checkpoint index → chosen gate index),log(crossed-gate history with adisguisedflag), andstatus(playing/won/lost). Rendering — walls, gate frames, camera scroll — is the caller’s job; the demo draws it on canvas.
Gotchas
- A checkpoint only blocks movement while unresolved; once a gate is chosen the wall stops mattering, so walking back through a resolved checkpoint is free (no re-charge, no re-pick).
- A gate whose declared cost exceeds the remaining budget is treated as locked — the wall holds even though the opening is visually there. Only a disguised gate’s actual cost can push the budget negative unexpectedly.
- The demo in
demo/bundles its own copy of the module (self-contained by contract). If you touchsrc/, re-copy it intodemo/.