Skip to main content

Tenant Isolation

Tegendo.AI is a multi-tenant platform, meaning multiple organizations share the same infrastructure. Strict tenant isolation ensures that one organization’s data is never accessible to another — at every layer of the stack.

Isolation architecture

Tenant isolation in Tegendo.AI operates at four levels:

1. Network isolation

Each organization’s traffic is logically isolated at the network level:
  • All services run in private VPCs with security groups that restrict traffic to authorized services only
  • API requests are authenticated and tagged with the organization ID at the edge (API gateway) before reaching any backend service
  • There is no network path between organizations — all inter-service communication passes through authenticated internal APIs

2. Application isolation

The application layer enforces organization boundaries on every request:
  • Middleware authentication — Every API request is authenticated and the organization ID is extracted from the authenticated session or API key
  • Organization context — All database queries are scoped to the authenticated organization. There is no API endpoint that can return data across organizations
  • Request isolation — Each request is processed in its own execution context. No state is shared between requests from different organizations

3. Database isolation (Row-Level Security)

Tegendo.AI uses Supabase with PostgreSQL Row-Level Security (RLS) to enforce tenant isolation at the database level. This is the strongest form of multi-tenant isolation available in a shared-database architecture.

How RLS works

Every table that contains organization data includes an org_id column. RLS policies are defined at the database level to ensure that:
-- Example RLS policy
CREATE POLICY "Users can only see their own organization's data"
ON conversations
FOR ALL
USING (org_id = auth.org_id());
This means:
  • SELECT queries only return rows where org_id matches the authenticated organization
  • INSERT operations automatically set org_id to the authenticated organization
  • UPDATE and DELETE operations can only affect rows belonging to the authenticated organization
  • These policies are enforced by PostgreSQL itself, not by application code
RLS policies are enforced at the database engine level. Even if application code contained a bug that omitted an organization filter, PostgreSQL would still prevent cross-tenant data access. This provides defense-in-depth beyond application-level controls.

RLS coverage

RLS policies are applied to every table containing organization data:
TableRLS policy
conversationsorg_id = auth.org_id()
messagesorg_id = auth.org_id()
agentsorg_id = auth.org_id()
skillsorg_id = auth.org_id() OR scope = 'system'
projectsorg_id = auth.org_id()
membersorg_id = auth.org_id()
audit_logsorg_id = auth.org_id()
filesorg_id = auth.org_id()
api_keysorg_id = auth.org_id()

4. Storage isolation

Files uploaded by users are stored in S3 with organization-scoped key prefixes:
s3://tegendo-uploads/{org_id}/{file_id}
  • S3 bucket policies prevent any cross-organization access
  • Pre-signed URLs are generated per-request with the authenticated organization ID
  • File metadata in the database is also protected by RLS

Vector store isolation

Agent knowledge bases use a vector database for RAG (Retrieval-Augmented Generation). Vector embeddings are isolated by organization:
  • Each organization’s embeddings are tagged with the org_id metadata field
  • Vector similarity searches are filtered by org_id before returning results
  • There is no query path that can return embeddings from another organization

AI provider isolation

When Tegendo.AI sends requests to AI providers (Anthropic, OpenAI, Google):
  • Each request contains only the authenticated organization’s data
  • BYOK organizations use their own API keys, ensuring complete separation at the provider level
  • For shared API keys (non-BYOK), requests are stateless and providers do not associate requests with specific Tegendo.AI organizations

Cache isolation

Redis caches used for session management and rate limiting are isolated:
  • Cache keys are prefixed with the organization ID: org:{org_id}:session:{session_id}
  • Rate limit counters are scoped per organization and per user
  • No cache query can return data from a different organization

Testing and verification

Tenant isolation is continuously verified through:
  • Automated integration tests — Test suites attempt cross-tenant access on every deployment and verify that it fails
  • RLS policy audits — Automated checks verify that every table with organization data has RLS enabled and correctly configured
  • Penetration testing — Annual third-party penetration tests specifically target tenant isolation boundaries
  • Code reviews — All database queries are reviewed to ensure they work correctly with RLS policies

Isolation guarantees

GuaranteeImplementation
Organization A cannot see Organization B’s conversationsRLS + application middleware
Organization A cannot access Organization B’s filesS3 key prefix isolation + RLS
Organization A cannot search Organization B’s knowledge baseVector store metadata filtering + RLS
Organization A cannot see Organization B’s membersRLS + application middleware
Organization A cannot access Organization B’s audit logsRLS + application middleware
A bug in application code cannot bypass isolationPostgreSQL RLS enforced at the database engine level