A regulator asking how one client’s data is separated from another’s wants a mechanism, not a policy document.
What it changes
Three independent layersEvery tenant-owned row carries its tenant; every query is rewritten to carry a tenant predicate; and row-level security enforces the same rule in the database, with context set per transaction so a pooled connection cannot carry it into the next request.
Brand is configurationName, legal name, domain and palette are configuration. No package, component, contract or copy string hard-codes a name.
Supervision is explicitPlatform-operator access across tenants is opt-in per transaction, read-only at the database level, and audited. Cross-tenant writes are refused regardless of application code.
Every irreversible act on this platform takes this shape, whatever the subject of the page: one person asks, a different one agrees, and only then does anything move.
Three layers, each sufficient alone. That is the only reason to run three: a defect in one is contained by the other two.
What it includes
Tenant provisioningBranding, roles, policy and approval thresholds per tenant.
Segregation of dutiesConflicting-role detection per tenant, surfaced where the owner actually looks.
Per-tenant exportsAudit, ledger and register, scoped to the tenant.
Evidence, not assertion
Controls that have been verified running, rather than described.
A test reads the generated data model and fails if any table is unclassified, so a new table cannot ship without somebody deciding how it is isolated.
Tenant isolation is checked before permission, so a denial cannot confirm that a foreign resource exists.
A control written down is not a control. Only the two lower rows are evidence that something holds, and both are what the list beside this describes.
See it against something real.
Bring an instrument you are actually considering. Structuring it is the only way to judge whether the model fits.