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:
| Table | RLS policy |
|---|
conversations | org_id = auth.org_id() |
messages | org_id = auth.org_id() |
agents | org_id = auth.org_id() |
skills | org_id = auth.org_id() OR scope = 'system' |
projects | org_id = auth.org_id() |
members | org_id = auth.org_id() |
audit_logs | org_id = auth.org_id() |
files | org_id = auth.org_id() |
api_keys | org_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
| Guarantee | Implementation |
|---|
| Organization A cannot see Organization B’s conversations | RLS + application middleware |
| Organization A cannot access Organization B’s files | S3 key prefix isolation + RLS |
| Organization A cannot search Organization B’s knowledge base | Vector store metadata filtering + RLS |
| Organization A cannot see Organization B’s members | RLS + application middleware |
| Organization A cannot access Organization B’s audit logs | RLS + application middleware |
| A bug in application code cannot bypass isolation | PostgreSQL RLS enforced at the database engine level |