Skip to content

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:

HTTP
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.

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.
Give feedback on this page

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/