# RPF-WP-0019 — apps-pg isolation evidence

Date: 2026-08-20

Live target: railiance01 / `databases/apps-pg`

Harness: `make apps-pg-isolation-probe`

The repeatable harness creates a labeled temporary namespace, projects the two
existing consumer Secrets into isolated probe pods without printing their
values, exercises the real consumer credentials over the service endpoint,
and deletes the namespace on exit.

## Finding before the passing run

The first privilege preflight found that `apps_meta`, `vergabe_db`, and
`coulomb_social_db` retained PostgreSQL's default `PUBLIC` `CONNECT` and
`TEMPORARY` privileges. A database-per-consumer declaration was therefore not
yet a database connection boundary. The controlled SQL now revokes both
privileges from `PUBLIC` on all three databases and grants them only to each
database's owner. The passing run occurred after that correction; the failed
precondition is not counted as a pass.

## Consumer boundary

All eleven assertions passed:

- each role connected to its own database through the live RW Service;
- each role was denied connection to the peer database;
- `coulomb_social` was denied connection to `apps_meta`;
- a consumer could not alter the peer role;
- an own-database table remained readable;
- the real credential observed both 15-second timeouts and connection limit
  20; and
- a 20-second statement was terminated by `statement_timeout`.

## Noisy-neighbour run

The harness measured five sequential `vergabe` queries, filled every available
`coulomb_social` role slot with client-side-idle sessions, verified 20 live
connections, and attempted one more connection.

| Observation | Result |
| --- | --- |
| `vergabe` baseline, five queries | 5,285 ms |
| `coulomb_social` at ceiling | 20 connections |
| excess `coulomb_social` connection | denied |
| `vergabe` during saturation, five queries | 8,146 ms |
| measured wall-time increase | 54.1% |
| victim availability | 5/5 queries succeeded |

The timings include five separate API/exec/process startups, so they are an
operator-path comparison rather than an application latency benchmark. Both
co-residents declare `interactive`, but neither declares a numeric database
latency objective. The result therefore supports the P1 consumer-boundary and
availability claim: one consumer exhausted its own allowance, the control
bound, and the peer retained service. It does **not** establish a latency SLO,
CPU fairness, memory fairness, tenant isolation within either consumer, HA, or
P2 placement.

## Result

`14 passed, 0 failed`. Production `apps-pg` remained Ready with continuous
archiving and the last backup healthy; `deployment/coulomb-social` remained
1/1 Ready. The temporary probe namespace was deleted.
