Multi-Tenant Isolation
STOA implements a hard multi-tenancy model where each tenant is fully isolated across infrastructure, identity, data, and networking layers. This enables a single STOA deployment to serve multiple organizations without cross-tenant data leakage.
Tenant Data Modelβ
Each tenant in STOA has the following properties:
| Field | Type | Description |
|---|---|---|
id | string | Slug identifier (e.g., oasis, acme-corp) β immutable |
name | string | Display name (e.g., "OASIS Gunters") |
description | string | Optional description |
status | enum | active, suspended, archived |
settings | JSON | Quotas, feature flags, custom config |
created_at | timestamp | Creation date |
Tenant Status Lifecycleβ
- Active β Full access to all platform features
- Suspended β Read-only access, no API calls, no deployments. Used for billing issues or compliance holds.
- Archived β Data retained for audit, no access. Pending deletion per retention policy.
Five Isolation Layersβ
1. Kubernetes Namespace Isolationβ
Each tenant operates in a dedicated namespace with labels for policy enforcement:
apiVersion: v1
kind: Namespace
metadata:
name: tenant-acme
labels:
stoa.io/tenant-id: acme
stoa.io/tier: enterprise
pod-security.kubernetes.io/enforce: restricted
Resource quotas prevent a single tenant from consuming cluster resources:
apiVersion: v1
kind: ResourceQuota
metadata:
name: tenant-quota
namespace: tenant-acme
spec:
hard:
requests.cpu: "10"
requests.memory: 20Gi
persistentvolumeclaims: "5"
services.loadbalancers: "2"
2. Network Isolationβ
Network policies prevent cross-tenant communication at the CNI level:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: tenant-isolation
namespace: tenant-acme
spec:
podSelector: {}
policyTypes: [Ingress, Egress]
ingress:
- from:
- namespaceSelector:
matchLabels:
stoa.io/tenant-id: acme
egress:
- to:
- namespaceSelector:
matchLabels:
stoa.io/tenant-id: acme
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: stoa-system
Tenants can communicate with their own namespace and the shared stoa-system namespace (for the Control Plane API and Gateway), but never with other tenants.
3. Gateway Isolationβ
The STOA Gateway enforces tenant boundaries at the API layer:
- Tenant-scoped routing β Each API is scoped to a tenant ID
- Separate rate limits β Per-tenant quota enforcement
- Independent policies β OPA policies evaluate tenant context
- Tenant-specific certificates β mTLS certificates scoped per tenant
In multi-gateway deployments, each gateway adapter (Kong, Gravitee, webMethods, STOA) maintains tenant isolation through its native mechanisms.
4. Authentication Isolationβ
Keycloak multi-realm architecture provides identity isolation:
- One realm per tenant β Isolated user stores, separate credentials
- Isolated client configurations β Each tenant has its own OIDC clients
- Independent token validation β Tokens from one realm are invalid in another
- Tenant-scoped roles β
tenant-admincan only manage their own tenant
5. Data Isolationβ
- Schema-per-tenant β Database schemas isolated per tenant
- Encrypted at rest β All tenant data encrypted (AES-256)
- Separate backup policies β Per-tenant backup schedules
- Audit logging β Every data access logged with tenant context
RBAC and Tenant Scopingβ
STOA's RBAC model combines platform-wide and tenant-scoped roles:
| Role | Scope | Permissions |
|---|---|---|
cpi-admin | Platform | Full access to all tenants, all operations |
tenant-admin | Tenant | Full access to own tenant only |
devops | Tenant | Deploy and promote within own tenant |
viewer | Tenant | Read-only access to own tenant |
Key behaviors:
- A
tenant-adminfor tenantacmecannot see tenantglobexresources - A
viewercan browse APIs and tools but cannot invoke, create, or modify - A
cpi-adminsees all tenants and can perform cross-tenant operations - Environment mode (dev/staging/prod) further restricts operations β production is read-only by default
Tenant Settingsβ
The settings JSON field on each tenant allows per-tenant configuration:
{
"quotas": {
"max_apis": 50,
"max_subscriptions": 200,
"max_rate_limit": 10000
},
"features": {
"mcp_enabled": true,
"shadow_mode": false,
"advanced_analytics": true
},
"notifications": {
"webhook_url": "https://hooks.acme.com/stoa",
"email_alerts": true
}
}
Tenant Tiersβ
| Tier | Resources | Features | SLA |
|---|---|---|---|
| Community | Limited | Core APIs, basic MCP | Best effort |
| Starter | Moderate | APIs + MCP tools, portal | 99% |
| Business | High | Full platform, multi-gateway | Per agreement |
| Enterprise | Custom | White-label, dedicated support | Custom SLA |
Per-Tenant Observabilityβ
Every metric in STOA is labeled with the tenant ID, enabling per-tenant dashboards:
- API request rates β
stoa_api_requests_total{tenant="acme"} - Error rates β
stoa_api_errors_total{tenant="acme"} - Latency percentiles β
stoa_api_duration_seconds{tenant="acme"} - Resource utilization β CPU, memory, storage per namespace
- Cost attribution β Per-tenant resource consumption for billing
Grafana dashboards can be filtered by tenant for tenant-admins, or viewed across all tenants for platform admins.
Relatedβ
- Architecture Overview β System architecture
- MCP Gateway β Gateway concepts
- Subscriptions Guide β API subscription management
- ADR-022: UAC Tenant Architecture β Architecture decision