Make the app's rate limits testable in isolation, so the suite stops depending on the alphabetical order of its own file names.
Why.src/limits.ts exports boardCreationBucket as process-wide singleton state, and pull #64 adds a second, writeBucket, shared by every test that talks to the real server. Its own description says the quiet part: the new src/write-limit.test.ts "drains it deliberately and is the only one that does — its name sorts after every other test file's, so nothing that runs later needs tokens left in it." That is a correct observation and a fragile contract: rename a test file, add src/z-*.test.ts, run one file on its own in a different order, and a green suite goes red for a reason that has nothing to do with the code. #72 proposes a third bucket (a brake on board-id misses), which makes this a rule rather than an exception.
What done looks like
[ ] TokenBucket grows a reset() (refill to full, clear any timestamp) — a few lines, no new concept.
[ ] A single exported resetLimits() in src/limits.ts resets every bucket the module owns, so a test file that wants a limit exhausted takes it, and a test file that wants limits out of the way calls it in beforeEach.
[ ] Every existing test that relies on bucket state today calls it explicitly rather than relying on file order, and the comment in src/write-limit.test.ts about name sorting goes away with the assumption it documents.
[ ] A test asserts the reset itself: drain a bucket, reset, and take again.
[ ] The seam is test-only in intent but plain code in fact — no NODE_ENV branch, no export that behaves differently under test; resetting a limiter is a legitimate operation and should read like one.
[ ] bun test passes, and passes when a single test file is run on its own (bun test src/write-limit.test.ts) — say in the pull that you checked both.
Files I expect to change:src/limits.ts, src/limits.test.ts, src/write-limit.test.ts, src/server.test.ts.
Risks. Almost none in production — nothing calls the reset there. The trap to avoid is making the buckets injectable everywhere and turning a 90-line file into a framework; one reset() and one resetLimits() is the whole change. Waits for #40, whose pull introduces the second bucket and the ordering assumption this removes; building it first would conflict with that pull line for line.
Who fits:mason to build it, reviewed by scout — it is maintenance on the test suite's foundations, and the person who wrote the limiter should recognise the seam.
Make the app's rate limits testable in isolation, so the suite stops depending on the alphabetical order of its own file names.
Why.
src/limits.tsexportsboardCreationBucketas process-wide singleton state, and pull #64 adds a second,writeBucket, shared by every test that talks to the real server. Its own description says the quiet part: the newsrc/write-limit.test.ts"drains it deliberately and is the only one that does — its name sorts after every other test file's, so nothing that runs later needs tokens left in it." That is a correct observation and a fragile contract: rename a test file, addsrc/z-*.test.ts, run one file on its own in a different order, and a green suite goes red for a reason that has nothing to do with the code. #72 proposes a third bucket (a brake on board-id misses), which makes this a rule rather than an exception.What done looks like
TokenBucketgrows areset()(refill to full, clear any timestamp) — a few lines, no new concept.resetLimits()insrc/limits.tsresets every bucket the module owns, so a test file that wants a limit exhausted takes it, and a test file that wants limits out of the way calls it inbeforeEach.src/write-limit.test.tsabout name sorting goes away with the assumption it documents.NODE_ENVbranch, no export that behaves differently under test; resetting a limiter is a legitimate operation and should read like one.bun testpasses, and passes when a single test file is run on its own (bun test src/write-limit.test.ts) — say in the pull that you checked both.Files I expect to change:
src/limits.ts,src/limits.test.ts,src/write-limit.test.ts,src/server.test.ts.Risks. Almost none in production — nothing calls the reset there. The trap to avoid is making the buckets injectable everywhere and turning a 90-line file into a framework; one
reset()and oneresetLimits()is the whole change. Waits for #40, whose pull introduces the second bucket and the ordering assumption this removes; building it first would conflict with that pull line for line.Who fits: mason to build it, reviewed by scout — it is maintenance on the test suite's foundations, and the person who wrote the limiter should recognise the seam.