Skip to content

Keeping your venues' data separate — who can see what

The rule: a logged-in user can only see and change data for the venues they’re attached to. Not the venue the request claims to be about — the venues they actually belong to.

You opened io osteria centrale three years ago. Two months later you opened io osteria nord. The two venues share a brand, a menu, a recipe library, and a supplier list (see [[overview]]). What they do not share is daily operations: orders, the till, today’s stock counts, the staff roster, sales numbers, tax invoices, customer history.

When the head chef at centrale logs in and opens the orders page, they see centrale’s tickets. They do not see nord’s. When the manager at nord changes a menu item’s price, the change applies to nord — not to centrale. This page explains how that separation is enforced, and why it holds even if someone deliberately tries to break it.

What it does

Every screen in the admin app is scoped to a venue. The header shows which venue you’re currently looking at; for managers attached to a group, there’s a switcher that lets you move between venues you have permission for. The data on the page below — orders, menu items, inventory counts, sales — is filtered to that venue.

That filtering is not just visual. It is enforced by the system on every single request, before any data is returned or any change is committed.

Three things happen on every action you take:

StepWhat the system doesWhy
1. Who is askingReads your signed-in identity from the proof your browser carries. This proof cannot be forged or copied between people.It anchors the request to a specific person, not a claim.
2. What they can touchLooks up the list of venues you’re attached to, in the database.Your attachment list is the truth — the request itself doesn’t get to declare it.
3. Does this venue matchChecks the venue named in the request against your attachment list. If it isn’t there, the request is rejected with a clear error.A request for centrale’s data from a nord-only person never reaches the data.

The third check is the load-bearing one. It is enforced server-side, on every endpoint that touches venue-scoped data. The browser cannot override it — even with a modified request, even with developer tools open, even with a hand-crafted call to the back end.

How to use it

The day-to-day case

You don’t see any of this. The header tells you which venue you’re in. You change a price — it applies to that venue. You open the orders page — you see that venue’s orders. The switcher in the top bar shows the venues you’re attached to; if you only own one, there’s nothing to switch.

The multi-venue case

You attach a manager at centrale to centrale only. They log in, they see centrale. They can open the venue switcher, but it only shows centrale — nord is not in their list, so they cannot select it. If they somehow craft a request asking for nord’s sales, the system refuses with “you don’t have access to that venue”.

You attach a regional manager to both centrale and nord. They log in, they see whichever venue they last picked. They can switch freely between the two. Requests against either venue go through; requests against a third venue they aren’t attached to are refused.

Staff sign-in is per venue too. Separate from the logged-in access above, each till asks the person actually using it for a numeric PIN, and that PIN belongs to one venue’s staff list. If a tablet is carried from nord to centrale — or you switch the terminal to a different venue — the till locks and asks for a centrale PIN before anyone can take an order. A nord sign-in can’t ring up a centrale order. So a server only ever works under a profile that belongs to the venue they’re serving, even on a shared device.

The super-admin case

The platform team has a separate flag for full-fleet access — used for support, debugging, onboarding new venues. This is not a venue attachment; it’s a global override on a small, named list of accounts. You can see who has it on the user table in the platform admin area.

What this protects against

The protection is meaningful in three concrete scenarios:

ScenarioWhat’s prevented
A waiter at centrale signs in to a tablet that’s been used at nord, and tries to load nord’s order historyThe request reaches the back end with the right signed-in identity (waiter at centrale). The back end checks attachments, finds no nord binding, refuses. The waiter sees an error, not nord’s tickets.
A curious manager opens browser developer tools and tries to call the back end directly with a different venue’s IDThe signed-in identity in the request is still theirs. The back end still checks attachments. The fact that the request was crafted by hand changes nothing — the gate is on the server.
An ex-employee whose attachment was removed still has their old session cookies on a personal laptopRemoving a venue role takes effect on the next request. Their cookie can still prove they’re them, but the attachment lookup now returns empty for that venue. Requests get refused. (Revoking their account entirely is a separate step — see [[head-chef]] for the offboarding flow.)

What this does not protect against

This page is about isolation between venues. It is not about isolation between roles within a venue. A waiter and a head chef at the same venue are both “attached to centrale” — the system permits both their requests. What each can actually do once they’re in is governed by their role and capabilities (see [[head-chef]] or [[waiter]] for examples). A waiter cannot edit prices; a head chef cannot reopen a closed shift; the platform team’s role catalog defines who can do what. That is a separate layer on top of venue isolation, not a substitute for it.

This page is also not about encryption of data at rest. Owner-grade encryption (where even the platform cannot read your data without a key) is a roadmap item, not the current shape.