Workspace isolation
Each workspace (tenant) is a dedicated Kubernetes namespace with its own Postgres, Convex backend, graph database for the Knowledge Graph, HashiCorp Vault, Zitadel identity plane, workflow file store, and persistent volumes. There is no shared database and no shared secret store across workspaces. The workspace namespace is the primary segregation boundary for data, credentials, and compute.
Isolation by layer
Section titled “Isolation by layer”| Layer | Isolation primitive | Per workspace? | Notes |
|---|---|---|---|
| Authorization | Namespace-scoped RBAC and service accounts | Yes | Workloads hold credentials for their own namespace only |
| Compute | Separate Deployments and Pods | Yes | Flow, the engines, and the backend services |
| Capacity | ResourceQuota and LimitRange per namespace | Yes | One workspace cannot exhaust the cluster on behalf of another |
| Data | Separate databases, graph store, and volumes | Yes | No shared database; volumes on encrypted cluster storage |
| Secrets | A separate Vault per workspace (KV fontana) |
Yes | Its own unseal material; no shared secrets across workspaces |
| Network | Default-deny NetworkPolicy per namespace | Yes | Every permitted route is declared, including egress to shared services |
| Identity | Self-hosted Zitadel per workspace | Yes | SSO, MFA, and RBAC scoped to the workspace |
| Ingress and TLS | A certificate per workspace hostname | Yes | Issued and renewed automatically by cert-manager |
| Runtime | Pod Security Standards on every workspace namespace | Yes | Applied by the charts, not left to convention |
| Cluster control layer and node kernel | Shared by default | Shared | Addressed below |
The cluster API is not exposed to the public internet. On a self-hosted Linux server the bootstrap firewall closes it and operators reach it over SSH; on AWS it is reached through your account’s authentication, by a role your deploy pipeline holds.
Soft and hard tenancy
Section titled “Soft and hard tenancy”Namespace separation delivers strong authorization, secret, network, and data isolation, and it is what the product enforces by default. Workspaces in one cluster still share a control layer and, unless you separate them, the nodes those pods run on. Fontana treats that as soft multi-tenancy and says so plainly.
Three levels are available, and they are all the same product:
| Level | What you change | What it buys |
|---|---|---|
| Shared cluster (default) | Nothing | Namespace-level isolation with the controls above |
| Dedicated node pool | A taint on the pool and a matching toleration for the workspace | No other workspace’s containers share the kernel |
| Dedicated cluster | The cluster named in tenants.<id>.cluster in fontana.yaml |
No shared control layer at all |
Because placement is a value in fontana.yaml rather than a different deployment product, moving a workspace up a level is a configuration change your change process can review, not a migration.
Platform namespace (shared, stateless)
Section titled “Platform namespace (shared, stateless)”A platform namespace runs shared stateless services: telemetry collection and operator dashboards, health probes, Docling document parsing, Kokoro text to speech, sandboxed code execution, and managed browser sessions. Which of these run in your cluster is declared in fontana.yaml; a service can also be consumed from a shared origin elsewhere, or turned off.
The platform namespace holds no workspace databases, Vault secrets, or workflow datasets. Workspace namespaces remain the data and secrets boundary.
Documented cross-tenant exceptions
Section titled “Documented cross-tenant exceptions”Some platform services are intentionally shared across workspaces, because running a model server per workspace costs far more memory than it earns. Fontana documents compensating controls for each:
| Service | Why shared | Primary controls |
|---|---|---|
| OpenSandbox MCP | One sandbox control layer per environment | Per-workspace bearer auth at the ingress, ownership enforced fail-closed by the proxy, digest-pinned base image, sandbox egress restricted to DNS |
| Docling | Stateless PDF and office parsing | Reachable only from workspace workloads that declare it, through an authenticated route; no durable cross-workspace store |
| Kokoro TTS | Shared speech synthesis | Reachable only from workspace workloads that declare it, through an authenticated route; declare it off in fontana.yaml if you do not use it |
| Managed browser sessions | One pooled browser service per environment | Session-scoped routing tokens, ephemeral session pods, and per-workspace egress rules |
These exceptions affect sandbox execution, in-flight document parsing, speech synthesis, and browser sessions only. They do not expose one workspace’s database, Vault, or workflow file store to another.
What this means for you
Section titled “What this means for you”- Blast radius: a compromise or misconfiguration in one workspace does not grant access to another workspace’s data plane through normal application paths.
- Evidence: segregation claims map to namespaces, network policies, Vault instances, and volume claims your reviewers can inspect during diligence, and
fontana soc2 snapshotcollects exactly those. - Graduation path: a workload that outgrows shared tenancy moves to a dedicated node pool or cluster without changing the product topology.
Related documentation
Section titled “Related documentation”- Deployment architecture: namespaces and the deploy model
- Secrets and encryption: per-workspace Vault and encrypted volumes
- Network and hardening: NetworkPolicy and TLS boundaries
- SOC 2 control summary: the tenant isolation row in the control matrix