Back to Blogindustry2026-05-2413 min read
Friday night, 3 parties double-booked to the same table — admin reservation cap gap (PR #626 GGG F3)
Tobias (45) runs Schwabinger Stube 75-cover Bavarian dinner spot one block off Münchner Freiheit in Munich Schwabing, 11 years, reservation-driven (~60% weekend revenue). Last Friday 19:30 prized 6-seat Tisch 12 (view of Alte Pinakothek garden) had **3 parties arrive same slot**: Müller family (6), Schneider friends (4), Weber + Söhne agency dinner (8). All said "I have 19:30 Tisch 12 reservation." Tobias panicked, pulled admin 3 entries — all created same afternoon by him, same table + same slot. "Did I really triple-book?" Forensic: customer-side /api/reservations enforces 3 cap layers (PR #539 MM max_party_size_per_reservation + PR #337 + PR #578 VV-C uq_resv_active_slot UNIQUE + per-restaurant daily 50 cap) but admin-side /api/admin/reservations **enforces NO caps**. Intent was "operator double-checks trust"; tired/distracted/fast-clicking operator in real world breaks that trust. Admin handler INSERT raw (no ON CONFLICT DO NOTHING either). Tobias s 3 rows landed in 3 different internal table_id (frontend bug — table picker visually same table emits different IDs); UNIQUE constraint (restaurant_id, table_id, reserved_at) bypassed. Wrong theory 1: "DB UNIQUE constraint exists, why need code-side?" — DB UNIQUE bypassed by different table_id. Right: every customer-side enforced cap must be EXPLICITLY enforced admin-side. Sweep found 4 admin sibling cap-miss: /api/admin/reservations (3-cap), /api/admin/orders (items.length cap PR #570 UU F3), /api/admin/loyalty/adjust (phone canonicalization PR #626 GGG F5), /api/admin/promo/create (max_uses_per_customer PR #544 OO). **PR #626 batch GGG F3** 2-layer fix: **Layer 1 admin reservations cap enforce** 4 layers: (a) party-size cap customer parity, (b) table seat_capacity cross-check admin-only addition, (c) slot conflict UNIQUE + ON CONFLICT, (d) per-day cap. **Layer 2 sweep other 3 admin siblings** same pattern. **Bonus UI** capacity-overflow confirmation prompt soft-cap: "Tisch 12 seats 6, party 8 — Confirm?" hard-cap (party > 50) still rejected. Tobias next Friday smooth: 1st 4-Schneider Tisch 12, 2nd 6-Müller same slot → 409 slot_already_taken Tisch 7 offered, 3rd 8-Weber Tisch 12 → party_size_exceeds_table Tisch 4 (12-cap booth) offered. 90-day platform-wide audit **23 restaurants 47 double-bookings** proactive apology + 3-month Pro tier. Tobias 6-month Pro tier + Hall of Fame "Helped harden admin endpoint parity." Pattern: **every cap enforced on customer-side endpoint (party-size, per-day count, slot UNIQUE, per-customer use, length, format) must be EXPLICITLY enforced on its admin-side sibling. The "operator double-checks" mindset breaks in the real world — operators are tired, distracted, fast-clicking; manual data entry produces errors.** Implementation checklist: (1) customer-side cap layers list/sweep; (2) admin-side EXPLICIT enforce (DB UNIQUE not enough, route handler pre-INSERT); (3) UI soft-cap confirmation prompt operator override explicit consent; (4) hard-cap reject, soft-cap confirmation; (5) quarterly grep audit customer vs admin sibling diff; (6) pentest admin bypass scenario; (7) production backfill cap-violation detection + proactive apology. Necdet Samsun Atakum Karadeniz Sofrası version with same flow.