Multi-Tenant Security Architecture
In-depth documentation of the security boundaries and tenant isolation in SveltyCMS.
On this page
SveltyCMS employs a rigorous “Defense in Depth” strategy for multi-tenant environments. This document outlines the architectural boundaries, isolation mechanisms, and security protocols that prevent cross-tenant data leakage and unauthorized access.
1. Core Isolation Principles (Vite+ Optimized)
SveltyCMS leverages the Vite+ middleware pipeline to enforce hard isolation at every request:
-
Middleware Gating: All requests pass through
handleSystemState,handleAuthentication, and the central API dispatcher. -
Tenant Context: The
tenantIdis resolved early and injected into the SvelteKitlocalsand GraphQL context. -
Hardened TBAC: The authentication hook (
handleAuthentication.ts) now dynamically fetches and populateslocals.rolesspecifically for the currenttenantIdcontext. This ensures that permissions granted in one tenant do not leak into another, even for the same user ID. -
Adapter Scoping: Every database operation is automatically scoped by the resolved
tenantId. -
🧪 Test Isolation (CI/CD): During automated testing, SveltyCMS uses the
x-test-worker-indexheader to dynamically route requests to isolated test database shards. This prevents race conditions and data leakage between parallel test workers in the CI pipeline.
2. API Security Boundaries
Both REST and GraphQL APIs are subject to tenant-level security checks:
- REST API Dispatcher: All routes under
/api/[...path]are centrally gated by a Fail-Closed security layer. It validates the required Permission ID against the user’slocals.rolesfor the current tenant before any adapter logic is executed. This pre-calculated route-level RBAC ensures that granular permissions never degrade database performance, making SveltyCMS immune to the SQL query bloat (e.g., 4000+ line injectedWHEREclauses) that commonly throttles multi-tenant competitors. - GraphQL Yoga: The schema is filtered based on the requester’s tenant permissions via the same robust TBAC layer.
- Performance Quotas: Rate limiting is applied per-tenant to prevent resource exhaustion.
3.1 GraphQL Schema Isolation & Protection
SveltyCMS prevents “Schema Leakage” by maintaining isolated YogaServer instances per tenant. This ensures that custom collections or fields defined by one tenant are never visible in the introspection query of another.
Furthermore, SveltyCMS protects the GraphQL interface with:
- AST Depth Limitation: Limits query depth to 7 via
createDepthLimitRulewired into the YogaonValidatehook, preventing nested relation Denial of Service (DoS) attacks. - Max Aliases Limitation: Limits query aliases to 15 via
createMaxAliasesRule, preventing alias-based batching DoS attacks. - Strict Tenant Enforcement: All GraphQL resolvers strictly check that the request’s context
tenantIdprecisely matches the entity’stenantId. Mismatches result in immediate query termination and an audit log event, unless triggered by a Super-Admin withbypassTenantIsolation. - Tenant-Scoped Rate Limits: Leverages Redis-backed rate-limiters scoped directly to
rate:tenant:${tenantId}:graphql:minuteensuring fair usage and protecting infrastructure from tenant-specific floods.
3.2 Real-Time Event Stream (SSE)
The Server-Sent Events (SSE) stream at /api/events performs real-time filtering. The eventBus wildcard listener verifies the payload.tenantId against the user’s locals.tenantId before enqueuing data to the stream controller.
3.3 Memory & Resource Hygiene
- Cleanup: SSE streams utilize the
cancel()method to clearsetIntervalheartbeats andeventBuslisteners, preventing memory leaks that could lead to Denial of Service (DoS). - Caching: Services like
AutomationServiceandWebhookServiceuse aMap<tenantId, Cache>structure to ensure that cached data is never shared across tenant boundaries. - Batch Operation Guard: The core
batch-module.ts(execute()) validates that all operations in a batch share the sametenantIdbefore coalescing. Mixed-tenant batches are rejected with a security error — preventing cross-tenant data leakage when multiple tenants share a database instance.
4. Data Portability & Encryption
4.1 Export Security
All data exports (Standard and Full) are tenant-scoped. Sensitive fields (API keys, secrets) are automatically detected via pattern matching and encrypted using AES-256-GCM with an Argon2 derived key before being included in the export JSON.
4.2 Import Integrity
The import system validates the scope of incoming settings. It dynamically looks up setting definitions to ensure that user-specific preferences are never imported into the global system scope, preventing database corruption.
5. Summary of Boundaries
| Boundary | Mechanism | Enforcement Point |
|---|---|---|
| Data | Explicit tenantId filters |
Database Adapters |
| CRUD Guard | Auto-inject + warn on missing tenantId |
crud-tenant-guard.ts |
| File Server | Tenant-scoped path ACL | /files/[...path]/+server.ts |
| Batch | Mixed-tenant rejection guard | batch-module.ts |
| Schema | Isolated Yoga Instances | GraphQL Handler |
| Real-Time | Payload Filtering | SSE Controller |
| Secrets | AES-256-GCM Encryption | Export Utility |
| UI/Prefs | Compound tenantId:userId keys |
Preferences API |
| Infrastructure | Super-Admin Restrictons | RBAC Middleware |
This architecture ensures that SveltyCMS remains secure, compliant, and performant even when hosting thousands of isolated customers on a single installation.