Skip to main content
Authorization belongs in your backend

AuthContext is SDK request metadata, not a verified Convex identity or an authorization policy. Tenant propagation varies by operation. Validate the authenticated identity and tenant on your trusted server, authorize every read and mutation there, and keep administrative APIs behind that boundary. Do not expose a privileged Convex deployment directly to untrusted clients or rely on IDs and client-side filters as access controls.

Isolation Boundaries

Understanding Cortex's multi-layered isolation model for security, privacy, and compliance.

Overview​

Cortex provides four layers of isolation that work together to ensure data security, enable multi-tenancy, and maintain privacy boundaries:

Isolation Hierarchy
1. Tenant Isolation

tenantId • Multi-tenant SaaS separation • Auto-injected via AuthContext

2. Memory Space Isolation

memorySpaceId • Fundamental data boundary • Hive or Collaboration Mode

3. User Isolation

userId • GDPR compliance • Enables cascade deletion

4. Participant Tracking

participantId • Hive Mode attribution • Audit trail

Four layers of data isolation
Key Principle

Each layer serves a distinct purpose and can be used independently or combined.


1. Tenant Isolation (Multi-Tenant SaaS)​

Tenant metadata helps scope SaaS data. Complete isolation requires authorization in the application backend.

const cortex = new Cortex({
convexUrl: process.env.CONVEX_URL!,
auth: createAuthContext({
tenantId: "customer-acme", // Tenant metadata; server authorization is still required
userId: "user-123",
}),
});

// Supported APIs use tenantId as a default scope
await cortex.memory.remember({
memorySpaceId: "user-123-personal",
// tenantId: "customer-acme" ← Auto-injected!
userMessage: "Hello",
agentResponse: "Hi!",
userId: "user-123",
userName: "Alice",
});
Tenant Guarantees
  • Tenant A cannot query Tenant B's data
  • Tenant A cannot access Tenant B's memory spaces
  • GDPR deletion respects tenant boundaries
  • Complete isolation at database level

2. Memory Space Isolation​

Core data isolation boundary for organizing memories, conversations, and facts.

Hive ModeCollaboration Mode
SpacesOne shared spaceSeparate spaces per agent
Data AccessAll participants see all dataAgents only see their own
Cross-AccessAutomaticVia A2A or Context Chains
Use CasePersonal AI toolsEnterprise workflows

All AI tools share user's personal space:

const memorySpaceId = "user-123-personal";

// Cursor stores
await cortex.memory.remember({
memorySpaceId,
participantId: "cursor",
userMessage: "I prefer TypeScript",
agentResponse: "Noted!",
userId: "user-123",
userName: "Alice",
});

// Claude reads same space — sees Cursor's memories
const memories = await cortex.memory.search(memorySpaceId, "preferences");

3. User Data Isolation (GDPR)​

Right to Be Forgotten

Link data to users via userId to enable cascade deletion across ALL layers with a single API call.

// Link data to user
await cortex.memory.remember({
memorySpaceId: "support-bot-space",
userId: "user-123", // ← GDPR link
userMessage: "My account issue",
agentResponse: "Let me help",
userName: "Alice",
});

// One API call deletes from ALL layers
const result = await cortex.users.delete("user-123", {
cascade: true,
verify: true,
});

Deleted from: Conversations • Memories • Facts • Sessions • User Profile


4. Participant Tracking​

Not Isolation — Attribution

participantId tracks which tool stored data. It does NOT isolate data — all participants can still see all memories in the space.

// Track which tool stored what
await cortex.memory.remember({
memorySpaceId: "shared-space",
participantId: "cursor", // Attribution
userMessage: "User message",
agentResponse: "Response",
userId: "user-123",
userName: "Alice",
});

// Filter by participant for debugging
const cursorMemories = await cortex.memory.list({
memorySpaceId: "shared-space",
participantId: "cursor",
});

Isolation Matrix​

How each data type is scoped by isolation layer:

Data TypetenantIdmemorySpaceIduserIdparticipantId
Conversations✅✅OptionalOptional
Vector Memories✅✅OptionalOptional
Facts✅✅OptionalOptional
User Profiles✅SharedN/AN/A
Immutable Store✅SharedOptionalN/A
Mutable Store✅SharedOptionalN/A

Best Practices​

Always Use tenantId for SaaS
const cortex = new Cortex({
auth: createAuthContext({
tenantId: req.tenant.id, // REQUIRED for multi-tenant
userId: req.user.id,
}),
});
Always Set userId for GDPR
await cortex.memory.remember({
memorySpaceId: "bot-space",
userId: "user-123", // Required for cascade deletion
// ...
});
Use participantId in Hive Mode
await cortex.memory.remember({
memorySpaceId: "shared-space",
participantId: "my-bot", // Track attribution
// ...
});

Next Steps​