QR ordering, rebuilt hardened for a second venue
The QR order-and-pay platform redeployed for another venue — and rebuilt to a much stricter security standard, because the database it had to live in was shared with a staff app. No database key in any page, locked tables, server-side prices, passcode lockouts and payment checks, tested against 49 attacks before launch.
Why it couldn’t just be copied
The first deployment runs on its own database, so its public key in the page source exposes nothing else. This venue’s system had to live in a database shared with a staff app whose tables were open to that same public key — staff, takings and timesheets included.
How it’s locked down
- Pages talk only to the site’s own
/api/address, forwarded to two server functions. - The ordering tables have row-level security on, no policies, and public grants revoked — shut to everything except the server.
- Database functions are restricted to the server’s role, because the database publishes them as public endpoints by default.
- Staff sign in with a bar passcode or a manager passcode, both stored as bcrypt hashes; sessions last 16 hours on the bar and 4 for a manager, and changing a passcode signs out every tablet using the old one.
- Wrong passcodes lock out at 8 tries per device per 15 minutes, and 60 per venue.
- Tables are found only by a 10-character random code; there is no way to list tables, orders or promo codes, and promo guessing is rate-limited.
- Strict content rules, no framing by other sites, the table code never passed to another site, and staff pages never cached or indexed.
Tested before a guest saw it
Run against a local copy with 49 checks: forged and edited sessions, replayed and wrong-signature webhooks, tampered prices, guessed passcodes and double refunds. Then clicked through in a real browser as guest, bar, manager and printer.