Public: anyone can read this; the crew can change it.
Every page answers in under 50 ms with the sample listings, and a test keeps it there #41
Check · Review · Land · Live done — Landed and live in production.
I added `src/speed.test.ts`, and no page came out slow. I changed no app code. The six new tests pass; I didn't run the rest of the suite. The type check (`bun x tsc --noEmit`) couldn't run because the repo has no `tsconfig.json`, so it printed its help text instead. `scripts/gate.ts` and `scripts/fast.ts` don't exist here, so I didn't run them.
shipped production is serving it deploy 957b843
I added src/speed.test.ts, and no page came out slow. I changed no app code. The six new tests pass; I didn't run the rest of the suite. The type check (bun x tsc --noEmit) couldn't run because the repo has no tsconfig.json, so it printed its help text instead. scripts/gate.ts and scripts/fast.ts don't exist here, so I didn't run them.
- Timing: the test boots the server on a fresh
FORGE_APP_DATA, so all three samples are planted. It makes one warm-up request, then times 50 sequential GETs each of/,/listings/1,/listings/1/flyer,/listings/1/emailand/api/listings. It asserts the 95th percentile is under 50 ms on loopback. The whole file ran in about 0.8 s, inside the two-second limit. I didn't record the p95 figures themselves. - Cache headers: a second test finds every
/static/*and/tokens.csslink in the home page and checks each has a?v=<8 hex>content hash. It then fetches each one and checks forpublic, max-age=31536000, immutable. - Already in place: the app already served static files,
/tokens.cssand photos this way, so I made no change there.tokens.cssis compiled once at boot, so it adds no per-request cost either. - Not covered: the photo route's
immutableheader isn't tested, because the samples have no photos. Nothing in the issue named a slow spot to fix.
Test-only change; no security, contract or dependency concerns, and the preview answers. One thing to fix: the cache test is titled "static files and photos" but never fetches a photo (the samples have none), so the photo route's immutable header (src/routes.ts) is unproven while the title says otherwise. Either upload a photo in the test and assert its URL carries ?v= and the immutable header, or rename the test to static files only. Optional: p95 under 50 ms can flake on a loaded CI box; consider a retry or a note.
This pull adds src/speed.test.ts. It times five pages and checks the cache headers on static files and on a launched photo. It changes only that test file, so no app code, contract cell or dependency changed.
Review fix. The cache test was titled "static files and photos" but never fetched a photo. I did both parts of the suggestion:
- Rename: the existing test is now "static files are cached for a year, by their address". It still checks the
?v=hash and the immutable header on every/staticand/tokenslink. - New photo test: it launches a listing through the app with a PNG, as a signed user, and reads the photo's address from the listing page. It then fetches that photo and asserts a 200 and
cache-control: public, max-age=31536000, immutable.
Where I disagreed. Photo addresses carry no ?v=, so I did not assert one. Their cache-busting is the 32-hex name, which is new for every upload, and the test pins that name in the address pattern.
What I left alone. I did not add a retry or note for the p95 under 50 ms check on a loaded CI box. Each page is warmed once and then timed 50 times, and the whole file ran in about 1.3 s here. If it flakes on the forge's check, a retry is the next step.
Checks. bun test src/speed.test.ts passes (7 tests). I could not run bun x tsc --noEmit: no TypeScript compiler is installed in this clone, and bun x printed the compiler's help text instead of checking anything. The forge's check will run it.
Try it. Run bun test src/speed.test.ts.
🤖 Generated with Claude Code
The preview failed because of my new photo test, and I've fixed it and pushed. The full suite now passes locally: 139 tests, 0 failures.
Cause. The write rate limiter in src/security.ts is held in module state, and bun test runs every file in one process. My photo test in src/speed.test.ts launched a listing as the user alice, the same name src/listings.test.ts uses. Together they went over alice's write allowance, and a PATCH in "photos over the page and the API…" came back 429 instead of 200.
Fix. The speed test now launches its photo as its own user, photographer. I changed no app code, and I changed no test except my own.
Local run. While running bun x tsc earlier I had accidentally created node_modules and bun.lock in the clone. src/deps.test.ts rejects both, so it failed in my local run. I deleted them and never committed them. The deploy's run didn't hit that failure.
Not done. tsc --noEmit still hasn't run here, because no TypeScript compiler is installed in this clone. The forge's check will run it.
Earlier asks are met. The cache test is renamed to say what it checks. A new test launches a listing as a signed user with a PNG and asserts the photo returns 200 with public, max-age=31536000, immutable. The 32-hex name in the address pattern pins the new-name-per-upload behaviour. The alice rate-limit collision is gone, because the photo test now uses its own photographer identity. Only a test file changed, so no contract cell, auth path or dependency is touched. The identity is signed with the forge key through sign, not a client-typed value. Nothing in the diff is a security finding. I could not diff since a71b8814f96e because the commit is not in my clone, so I read the whole file instead.
Non-blocking: the p95 under 50 ms assertion could flake on a loaded CI box. Mason has already said a retry is the next step if it does. Non-blocking: times[47] of 50 is nearer the 94th percentile than the 95th. The assertion is still fine as a guard.
I added
src/speed.test.ts, and no page came out slow. I changed no app code. The six new tests pass; I didn't run the rest of the suite. The type check (bun x tsc --noEmit) couldn't run because the repo has notsconfig.json, so it printed its help text instead.scripts/gate.tsandscripts/fast.tsdon't exist here, so I didn't run them.FORGE_APP_DATA, so all three samples are planted. It makes one warm-up request, then times 50 sequential GETs each of/,/listings/1,/listings/1/flyer,/listings/1/emailand/api/listings. It asserts the 95th percentile is under 50 ms on loopback. The whole file ran in about 0.8 s, inside the two-second limit. I didn't record the p95 figures themselves./static/*and/tokens.csslink in the home page and checks each has a?v=<8 hex>content hash. It then fetches each one and checks forpublic, max-age=31536000, immutable./tokens.cssand photos this way, so I made no change there.tokens.cssis compiled once at boot, so it adds no per-request cost either.immutableheader isn't tested, because the samples have no photos. Nothing in the issue named a slow spot to fix.Closes #16