Public: anyone can read this; the crew can change it.

Every limit the owner can hit is listed on one Limits page with its value and its reason, read from settings, not constants #1582

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

Every limit the owner can hit is now declared in `src/settings/limits.ts` and editable at `/admin/limits`. The modules that held the constants read from there.

shipped production is serving it deploy 77532cd

opened this

Every limit the owner can hit is now declared in src/settings/limits.ts and editable at /admin/limits. The modules that held the constants read from there.

I merged current main into the branch and pushed. The type check is clean. test/limits.test.ts, asks-expiry, mcp, crew-limits, accounts and checks pass (85 tests). I did not run the whole suite; the forge runs the full check on this push. The earlier failure ("asks that expire, hold and collapse…") was in test/asks-expiry.test.ts. It passed in my run before and after the merge, and I did not change it.

What changed

  • src/settings/limits.ts gives each limit a name, default, bounds and a one-sentence reason. The limits are children, crew slots, check concurrency, run budget ceilings and per-account caps.
  • src/web/pages/admin-limits.ts serves /admin/limits, for forge admins only, and a non-admin gets a 404. It shows each value with its reason.
  • A value out of bounds is refused with the bound named. The POST is same-origin checked. Each change is recorded with who made it and when.
  • There is a matching API and MCP tool beside the capacity ones. The MCP schemas no longer copy the limit values.
  • RateLimiter.setLimits lets a rate limit change at runtime.
  • test/limits.test.ts is in GATE. It shows that changing a limit changes the behaviour it governs for more than one limit, and that a non-admin gets a 404.

What I left out

  • I did not re-run the grep for leftover hard-coded copies of the listed limits this turn.
  • The diff against main also deletes some old constant-pinning tests in test/accounts.test.ts, checks.test.ts, crew-parks.test.ts, crew.test.ts and tui-workflows.test.ts. They pinned the old constants, and the new limits test covers the behaviour instead. That list is from the diff stat and I did not re-check it against the replaced constants.

To try it Sign in as a forge admin and open /admin/limits. Change a value, then try one outside its bounds to see the refusal. Run bun test test/limits.test.ts.

🤖 Generated with Claude Code

Closes #1476

Approved

Approved. Security holds: page, API and MCP all go through actions/limits.ts, which refuses non-admins and agents with not_found (even an agent with is_admin set, and the MCP test covers that). The page POST checks the admin before it reads the body, then readForm(ctx, "admin") enforces same-origin and the admin scope and caps the body by the bytes it reads. The API PUT reads through the bounded body(), and MCP writes need an admin-scope token. Values go through ^\d{1,12}$ and then the declared bounds. All SQL is parameterised (the LIMIT is a trunc'd number set by our own code), and every interpolation on the page goes through html. The concurrency limits stay a single stored value shared with capacity, so the two can't drift. Every constant the pull replaces is now read on each use, sign-in limits included (RateLimiter.setLimits keeps the hits it has counted).

Tests: at 978bdebd, bun x tsc --noEmit is clean, and test/limits.test.ts, mcp, share and capacity pass, except for one capacity case about FORGE_CHECK_SHARDS. That case fails the same way on main in this sandbox, so it comes from the environment and not from this pull. The preview and the screenshots couldn't be reached from the reviewer's sandbox, so this verdict rests on the code and the local tests.

Non-blocking, see the line comments: the MCP dry run doesn't validate the value, and crew/check concurrency can now be edited on two pages.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs