IntegrationsBackendConvex
Tenant Scoping
Isolation strategy for multi-tenant MemberPulse on Convex
Even though MemberPulse is conceptually "single tenant per organization", this Convex implementation assumes a shared Convex deployment with strict isolation.
Rule: every tenant-owned record has clientId
All tables that store tenant data must include:
clientId: v.id("clients")
Examples: memberProfiles, events, courses, resources, supportTickets, orders, crmSyncRecords.
Authorization pattern
All queries/mutations must:
- derive the caller identity (auth)
- resolve which
clientIdthey are allowed to access - scope the query by
clientId(and/or validate the target document belongs toclientId)
Index requirements
Convex performance depends on indexes. Tenant-scoped lists should have at least:
by_clientIdby_clientId_statusby_clientId_createdAt
depending on the screen.
Preventing cross-tenant references
Any time you write a reference (e.g., memberProfileId, eventId), validate:
- referenced doc exists
- referenced doc has the same
clientId
This check belongs in server-side mutations.
Features
Tenant Scoping
Acceptance Criteria
Frontend
- Developer-facing configuration and usage is documented and internally consistent.
Backend / API
- Convex implementation matches the rules and contracts described on this page.
Permissions
- Tenant scoping and access controls are enforced as described.
Business Rules
- Domain rules/invariants are enforced as described.
Error Handling
- Access violations and validation failures produce deterministic errors.