SS-02 is the platform's only database plane (ADR-0056): every shared service and app gets state by claim, so tenancy, backups, credentials, audit and encryption are solved once, not per service. Tenant isolation is database-enforced where it can be (Postgres RLS) and mechanically-guarded where it cannot (MySQL app-filter). A recorded boundary (ADR-0068) keeps analytics in Prism, not reaching into operational databases.
Only-data-plane · placement · Prism boundary
0 rows
cross-tenant read (CI pen-test)
1 plane
no embedded / per-service DBs
per-tenant
KEKs in Vault Transit, no cloud KMS
Sub-capabilities
One plane, hard tenant boundaries, and an explicit analytics frontier.
The only-data-plane guarantee
All database requirements go through SS-02 (ADR-0056). No other or embedded engine is allowed on the platform — SQL, KV/cache, vector, full-text and object storage are all claims. That single door is what makes tenancy, audit and encryption uniform.
Tenant→database placement & isolation
Placement (ADR-0071) records where a relational tenant lands and how it is isolated: Postgres+single → shared instance with FORCE ROW LEVEL SECURITY; MySQL+single → shared instance with an application-enforced tenant_id discriminator and the TenantScope guard; MySQL+multi → TiDB. The MySQL asymmetry is stated honestly, not pretended away.
Prism analytics boundary
SS-02 owns operational claims; SS-09 Prism owns governed analytics and SS-06 VRQGO owns observability/audit analytics. Analytics engines (ClickHouse, Iceberg, Trino) are reserved substrate behind Prism — direct analytical reach-in to service databases is forbidden; facts land via CDC/batch.
Per-tenant encryption keys
At-rest data is envelope-encrypted with a per-tenant key-encryption-key held in Vault Transit; KEK rotation never re-encrypts the data. Cloud KMS is forbidden by a sovereignty invariant — keys never leave the platform.
Tamper-evident audit chain
Every audited action — every claim, lease, rotation, placement move — is appended to a Vault-Transit-signed hash chain (ADR-0014). Removing or modifying any past entry is detectable; retention runs to 7 years on Enterprise.
Endpoints
5 real operations on the /api/v1 contract.
Method + path straight from the SS-02 OpenAPI spec. Governed routes take an SS-01 bearer token and, where marked, an X-Tenant-Id; the S3 wire gateway authenticates with AWS SigV4 instead.
GET/api/v1/claims/{name}/placementbearertenant
Read placement + serve the Postgres RLS DDL / MySQL discriminator DDL (?tables=…).
POST/api/v1/claims/{name}/placementbearertenant
Declare the placement requirement; the policy decides target + isolation.
GET/api/v1/engines/catalogbearer
Boundary + license posture: which engines are operational claims vs Prism-reserved.
POST/api/v1/claims/{name}/leasesbearertenant
Vault-held, audit-chained credential lease — the platform's record of access.
GET/api/v1/object/usagebearertenant
Metered usage the SS-60/SS-10 chargeback path reads (zero-rated vs billable).
Worked example
Read the exact RLS isolation the platform enforces.
Read the exact RLS isolation the platform enforces · bash
# For a shared-Postgres tenant, placement emits the RLS setup as DDL.
# Ask for it and you get exactly the isolation the database enforces.
curl "$BASE/claims/orders/placement?tables=orders,line_items" \
-H "Authorization: Bearer $TOKEN" -H "X-Tenant-Id: acme"
# → {"target":"shared-postgres","isolation":"rls",
# "naming":"schema t_acme",
# "ddl":"CREATE SCHEMA t_acme; CREATE ROLE t_acme NOLOGIN;
# ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
# ALTER TABLE orders FORCE ROW LEVEL SECURITY;
# CREATE POLICY tenant_isolation ON orders
# USING (tenant_id = current_setting('app.tenant_id'))
# WITH CHECK (tenant_id = current_setting('app.tenant_id'));
# …"}
# FORCE so even the table owner cannot bypass. A cross-tenant read
# returns ZERO rows — verified by an automated pen-test in CI.
For MySQL/TiDB the same endpoint returns the discriminator DDL and states plainly that the column enforces nothing — the platform/dbaas.TenantScope guard does, refusing any query that isn't bound by tenant_id.
In the architecture
Where it sits on the data plane.
Governance is not a bolt-on: because there is one data plane, tenancy (ADR-0019), the audit hash chain (ADR-0014), per-tenant KEKs and metering (SS-60 → SS-10) are wired into every claim by construction. The placement policy and admission catalogue are pure, table-tested functions; the Prism boundary is enforced by keeping analytics engines off the claim menu entirely.
ADR-0056 — DBaaS is the only database planeADR-0068 — DBaaS/Prism analytics boundaryADR-0071 — Tenant→database placement policyADR-0019 — MultitenancyADR-0014 — Tamper-evident audit chain