Skip to content

Round 14: admin throttling, real Gemini cascade walk, CSP report-only, FK indexes#81

Merged
bejranonda merged 9 commits into
mainfrom
claude/webapp-review-improve-dlhdzr
Jun 10, 2026
Merged

Round 14: admin throttling, real Gemini cascade walk, CSP report-only, FK indexes#81
bejranonda merged 9 commits into
mainfrom
claude/webapp-review-improve-dlhdzr

Conversation

@bejranonda

Copy link
Copy Markdown
Owner

Round 14 — backlog burn-down (security, resilience, schema, a11y)

Continues Round 13 (PR #80). Six changes, each its own commit:

  1. Admin mutation routes rate-limited (30/min per IP) — KNOWN_ISSUES 0b follow-up. A stolen admin cookie no longer allows unthrottled scripting of promo creation / tier / role mutations. Route-wiring test suite now pins all ten throttled routes.
  2. Chat Gemini cascade actually walks the list. The module header always documented the walk; callGemini only ever called GEMINI_VISION_MODELS[0] — the exact single-hardcoded-id outage mode the cascade exists to prevent. Now skips on 404/429 (per-model conditions), fails fast on 5xx, splits the timeout budget per model, and reports the answering model in modelUsed. The old test pin asserted the [0] shortcut verbatim; replaced with cascade-walk pins + 4 behavioural tests.
  3. CSP ships in Report-Only mode. Origin allowlist (self + Cloudflare Insights beacon; data:/blob: images; frame-ancestors 'none'). 'unsafe-inline' stays for script/style until the nonce work lands. Report-only never blocks; violations surface as console errors — which the Playwright suites assert against, so the preview e2e run below doubles as the violation scan.
  4. Duplicate root middleware.ts removedsrc/middleware.ts (which imports the shared locale config) is the survivor. Production build verified, middleware still compiles (42.1 kB).
  5. Migration 0004: FK indexes on sessions/code_redemptions/food_scans/chat_messages.user_id (KNOWN_ISSUES follow-up feat: Add comprehensive product strategy research documentation #4), with matching Drizzle index() definitions. ⚠️ Merger action required (ITERATION_PROCESS §7): this session has no Cloudflare credentials, so after merge someone must run cd frontend && npx wrangler d1 migrations apply eatinorder-db --remote. Safe to delay — IF NOT EXISTS, additive, app behavior unchanged until applied.
  6. Demo step-navigator a11y — emoji-only buttons get the localized step title as aria-label + aria-pressed.

Validation

  • npm run check:all: 193/193 unit (+8), i18n parity, type-check — green
  • next build + pages:build (exact CF command) — green locally
  • Full Playwright suite to be run against the branch preview before merge (CSP violation scan + locale-routing check after the middleware cleanup), then against production after.

Merge with Merge, not Squash (ITERATION_PROCESS §4).

https://claude.ai/code/session_01RaziyjCxHgKcqvTqss7bXS


Generated by Claude Code

claude added 8 commits June 10, 2026 05:55
A Linux-only npm install pruned the optional @next/swc-win32-x64-msvc
entry from the root lockfile and the version-bump commit carried that
removal; a later local build re-added it. Keep the platform-complete
lockfile so Windows contributors get identical installs.

https://claude.ai/code/session_01RaziyjCxHgKcqvTqss7bXS
… IP)

KNOWN_ISSUES 0b follow-up: admin routes are session+is_admin gated,
but a stolen admin cookie allowed unthrottled scripting of promo
creation and tier/role mutations. Route-wiring test suite extended to
pin all ten throttled routes.

https://claude.ai/code/session_01RaziyjCxHgKcqvTqss7bXS
The module header always documented that the chat path walks
GEMINI_VISION_MODELS with the scan path's skip semantics, but
callGemini only ever called the first id — reintroducing the
single-hardcoded-id outage mode the cascade exists to prevent (the
May-2026 zero-quota incident class). The walk skips on 404 (model
retired) and 429 (per-model quota gone), throws immediately on
anything else, splits the time budget per model, and reports the
model that actually answered in modelUsed (it previously always
claimed [0]).

The old source pin in analyze-fallback.test.ts asserted the [0]
shortcut verbatim — replaced with pins on the for-of walk + skip
branch; 4 new behavioural tests cover 429-skip, 404-skip, 5xx
fail-fast, and all-skipped → CF safety net.

https://claude.ai/code/session_01RaziyjCxHgKcqvTqss7bXS
Screen readers announced raw emoji names ('broccoli') with no step
context. Each button now carries the localized step title as
aria-label plus aria-pressed state.

https://claude.ai/code/session_01RaziyjCxHgKcqvTqss7bXS
The long-deferred CSP follow-up, staged safely: the policy's value at
this stage is the ORIGIN allowlist (only self + the Cloudflare
Insights beacon may load scripts or connect; img allows data:/blob:
for scan thumbnails; frame-ancestors none mirrors X-Frame-Options).
script/style keep 'unsafe-inline' until a nonce strategy lands —
Next.js emits inline RSC bootstrap scripts and critical CSS.

Report-only never blocks; violations surface as console errors, which
the Playwright suites already assert against — the e2e run against
the branch preview doubles as the violation scan. Flip to enforcing
by dropping '-Report-Only' after a quiet window.

https://claude.ai/code/session_01RaziyjCxHgKcqvTqss7bXS
frontend/ carried two middleware files: src/middleware.ts (imports
locales from lib/i18n-config — the single source of truth) and a root
middleware.ts duplicating the same config with a hardcoded locale
list. Next.js only honours one; the redundant copy invited drift (add
a locale to i18n-config, wonder why routing ignores it). Production
build verified — middleware still compiles at 42.1 kB.

https://claude.ai/code/session_01RaziyjCxHgKcqvTqss7bXS
KNOWN_ISSUES 'Ongoing Follow-ups #4': sessions, code_redemptions,
food_scans and chat_messages all reference users.id with no secondary
index, so every 'rows for user X' query full-scans. Four CREATE INDEX
IF NOT EXISTS statements — additive, idempotent, no data movement —
plus matching index() definitions in the Drizzle schema so a future
drizzle-kit generate doesn't diff-fight the database.

NOTE for the merger (ITERATION_PROCESS §7): this environment has no
Cloudflare credentials, so the migration is NOT yet applied to remote
D1. Run after merge:
  cd frontend && npx wrangler d1 migrations apply eatinorder-db --remote
The app is fully functional before the apply — indexes only change
query plans.

https://claude.ai/code/session_01RaziyjCxHgKcqvTqss7bXS
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@bejranonda, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 47 minutes and 35 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d90f1e8c-55da-42fc-98df-bfed0adeae9e

📥 Commits

Reviewing files that changed from the base of the PR and between 85dc782 and 45d622f.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (16)
  • CHANGELOG.md
  • docs/KNOWN_ISSUES.md
  • frontend/drizzle/0004_fk_user_id_indexes.sql
  • frontend/drizzle/meta/_journal.json
  • frontend/middleware.ts
  • frontend/next.config.js
  • frontend/src/app/[locale]/demo/page.tsx
  • frontend/src/app/api/admin/promo/create/route.ts
  • frontend/src/app/api/admin/promo/toggle-active/route.ts
  • frontend/src/app/api/admin/users/toggle-admin/route.ts
  • frontend/src/app/api/admin/users/update-tier/route.ts
  • frontend/src/db/schema.ts
  • frontend/src/lib/ai-providers.ts
  • frontend/tests/ai-providers.test.ts
  • frontend/tests/analyze-fallback.test.ts
  • frontend/tests/rate-limit.test.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/webapp-review-improve-dlhdzr

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 10, 2026

Copy link
Copy Markdown

Deploying eatinorder with  Cloudflare Pages  Cloudflare Pages

Latest commit: 45d622f
Status:⚡️  Build in progress...

View logs

@bejranonda bejranonda merged commit c21d119 into main Jun 10, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants