The scenario

Consider a SaaS product where an account can belong to several workspaces, with different permissions in each. The example would let a person switch workspace context while keeping authorization tied to verified membership. A workspace identifier in a URL would select context, but would never grant access by itself.

Resolve membership on the server

The application would authenticate the session and resolve active workspace membership at the server boundary. Each action would check the required permission, including exports, background jobs, and attachment access. Hiding an interface control would be useful presentation logic, not an authorization mechanism.

A small permission model would describe operations such as reading a project, editing one, or managing membership. Ownership transfer and account removal would have explicit rules. Requests started before a membership change would need a defined policy rather than relying on an old client-side role.

Use database isolation as an additional boundary

Tenant-owned tables would carry a tenant reference. PostgreSQL row-level security could enforce row visibility and write constraints for the intended application role. The design would account for roles that bypass policies, including superusers, BYPASSRLS roles, and normally table owners.

A pooled connection would receive tenant context through a controlled transaction-scoped mechanism. The next request must not inherit the previous tenant’s context. Tests would use the real restricted application role; a successful test under a database owner account would not prove isolation.

Include the paths outside ordinary page requests

Cache keys, asynchronous jobs, stored files, and search indexes would all include the intended tenant scope. A job payload would identify the tenant and operation, while the worker would verify that its authority is still appropriate before exposing data or applying a change.

An integration test matrix would try direct object references across two workspaces, role changes during a session, and a user with no active membership. Audit records would identify the actor, tenant, and operation without copying the underlying sensitive record into general logs.

What to validate

  • Changing a URL cannot reveal a different workspace’s record.
  • The restricted database role enforces the expected row policies.
  • Pooled connections do not leak tenant context.
  • Exports, files, jobs, and caches follow the same isolation rules.

The tradeoff

Row-level security can strengthen isolation, but it does not replace authorization design. Complex policies and privileged worker roles need review and realistic tests. A simpler ownership model may be preferable for an early single-workspace product.

Technical references

Official documentation supporting the tools and mechanisms discussed above. The proposed architecture is illustrative.