> ## Documentation Index
> Fetch the complete documentation index at: https://getoverlay.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Tenancy and roles

> Single-customer deployment boundary, role model, and multi-tenant roadmap.

Overlay currently uses a **single-customer deployment** model.

That means the deployment boundary is the tenant boundary:

* A self-hosted enterprise gets one web runtime, one Convex deployment, one object-store namespace, and one secret set.
* A managed-cloud enterprise also gets one dedicated deployment and backend set.
* Multiple stakeholders inside that enterprise are users with roles, not separate tenants.

Do not onboard multiple enterprise customers into the same Convex deployment with the current schema.

## Tenants Versus Roles

A tenant is a hard data-isolation boundary. In today’s architecture, that boundary is the deployment itself.

Roles are authorization rules inside one tenant. A school should normally be modeled like this:

| Concept | Example |
| - | - |
| Tenant/deployment | Springfield School District |
| Roles | student, teacher, parent, administrator, IT administrator |
| Optional future grouping | school, classroom, grade, department, project, cohort |

Do not add `tenantId` just to represent students, teachers, parents, departments, or classes. Future RBAC should use roles, groups, memberships, and policy checks within the same deployment.

## Deployment Modes

| Mode | Status | Tenant boundary |
| - | - | - |
| Self-hosted enterprise | Supported target | One customer per deployment. |
| Managed-cloud enterprise | Supported target | One customer per dedicated managed deployment. |
| Shared multi-tenant cloud | Not supported today | Multiple customers in one backend, blocked until tenant isolation is implemented. |

The current config schema rejects `capabilities.multiTenant=true`. Admin/system surfaces should report `single-customer deployment`; no tenant switcher or tenant-admin UI should appear.

## Workspaces Are The In-Deployment Boundary

Within a single-customer deployment, workspaces are the in-deployment boundary for collaboration. A workspace scopes conversations, files, knowledge bases, agents, automations, shares, governance, and billing to a group of members. Cross-workspace access is never implied by deployment membership; every resource read and mutation checks workspace participation. This boundary is what makes a future shared multi-tenant deployment possible: adding `tenantId` is an outer scope on top of workspace-scoped data, not a replacement for it.

## Current Security Model

Single-customer deployment:

* No `tenantId` column is required in Convex tables.
* User-owned rows are scoped by `userId` inside that deployment.
* API keys belong to a user in the deployment.
* Webhook subscriptions and deliveries belong to a user in the deployment.
* Storage keys and generated URLs are scoped to the deployment’s object-store namespace and user checks.
* Operational isolation comes from separate Convex deployments, object-store buckets or prefixes, secrets, domains, logs, and provider credentials.

This is the required model for enterprise customers until shared multi-tenant deployment support exists.

## API Keys And Webhooks

API keys:

* Current behavior: API keys are deployment-local and user-owned through `apiKeys.userId`.
* No tenant claim is encoded or enforced because the deployment is the tenant boundary.
* A dedicated managed-cloud enterprise must have its own `API_KEY_HASH_SECRET`.
* Shared multi-tenant requirement: API keys must include tenant ownership, tenant-aware scopes, tenant-aware rate-limit keys, tenant-aware audit entries, and validation that the key tenant matches the request tenant.

Webhooks:

* Current behavior: webhook subscriptions and deliveries are deployment-local and user-owned through `webhookSubscriptions.userId` and `webhookDeliveries.userId`.
* No tenant routing field exists because the deployment is the tenant boundary.
* Shared multi-tenant requirement: webhook subscriptions, deliveries, event ownership, signing secrets, retries, and delivery runner queries must include tenant context.

## Convex Table Tenant Decisions

These user-owned tables intentionally do **not** have `tenantId` today because the deployment is the tenant boundary. `npm run check:tenant-boundaries` verifies that every current `userId`-owned Convex table is listed here.

| Table | Current owner | Tenant decision | Shared multi-tenant requirement |
| - | - | - | - |
| `userUiSettings` | `userId` | Deployment boundary | Add `tenantId` to row and `by_tenantId_userId` indexes. |
| `subscriptions` | `userId` | Deployment boundary | Add `tenantId`; Stripe customer/subscription indexes must include tenant ownership. |
| `budgetTopUps` | `userId` | Deployment boundary | Add `tenantId`; payment/session indexes must validate tenant ownership. |
| `apiIdempotencyKeys` | `userId` | Deployment boundary | Add `tenantId`; idempotency keys must be tenant-scoped. |
| `apiKeys` | `userId` | Deployment boundary | Add `tenantId`; validation, scopes, rotation, revocation, audit, and rate limits must enforce tenant context. |
| `tokenUsage` | `userId` | Deployment boundary | Add `tenantId`; usage and billing rollups must be tenant-scoped. |
| `budgetReservations` | `userId` | Deployment boundary | Add `tenantId`; reservation and reconciliation queries must be tenant-scoped. |
| `usageOperations` | `userId` | Deployment boundary | Add `tenantId`; operation identity, request fingerprints, and reconciliation must be tenant-scoped. |
| `administrativePrincipals` | `userId` | Deployment boundary | Add `tenantId`; administrative role grants and revocations must be tenant-scoped and audited. |
| `toolInvocations` | `userId` | Deployment boundary | Add `tenantId`; audit/cost views must include tenant context. |
| `dailyUsage` | `userId` | Deployment boundary | Add `tenantId`; usage counters must include tenant context. |
| `skills` | `userId` | Deployment boundary | Add `tenantId`; project and enabled-skill indexes must include tenant context. |
| `automations` | `userId` | Deployment boundary | Add `tenantId`; scheduling and runner queries must not cross tenants. |
| `workItems` | `userId` | Deployment boundary | Add `tenantId`; task lists, board ordering, and dependency checks are already workspace-scoped and must also be tenant-scoped. |
| `automationRuns` | `userId` | Deployment boundary | Add `tenantId`; run history and scheduler claims must be tenant-scoped. |
| `mcpServers` | `userId` | Deployment boundary | Add `tenantId`; connector credentials and enabled indexes must be tenant-scoped. |
| `mcpToolExecutions` | `userId` | Deployment boundary | Add `tenantId`; connector execution audit, authorization, and usage records must be tenant-scoped. |
| `conversations` | `userId` | Deployment boundary | Add `tenantId`; share tokens need explicit cross-tenant policy. |
| `conversationMessages` | `userId` | Deployment boundary | Add `tenantId`; conversation/message indexes must include tenant context. |
| `conversationContextSummaries` | `userId` | Deployment boundary | Add `tenantId`; context summary indexes must include tenant context. |
| `memories` | `userId` | Deployment boundary | Add `tenantId`; memory extraction and search must enforce tenant context. |
| `knowledgeChunks` | `userId` | Deployment boundary | Add `tenantId`; search indexes must include `tenantId` as a filter field. |
| `knowledgeChunkEmbeddings` | `userId` | Deployment boundary | Add `tenantId`; vector indexes must include `tenantId` as a filter field. |
| `r2UploadIntents` | `userId` | Deployment boundary | Add `tenantId`; upload finalization must include tenant context. |
| `files` | `userId` | Deployment boundary | Add `tenantId`; file/folder/share indexes must define cross-tenant behavior. |
| `webhookSubscriptions` | `userId` | Deployment boundary | Add `tenantId`; subscriptions, signing secrets, and event ownership must be tenant-scoped. |
| `webhookDeliveries` | `userId` | Deployment boundary | Add `tenantId`; delivery runner claims and retries must enforce tenant ownership. |
| `emailSuppressions` | `userId` | Deployment boundary | Add `tenantId`; suppression lists must be tenant-scoped to prevent cross-tenant email leakage. |
| `mcpOAuthSessions` | `userId` | Deployment boundary | Add `tenantId`; OAuth session tokens and refresh flows must be tenant-scoped. |
| `authorizationGroupMemberships` | `userId` | Deployment boundary | Add `tenantId`; group membership queries must enforce tenant context. |
| `authorizationUserRoles` | `userId` | Deployment boundary | Add `tenantId`; role assignment queries must enforce tenant context. |
| `conversationEvents` | `userId` | Deployment boundary | Add `tenantId`; event stream and presence queries must be tenant-scoped. |
| `workspacePrincipals` | `userId` | Deployment boundary | Add `tenantId`; principal identity and directory queries must enforce tenant context. |
| `workspaceConnectors` | `userId` | Deployment boundary; Deployment-wide | Add `tenantId`; connector mappings, provider keys, and account ownership must be tenant-scoped. |
| `workspaceUserPreferences` | `userId` | Deployment boundary | Add `tenantId`; per-user workspace preferences must be tenant-scoped. |
| `billingAccounts` | `userId`; optional `workspaceId` | Personal accounts remain user-owned; workspace accounts are bound to the exact workspace | Require a deployment tenant identifier in addition to the current account subject, and keep every Stripe identifier unique within that tenant. |
| `conversationAgentRuns` | `userId` and `workspaceId` | Every collaborative run is authorized through its conversation and workspace; personal runs remain user-owned | Require tenant-scoped run, conversation, initiator, agent, reservation, and idempotency indexes. |
| `documentIngestionJobs` | `userId`; optional workspace-owned file | The job inherits authorization from the source file/project and records its initiating user | Add explicit tenant/workspace ownership and tenant-scoped claim indexes before shared deployment. |
| `slackImportJobs` | `userId` and `workspaceId` | Imports are bound to the selected workspace and initiating user; mappings cannot be rebound across workspaces | Add tenant context to job claims, connector credentials, mappings, and imported resources. |
| `userProviderConnections` | `userId`; optional `workspaceId` | Personal provider credentials are user-owned; workspace connections are authorized through workspace membership and policy | Add tenant context to encrypted credential ownership, lookup, rotation, revocation, and audit indexes. |
| `mcpGrants` | `userId` | An access the person granted to another AI app over MCP: one person, one workspace, one access level; tokens carry only the row id and stop working when it is revoked, and a person who leaves the workspace loses every grant into it | Add `tenantId`; resolve the grant's workspace within the tenant and revoke grants when a member is removed. |
| `agentProfiles` | `userId` | An Overlay Cloud agent's imported Claude Code or Codex config, versioned: cleaned file bundle metadata (never credentials), bound to one agent and one workspace, created by a person who can edit that agent | Add `tenantId`; resolve the agent's workspace within the tenant and delete versions with the agent. |
| `agentProfileChunks` | `profileId` | The compressed contents of one config version, split into chunks; reachable only through its `agentProfiles` row | Inherits the tenant decision of `agentProfiles`. |
| `agentSecrets` | `userId` | The names of values an agent's imported MCP servers need; the values live in the encrypted credential vault and are handed to the agent per run | Add `tenantId`; scope the vault reference to the tenant and delete with the agent. |
| `agentAskCounters` | `workspaceId` | How many questions agents have asked other agents for one person's message or one turn; a counter, no content | Add `tenantId` to the key; counters are deleted with the workspace. |
| `cloudAgentProvisions` | `userId` | Startup progress of an agent's Overlay Cloud machine (phase and a safe error message, never credentials); read and written only through the agent's workspace-authorized machine route | Add `tenantId`; scope by tenant alongside the agent. |
| `agentProviderAccounts` | `userId` | Personal credentials for Claude Code and Codex agents are user-owned; a binding records the owner and the host can read a credential only for an active run of that binding | Add `tenantId`; vault references, status, and lookups must be tenant-scoped, and credentials must stay in the tenant's secret store. |
| `workflowStepEvents` | `userId`; workspace inherited from the automation run | Events are readable only through their owning automation/workflow run and initiating user | Store tenant/workspace ownership directly and tenant-scope projection cursors and subscription indexes. |

The following tables are not user-owned tenant data today. They still need review before shared multi-tenant deployments, but the static check only requires explicit documentation for `userId`-owned tables:

* `processedWebhookEvents`
* `rateLimitWindows`
* `serviceAuthReplayNonces`
* `sessionTransferTokens`
* `overlayFreeRoutes` and `overlayFreeRefreshLocks` (deployment-global operational safety state; the deployment is the tenant boundary, and rows contain only route capability, lease, receipt-status, and quarantine metadata, never user content or credentials)

## Shared Multi-Tenant Checklist

Do not enable shared multi-tenant deployments until this checklist is complete:

* Schema migration plan for adding `tenantId` to every user-owned table.
* Backfill plan for existing rows.
* Index expansion plan for every secondary, search, and vector index.
* Tenant-aware auth/session claims.
* Tenant-aware role and membership model.
* Tenant-aware API keys, scopes, audit trail, and per-key/per-tenant rate limits.
* Tenant-aware webhook subscription, delivery, retry, and signing-secret ownership.
* Tenant-aware object-storage key namespace and public/share URL policy.
* Cross-tenant negative tests for every domain service before enabling shared deployments.
* UI policy for tenant switchers, unavailable states, and tenant admin surfaces.

Until then, use one deployment per enterprise customer.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.