Tenant isolation¶
Venturi enforces isolation between tenants by construction: separate data stores, separate encryption keys, and a query layer that rejects any cross-tenant access. This page describes exactly how your data is kept apart from every other tenant’s, and how Venturi support is prevented from holding standing access to it.
Customer-onboarding isolation contract
Tenant-scoped stores and keys, signed-token tenant binding, the 403
TENANT_MISMATCH rejection, and customer-approved support access are
activation requirements. A deployment is not handed to a customer until
these controls pass the onboarding verification for that tenant.
Isolation primitives¶
Tenant isolation is built from per-tenant resources, not from row-level filtering on a shared store.
| Resource | Isolation model |
|---|---|
| Attribution store (Postgres) | Each tenant’s AttributionRecords live in a tenant-scoped database. Records for tenant T are accessible only to tenant T (and to Venturi support under the break-glass procedure below). |
| Event stream (Kafka) | Event streams are tenant-scoped; the topic namespace is tenant-isolated. |
| Encryption keys (KMS) | Every database and tenant-scoped object-storage bucket uses a customer-managed KMS key (one key per tenant) in your own KMS key store. |
| Audit trail | The audit log is tenant-scoped: each tenant’s trail is written to that tenant’s own audit bucket, reads through Venturi go through the tenant’s audit-retrieval role, and a request for another tenant’s audit entries returns 403 TENANT_MISMATCH. See Audit logs. |
| SaaS routing tier | In SaaS mode only, a shared, multi-tenant routing tier in front of every dedicated data plane terminates TLS behind the tenant-plane WAF, resolves the tenant from the credential (never from a client-supplied tenant identifier), and forwards the request to that tenant’s data plane. For routing it holds salted API-key hashes, client_id registrations, and provider-key fingerprints, never the keys themselves; proxied request and response content stays in memory and is never logged. See SaaS routing tier. |
| Deterministic resolution | Stage A (deterministic reconciliation), the platform stage that runs before RAIL (Resource Attribution & Inference Layer) inference in the three-stage attribution pipeline, operates entirely within the dedicated tenant data plane, with no shared state across tenants. |
Per-tenant keys¶
Each tenant’s encryption keys live in your own key store. Venturi workloads receive only Decrypt and GenerateDataKey on your key, never ScheduleKeyDeletion. Keys are rotated annually, or on a cadence you define.
This per-tenant key model is also the mechanism behind certified erasure: destroying a per-subject or per-tenant data-encryption key renders the data encrypted under it permanently unrecoverable. Per-subject and per-tenant data-encryption keys are generated under your customer-managed KMS key and stored only in wrapped (encrypted) form. Crypto-shred erasure destroys the wrapped data-encryption keys, so it needs no KMS key deletion, and Venturi workloads never hold ScheduleKeyDeletion on your key. See crypto-shred erasure.
Cross-tenant access is rejected, not filtered¶
Every request to the query API carries a signed Bearer token that resolves to a tenant_id. The verified token selects the tenant; a tenant identifier in the URL or request body cannot override it. A request for a resource that belongs to another tenant returns HTTP 403 with the error code TENANT_MISMATCH, and the response never contains rows or identifiers belonging to that tenant. Cross-tenant attempts are additionally logged with full request context for security audit.
In this example, a token issued to one tenant requests an attribution record that belongs to a different tenant:
GET /v1/attribution/attr_01HF8QZ2V9K7M3N4P5R6S7T8W9 HTTP/1.1
Host: api.venturi.systems
Authorization: Bearer <access token issued to your tenant>
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
{
"type": "https://venturi.systems/problems/tenant-mismatch",
"title": "Tenant mismatch",
"status": 403,
"detail": "The requested resource belongs to another tenant.",
"instance": "/v1/attribution/attr_01HF8QZ2V9K7M3N4P5R6S7T8W9",
"error_code": "TENANT_MISMATCH",
"trace_id": "5f0c2d7e-8a41-4b6f-9c3e-2d71a8b4e019"
}
Error bodies follow the API error contract. For a self-hosted deployment, send the same request to your own instance host.
This is the binding engineering invariant: a cross-tenant query returns 403
TENANT_MISMATCH and never returns rows from a different tenant. Activation
evidence includes the tenant-binding test for the deployed query path.
Token validation discipline
Bearer tokens are verified for issuer, audience, expiry, and signature before any authorization decision. Tokens using alg:none or otherwise unsigned are rejected. Tenant binding (the subject-to-tenant_id mapping) is enforced only after signature verification: a token is never trusted to assert its own tenant before its signature is validated (RFC 8725, JWT Best Current Practices).
The model is shared; your data is not¶
Venturi’s attribution-intelligence model uses shared model weights across tenants (there are no tenant-specific weights) with per-tenant calibration and per-tenant thresholds applied at inference time.
No tenant’s data trains a model another tenant consumes
No tenant’s data is used to train a model another tenant consumes, except under explicit, scoped, de-identified cross-tenant aggregation permission (described below). Your raw data never becomes another tenant’s training input.
Cross-tenant aggregation (consent-gated)¶
Any cross-tenant signal aggregation (used to improve the baseline models) runs in a separate, Venturi-managed Aggregation VPC that no tenant data plane can read. It operates only with explicit, scoped, de-identified permission, and is off by default.
- Explicit, informed, revocable consent. Participation is opt-in via your agreement; opt-out is available at any time and is recorded in your audit trail.
- De-identification before egress. All tenant-identifying attributes are anonymized before any data leaves the dedicated tenant boundary. The training pipeline reads only from the Aggregation VPC, never from tenant data planes directly.
- k-anonymity with a minimum cohort of 5. Aggregation outputs enforce a minimum cohort size of k = 5, with sub-cohort suppression and roll-up, and blocking of reconstruction-by-differencing across overlapping cohorts. A documented re-identification-risk acceptance test gates the pipeline. The same floor applies to every customer-facing cohort read path; see cohort-only adoption intelligence.
- Per-jurisdiction residency filtering. EU tenants do not contribute to non-EU aggregations, and vice versa.
Once anonymized into the Aggregation VPC, a contribution is non-personal. See Residency & subprocessors for the region-pinning guarantees and Data privacy & retention for how this interacts with erasure.
Support access is break-glass only¶
There is no standing Venturi support access to your data. Any support access to a tenant’s database or runtime is break-glass:
- Customer-approved: a customer Admin approves each request and fixes its scope, purpose, and duration; without approval the request expires unused.
- Time-boxed: a grant lasts 4 hours by default and never more than 24 hours. It auto-revokes when its approved window closes, and your Admin can revoke it at any time.
- MFA-gated: the support actor completes a step-up MFA challenge before a session opens.
- Read-only by default: a session can only read the approved scope unless your Admin explicitly approved a write action.
- Audit-logged: every request, approval, session, action, and revocation is recorded to your tenant audit trail.
- Customer-notified: approving a grant and opening a session each notify you.
This architecture is designed to support the GDPR Art. 28(3)(b) confidentiality-of-personnel obligation and the AICPA Trust Services logical-access criteria. Contractual compliance and assurance depend on the applicable Data Processing Agreement (DPA), the deployed controls, and the evidence available for that customer. For the full break-glass flow and what is visible to Venturi staff before a grant exists, see Support-access architecture.
What a reviewer can verify¶
| Question | Answer |
|---|---|
| Is my data in a shared database? | No. Your AttributionRecords live in a tenant-scoped database, encrypted with your own KMS key. |
| Can another tenant query my data? | No. Cross-tenant queries return 403 TENANT_MISMATCH, are logged, and never return another tenant’s rows. |
| Does another tenant’s model see my raw data? | No. Model weights are shared, but your raw data is never another tenant’s training input; only de-identified aggregates contribute, and only if you explicitly opt into cross-tenant aggregation. |
| Does Venturi support have standing access? | No. Support access is break-glass: customer-approved, time-boxed, MFA-gated, audited, and customer-notified. |
| Who controls the encryption keys? | You do. Keys live in your KMS store; Venturi holds only decrypt/generate, never delete. |
Related pages¶
- Security architecture: the trust boundary, encryption, and the threat model.
- Data privacy & retention: what is collected, retention, and crypto-shred erasure.
- Residency & subprocessors: region pinning and the aggregation environment.
- Data-subject rights: how erasure requests reconcile with the append-only architecture.
Sign in to send feedback. Opens in a new tab.
Copy page details
Docs feedback: Tenant isolation
Page: https://docs.venturi.systems/security/tenant-isolation/