Each company's workspace is kept apart
Every company's data carries its workspace, and the database itself refuses to show one workspace's rows to another.
- Row-level security is on for every workspace table in Postgres. The app connects as a database role that row-level security always applies to.
- Each request runs in a transaction that first sets the workspace; a query without one fails rather than running unscoped.
- Database triggers set a child record's workspace from its parent, so a record can't be attached to another workspace's shipment or invoice.
- An automated test calls every API route as one workspace with another's record IDs and fails if anything is revealed, changed or linked. It's generated from the list of routes, so a new route can't skip it.
- Each workspace has its own address, and sign-in sessions belong to that address alone: a session presented on another workspace is refused.
