Security
How DataRestro protects your data
The controls that protect restaurant and guest data today, each backed by a test or a drill, and at the end, what we do not claim.

One request, seven gates
The checks one order passes, from tablet to database
Follow a single order from a cashier's screen to PostgreSQL. Select a gate to see what it does and how we know it works.
TLS terminates in front of the API and cookies are marked secure in production. Every response carries Helmet security headers, a locked-down Content-Security-Policy and no-referrer. CORS allows exact origins only; a wildcard origin is refused at start-up, because the API sends credentials.
Evidence: API refuses to boot with a wildcard CORS origin or the published example secrets
- Your data, in PostgreSQL
Gate 1 of 7
Transport & headers
TLS terminates in front of the API and cookies are marked secure in production. Every response carries Helmet security headers, a locked-down Content-Security-Policy and no-referrer. CORS allows exact origins only; a wildcard origin is refused at start-up, because the API sends credentials.
Evidence
API refuses to boot with a wildcard CORS origin or the published example secrets
Data we never collect
- Card numbers
- Cards are run on your own terminal. The POS records the amount and the approval reference. No cardholder data ever reaches it.
- Plain-text passwords
- Hashed with argon2. Nobody at DataRestro can read your password, including us.
- Request bodies in error reports
- Error tracking drops bodies wholesale and redacts auth headers, cookies, tokens, card references, emails and phone numbers. Session replay is off, because it would record guest names off the POS screen.
- Prices from the browser
- Guests and staff send ids and quantities. Every price, tax and total is computed by the server.
- Internals on public endpoints
- The guest-facing API never returns payments, staff names, other guests’ orders, costs or the audit trail. Health probes return up/down and a latency, never versions or hostnames.
Testing the guest ordering flow
QR ordering is the only part of the system anyone can reach without signing in. We sent these unauthenticated requests to a running instance. The results are below.
| Attempt | What happened |
|---|---|
| Unknown or expired QR token | 404One message for malformed, expired and never-valid, so nothing can be told apart. |
| Guessing restaurant slugs | 404Identical for “no such restaurant” and “restaurant disabled”. Slugs cannot be enumerated. |
| Ordering another restaurant's menu item | 400Ids are filtered by restaurant in the same query; a foreign id looks like a missing one. |
| Attaching a modifier from another item | 400A modifier must belong to this restaurant and be linked to this exact item. |
| Quantity 0, or 51 on one line | 422Rejected before the database is touched. |
| Reading another table's order through your QR | 404Every order lookup is filtered by the table the token resolves to. |
| Replaying an order with a tampered body | 422Same idempotency key with a different body is refused; the original is untouched. |
Guest order tracking uses polling rather than a live socket. A guest-safe realtime channel has to prove it cannot see another table's traffic; until it can, we would rather ship the slower, provably scoped option.
Backups and recovery
Backups and the restore drill
We deleted a year of trading data from a production-sized copy and restored it from backup.
- Recovery point target
- ≤ 15 min
- Recovery time target
- ≤ 1 hour
- Single-host restore
- ~10 min
- Daily backups kept
- 30
Targets, not guarantees. Nightly dumps alone give a 24-hour recovery point; managed point-in-time recovery brings it under five minutes, which is why we recommend it for every deployment.
The drill shown here ran on a production-sized copy of the data. For the hosted service, an independent, encrypted backup and a production restore drill are still being put in place; until they are, recovery relies on our database provider's built-in features, and we do not claim these targets for it.
- Baseline44,547 orders · 36,275 payments · revenue 5,469,666.37
- Backuppg_dump --format=custom → 12.3 MB, catalogue verified
- Destroyevery payment and refund, 20,000 orders, 70,207 order items, all stock zeroed
- RestoreDROP DATABASE, CREATE, pg_restore: no errors
- Verify44,547 orders · 36,275 payments · revenue 5,469,666.37
- Integrity0 orphans · 0 paid-status mismatches · 97 foreign keys · 132 indexes
Revenue after restore: exact to the cent.
How long data is kept
A nightly job can apply a retention policy, which you can preview before it runs. These are its defaults. Tax records are always kept for the legal minimum.
- TransactionsKept for the tax record-keeping period84 months
- Audit logConfigurable; must be disabled for Nepal fiscal use24 months
- Dormant guestsPersonal data anonymised, sales kept24 months
- Idempotency keysLong enough to catch any retry48 hours
What we don't claim
Certifications we do not hold
DataRestro holds no third-party security certification or attestation today. We have not completed a SOC 2 or ISO 27001 audit, and we are not PCI-DSS certified: card data never reaches us, which keeps it out of scope rather than certified. We are not IRD-approved. When any of that changes, it will be listed here with the report.
Some security sits with your restaurant: give each person their own login or PIN, lock counter devices when they are unattended, and remove access as soon as someone leaves. Owners can see sensitive actions in the audit log.
Found a vulnerability? Email support@datadoodlestech.com privately with steps to reproduce, and give us time to fix it before it is public.