# Isolation and trust

## What it is

Each environment gets its own database, its own service logins and its own keys, so an app's users and tokens cannot reach another environment. Some parts are deliberately shared (the PostgreSQL engine, Storage, the gateway and the host), and anything shared is a place where one environment's failure can affect the others.

## Why

**Choice: trusted operators, untrusted app visitors.** The people who run the server and write SQL for its environments are trusted. The visitors of the apps, with their anonymous or signed-in tokens, are not. This matches the primary user (one developer or agency running apps for their own clients) and keeps the design honest about what it defends against.

**Rejected alternative: hostile multi-tenant hosting.** Selling space to mutually hostile customers would require isolation from the operator and from arbitrary SQL, which a shared PostgreSQL engine cannot give. Anyone who needs that should run independent stacks.

**Choice: separate credentials, not only separate schemas.** Separation by schema inside one database would leave every environment behind the same Auth and the same API roles. A database per environment, with its own logins and connection rules that allow exactly one login to reach exactly one database, keeps a leaked service credential inside its environment.

## How we built it

![Untrusted app visitors reach the server only through the TLS proxy and the gateway with a publishable key; trusted operators use the console or the host directly; each environment has its own Auth, REST, database and logins, while the PostgreSQL engine and Storage are shared failure boundaries](https://base.sbarah.com/docs/diagrams/trust-boundaries.svg)

*Only the TLS proxy faces the network; the engine and Storage are shared failure boundaries.*

![A request with project A's key on environment A's path reaches A's REST and database A; the same key on environment B's path gets 401 at the gateway; and a login that tries another environment's database is refused by PostgreSQL's connection rules](https://base.sbarah.com/docs/diagrams/key-isolation.svg)

*No data mixing: A's key, tokens and logins open only A's database.*

![A burst on environment A fills its guaranteed 8 gateway slots and borrows idle ones up to its ceiling of 24 of the gateway's 64, so environment B is still admitted at once and A's extra requests get 429; behind the gateway each environment has its own containers with CPU, memory and IO limits, and its own connection limits in the shared engine](https://base.sbarah.com/docs/diagrams/load-isolation.svg)

*A busy environment uses the idle server, but never the share its neighbours need. The limits are not calibrated under sustained load.*


What is separate per environment:

- A database with `CONNECT` granted only to its own logins, and connection rules (the PostgreSQL host-based authentication file, HBA) naming exact login and database pairs.
- Three scoped service logins for Auth, REST and Storage, with generated passwords.
- A developer login for migrations, agents and Studio. It is not a superuser, cannot use the platform's schema names, and cannot create extensions that reach the server's network or see every environment, such as `http`, `pg_net` or `dblink` ([database access](https://base.sbarah.com/en/docs/guides/database-access/)).
- Its own Auth signing secret, its own publishable and secret keys (secret keys stored only as hashes), and its own Storage tenant and signing keys.
- Its own Realtime, Edge Functions and Studio containers when they are on. The Functions container reaches only its own Auth, REST and Storage tenant, and each Studio session has a private network.
- A routing record that can put the environment in maintenance without touching the others.

What is shared, and therefore a shared failure boundary:

- **The PostgreSQL engine.** A crash, a full disk or a long lock affects every environment on it. The canonical API roles (`anon`, `authenticated`, `service_role`) exist once per engine, because PostgreSQL roles are cluster-wide.
- **The Storage process.** It holds every tenant's configuration; a compromise of that process is a compromise of all tenants' files.
- **The gateway and control catalog.** If they stop, every environment stops answering.
- **Vault's root key.** Every environment's Vault secrets are encrypted with one key that belongs to the server. They stay apart because each environment reaches only its own database.
- **The host.** CPU, memory, disk and IO are shared. Each container runs under a resource tier with CPU weight and per-device IO limits, and new environments are refused when memory, disk, cgroup pressure or connection budgets are short.

Code: [lab/resource_policy.py](https://github.com/M7MMAD-OMAR/sbarbase/blob/main/lab/resource_policy.py) (tiers), [lab/resource_admission.py](https://github.com/M7MMAD-OMAR/sbarbase/blob/main/lab/resource_admission.py), [lab/pressure_admission.py](https://github.com/M7MMAD-OMAR/sbarbase/blob/main/lab/pressure_admission.py) and [lab/connection_budget.py](https://github.com/M7MMAD-OMAR/sbarbase/blob/main/lab/connection_budget.py) (admission), [lab/hba_authority.py](https://github.com/M7MMAD-OMAR/sbarbase/blob/main/lab/hba_authority.py) (connection rules), [src/gateway/handler.ts](https://github.com/M7MMAD-OMAR/sbarbase/blob/main/src/gateway/handler.ts) (key checks).

## Limits

- Isolation from a hostile server operator or from arbitrary SQL run by a trusted author is not provided.
- Resource tiers are configured, not calibrated under sustained load; a noisy neighbour can still slow the others.
- Reloading connection rules does not end sessions that were already open.
- Multiple adversarial reviews informed the design; they are not a security certification.

## Go deeper

- [Threat model](https://base.sbarah.com/en/docs/explain/threat-model/): assets, actors, trust boundaries, the evidence behind each mitigation and the known gaps.
- [Security and operations review](https://github.com/M7MMAD-OMAR/sbarbase/blob/main/docs/engineering/reviews/security-operations.md).
- [Resource policy](https://github.com/M7MMAD-OMAR/sbarbase/blob/main/docs/engineering/RESOURCE-POLICY.md), [resource admission](https://github.com/M7MMAD-OMAR/sbarbase/blob/main/docs/engineering/RESOURCE-ADMISSION.md), [pressure admission](https://github.com/M7MMAD-OMAR/sbarbase/blob/main/docs/engineering/PRESSURE-ADMISSION.md), [connection budget](https://github.com/M7MMAD-OMAR/sbarbase/blob/main/docs/engineering/CONNECTION-BUDGET.md), [noisy neighbour](https://github.com/M7MMAD-OMAR/sbarbase/blob/main/docs/engineering/NOISY-NEIGHBOR.md).
- [Shared Storage review](https://github.com/M7MMAD-OMAR/sbarbase/blob/main/docs/engineering/reviews/shared-storage.md) and [atomic HBA replacement](https://github.com/M7MMAD-OMAR/sbarbase/blob/main/docs/engineering/ATOMIC-HBA-REPLACEMENT.md).
