Tenant Isolation
Tenant isolation is HQ’s most important security property. A team AI operating system holds an organization’s working context and brokers access to its data, so the guarantee customers most need is simple to state: one organization can never read or write another organization’s data. This page explains how HQ enforces that guarantee.
HQ isolates tenants physically and cryptographically, not just logically. The design avoids the most common multi-tenant failure mode — a shared datastore where a missing WHERE tenant_id = ? clause leaks data — by giving every tenant separate storage and a separate encryption key, and by brokering every access through a credential that the cloud platform itself constrains to a single tenant.
| Layer | Isolation mechanism |
|---|---|
| Storage | A dedicated Amazon S3 bucket per organization. |
| Encryption | A dedicated AWS KMS customer-managed key (CMK) per organization. |
| Access | Per-request AWS STS sessions whose IAM policy is scoped to exactly one tenant’s bucket and key. |
| Authorization | Membership role plus path-scoped grants, recomputed per request, never cached. |
| Verification | Blocking end-to-end tests in CI that assert cross-tenant access is denied. |
Dedicated storage per tenant
Each customer organization is provisioned with its own S3 bucket. (Each individual user likewise receives a dedicated personal bucket.) Buckets are created through an idempotent provisioning routine that also applies, on every run:
- Full S3 Public Access Block — buckets are never public.
- A bucket policy that denies all non-TLS requests and restricts access to the vault service’s role.
- Object versioning, so overwrites and deletes are recoverable.
- SSE-KMS default encryption bound to that tenant’s dedicated key (below).
Because data lives in physically separate buckets, there is no shared object namespace across tenants to mis-scope.
Dedicated encryption key per tenant
Provisioning also creates a dedicated KMS customer-managed key (CMK) per organization, used as the default encryption key for that tenant’s bucket. Keys are symmetric, rotated automatically on an annual cycle, and tagged so that IAM policies can gate KMS usage on the tag.
The practical consequence: a tenant’s objects are encrypted under a distinct key. Even within AWS, decrypting one tenant’s data requires access to that tenant’s specific key, which the access-brokering layer grants only to that tenant’s authorized members.
Access brokered by scoped, short-lived credentials
This is the core enforcement mechanism. HQ does not rely solely on application code remembering to filter by tenant. Instead:
- A request arrives bearing the caller’s verified identity (a validated JWT; see Identity & Access Management).
- The service resolves the caller to their organization membership — a role (admin / contributor / read-only) and a set of permitted path prefixes, including any explicit grants and deny carve-outs.
- The service compiles those permissions into a least-privilege IAM policy that references only that one tenant’s bucket and KMS key, then calls AWS STS
AssumeRoleto mint a short-lived session (15 minutes by default, capped at one hour) carrying that policy. - All data access uses that scoped session. AWS — not just HQ’s code — then enforces the boundary: the credentials are cryptographically incapable of touching another tenant’s bucket or key.
Two properties strengthen this:
- Fail-closed. If the computed policy cannot be represented or would exceed limits, the request is denied rather than broadened.
- No credential caching. Permissions are recomputed on each request, so revoking a membership or changing a grant takes effect on the very next call — there is no stale-session window.
Authorization model
Access within a tenant is governed by an access-control list (ACL) model:
- Permission levels:
read,write,admin(ranked). - Grantee types: individual person, group, email, or organization-wide.
- Resolution: the most specific matching path rule wins; a resource’s creator and organization admins resolve to
admin; an explicitly “open” resource floors atreadfor the organization.
Grants are stored as per-path entries and consulted when the per-request session policy is built (step 3 above), so the ACL decision and the enforced AWS scope are derived from the same source of truth.
Capability-based external sharing
When a user shares data outside their organization, HQ issues an encrypted, single-use, time-limited capability token rather than broadening bucket access (see Data Security & Encryption). These tokens are pinned to specific paths and a maximum permission level (capped at write; admin is never grantable through a share), and are consumed atomically so they cannot be replayed.
Isolation at the local-agent layer
HQ runs agents on customers’ own machines as well as in the cloud. The local layer enforces complementary isolation:
- Per-organization credentials are kept separate; the agent layer does not fall back to one organization’s credentials when operating in another’s context.
- Credential, settings, dataset, and prompt-library directories are excluded from cloud sync by default and validated against the ignore rules before a first upload.
See Shared Responsibility for the division of duties on customer-controlled machines.
Verification: isolation is test-enforced
Cross-tenant isolation is not just an architectural claim — it is a gate in the continuous-integration pipeline. HQ’s CI runs end-to-end tests that attempt cross-tenant access and assert it is denied; these tests are treated as blocking for the relevant service. This makes a regression that weakens isolation a build failure rather than a silent vulnerability.
Honest limitations
- Isolation depends on the per-request session policy being scoped correctly; we mitigate this with fail-closed defaults, the test gates above, and audit logging of every credential issuance, and we are working to add principal-scoped storage policies as an additional, redundant backstop.
- Per-tenant keys are Indigo-managed (no BYOK / E2E today).
- Certain internal administrative and maintenance functions operate with broader scope than a normal tenant session; these are restricted to vetted staff/automation and recorded in the audit trail. Narrowing them further is tracked on the roadmap.