Back to Blogindustry2026-05-2413 min read
Dashboard "AI rate limit reached" — staff was using it for side work, quota gap (PR #621 FFF F2)
Bryn (48) runs Y Gegin 55-cover modern Welsh restaurant Cardiff Cathays Park Wood Street with cousin-nephew Iestyn + head chef Megan. 17 years trade, 14 months thMenu Pro+. AI menu translation 8 languages (EN, FR, DE, ES, IT, JA, AR, ZH). Friday morning dashboard: **"AI rate limit reached. You ve used 100/100 daily AI inferences."** Bryn added 4 menu items since Tuesday but 100 inferences burned. Audit log: staff_id "megan" 92 inferences /api/ai-translate-menu last 24h. Megan confessed: side-gig translating Cardiff tourism PDFs from Welsh to English via thMenu s AI for 5 months. Restaurant s 100/day quota burned by single staff. **Forensic**: thMenu admin AI endpoints (11 total: ai-bio, ai-description, ai-pricing-suggestions, ai-daily-specials, ai-recipe-suggest, ai-translate-menu, ai-forecast, ai-menu-cleanup, ai-review-reply, ai-menu-generator, ai-shift-schedule) none called checkAiDailyQuota (PR #509 Z F1 customer-facing 4 endpoints). PR #624 GGG-prelim consolidated 2 (ai-menu-generator + ai-shift-schedule) to shared helper, 9 remaining endpoints quota-helperless. Threat model: (1) cost burn 1000+ inf/day/tenant Cloudflare AI billing $55/day max-burn; 100 tenants = $5,500/day Synaltix cost; (2) compromised CSRF token attacker 30,000 inf/day; (3) rogue/personal staff (Megan case); (4) restaurant locked out of legitimate AI work quota exhausted by non-legit use. **PR #621 batch FFF F2** 4-layer fix: **Layer 1 admin AI quota helper** apps/web-admin/src/lib/ai-quota.ts mirror of web-menu helper. Atomic UPSERT counter pattern (PR #575 VV F1) `INSERT ... ON CONFLICT DO UPDATE SET used = used + 1 WHERE used < ? RETURNING used` single statement. Admin cap 100/day per restaurant (customer-side separate 100/day bucket). **Layer 2 route 9 admin endpoints**: ai-bio/ai-description/ai-pricing-suggestions/ai-daily-specials/ai-recipe-suggest/ai-translate-menu (per-language break)/ai-forecast (soft-fail)/ai-menu-cleanup (soft-fail)/ai-review-reply. Per-endpoint break vs soft-fail decision by endpoint semantic. **Layer 3 aiQuotaExceededResponse() builder**: standardize response shape {error: "ai_quota_exceeded", message, remaining, reset_at}. UI modal countdown timer + "Try again later" CTA. **Layer 4 telemetry beacon** [BEACON:ai_quota_high_burn] 80+/day threshold Synaltix internal alert manual review compromised account / rogue staff indicator. Platform-wide audit 60 days 7 high-burn restaurants: 3 legitimate heavy use (multi-language menu, frequent specials), 2 staff personal use (Bryn case), 1 compromised CSRF token (staff password phished, 2FA enforced), 1 bot abuse (CSRF cookie stolen). 2FA mandatory + admin rate-limit tightening parallel shipped. Pattern: **per-tenant daily quota caps enforced on customer-facing AI inference endpoints must be enforced EXPLICITLY on admin-side sibling endpoints too. The "operator manages own cost" assumption breaks under compromised CSRF token / rogue staff / personal side-business usage vectors. A telemetry beacon must flag high-burn restaurants for manual review.** Implementation checklist: (1) identify customer + admin AI endpoints cap both; (2) atomic UPSERT counter pattern; (3) shared helper cross-app access; (4) break vs soft-fail per-endpoint decision by semantic; (5) standardized response shape; (6) UI countdown timer; (7) telemetry beacon high-burn manual review; (8) 2FA mandatory + admin rate-limit tightening parallel; (9) quarterly burn-rate audit. Ferhat Antakya Saraykent "Hatay Mutfağı" 19-year modern Levantine + chef Pınar Arabic-Turkish translation side-work version with same flow.