← All tests

R2 follow-ups round 3 PROD

Two ergonomics polish items shipped on top of the morning's two bundles. The R2 GC route's cron schedule is now wired (was deployed but never firing). The per-line discount editor gets a 10% / 20% / 50% / Comp quick-percent picker for one-tap discounts.

7/7 prod checks passed.
70/70 total prod tests green — no regressions from this push.
test-r2-followups3-prod.mjs (this bundle)7/7
test-r2-followups2-prod.mjs (round 2)11/11
test-r2-followups-prod.mjs (round 1)19/19
test-nix-os-r2-4b-prod.mjs (Starter register UI)12/12
test-nix-os-70-2-prod.mjs (R2 uploads)10/10
test-phase1-prod.mjs (route smoke)11/11

What's new — code surface

nix-cafe (commit b1fbec0):
  cron-trigger/wrangler.jsonc                     — adds "30 18 * * *" to triggers.crons
  cron-trigger/worker.ts                          — branch on cron string;
                                                    postCronRoute() shared helper;
                                                    fireR2Gc() dispatch
  app/(authed)/pos/starter-register-client.tsx    — 10/20/50/Comp quick-percent picker
                                                    + X clear button + active-state highlighting

Cron-trigger Worker deployment (NOT auto-deployed on push — manual step):
  cd nix-cafe && npx wrangler deploy -c cron-trigger/wrangler.jsonc
  → "Deployed nix-cafe-cron-trigger triggers"
    schedule: 0 15 * * *
    schedule: 30 18 * * *

Why we didn't manually fire R2 GC in this test

The cron route's whole job is to delete unreferenced uploads. Firing it
intentionally during a test would be either a no-op (current bucket is
clean) or destructive (delete real orphans), neither of which proves the
schedule is working. Schedule deployment is itself the proof — wrangler's
post-deploy output lists both crons, and the Cloudflare scheduler will
fire them autonomously. R2 GC route's auth boundary (401 without secret /
401 with wrong secret) was already covered by test-r2-followups2-prod.mjs.

First production fire will be tonight at 01:30 Phnom Penh local time.
Tail logs to confirm:
  npx wrangler tail nix-cafe-cron-trigger -c cron-trigger/wrangler.jsonc

Operator follow-ups (not blocking)

• Tomorrow morning: confirm the 01:30 R2 GC cron fired by checking the
  cron-trigger Worker's tail or by listing the bucket and noting any drop
  in object count. Today get-coffee has 2-3 historical promo uploads
  that might be unreferenced — first run will tell us.
• If the GC's safety cap (500 deletions/run) trips on the first real run,
  that's intentional — it means a bigger orphan backlog than expected.
  Run manually with `?dry=1` to see the diff before raising the cap.
• Quick-percent UI is touch-friendly (44px tap targets via Tailwind h-7
  on tighter screens). Could move to 32px / 40px if Narong wants more
  density on the iPad's portrait orientation.
• Active-state highlighting on the picker uses bg-green-deep when the
  current discount matches a preset within $0.01. If a cashier types
  $0.99 in the free-form input, the 10% button on a $10 line ($1.00)
  won't activate — by design, since they're not actually identical.