MindshineMindshineCortex enterprise architecture v1.0.898

Multi-tenancy

The concern: a platform-built product must serve many customers of the enterprise, not one. Build once and run many, deployment across client environments, tenant context propagation, tenant-specific credentials, database isolation, data partitioning, upgrade strategy, customer customisations, and whether one tenant's agent can ever touch another tenant's data.

The short answer

Two of the three usual models are supported by the platform as it stands; the third is the application's own design, with the platform supplying the pieces around it.

Model How it maps to the platform Standing
Dedicated deployment per tenant One project per tenant. A project is already the unit of tenancy and of delivery: its own configuration database, engine fork, target database, object-storage prefix, containers, and its own customer archive. Upgrades are a new export per project. In place
Shared application, shared infrastructure, tenant isolation One project. A tenant column in the governed data and one row filter bound to the caller's tenant attribute; the attribute comes from the membership or from the enterprise's entitlement API; the filter applies to every screen and every agent that reads the governed data, and fails closed. In place
Hybrid: shared services, tenant-specific data and security The application's own design (a connection per tenant, a database per tenant). The platform supplies the per-project environment, secrets and the tenant attribute in the verified subject; it does not manage a per-tenant connection map inside one application. Partial

The concerns, one by one

Concern Dedicated per tenant Shared with tenant policies Standing
Tenant context propagation The deployment is the tenant. The caller's verified subject (e-mail, organisation, role, membership attributes, entitlement-API attributes) is assembled server-side on every call, compiled into a signed grant with a five-minute expiry, and carried into every endpoint. An endpoint that forwards a call to an enterprise system can pass on the tenant attributes it can trust. Nothing is taken from the browser. In place
Tenant-specific credentials Per project, in the project's environment, rotatable. One set per project; a per-tenant credential inside one application is the application's concern. Partial in the shared model
Database isolation A target database per project. One database; isolation by row filter and column mask compiled into every query. A policy that names an attribute the caller lacks compiles to false, so an outage of the attribute source narrows access. In place
Data partitioning By project. By the tenant column; the pipeline's processing rules and the governed target enforce the column's presence and values. In place
Upgrade strategy Export per project; the runbook's rollback is the previous image tag plus per-consumer flags in the project's data. Projects that share a design can be prototyped from one base project (forks inherit from a prototype) so a fix to the base reaches every fork. One deployment, one upgrade; per-consumer flags in the data switch a change off for one tenant without redeploying. In place
Customer customisations A branch of the tenant's project: every branch has its own engine fork, so a customisation is developed and tested on the branch and merged or kept. Configuration rows per tenant (rules, reference lists) on the shared project; code-level customisation per tenant argues for the dedicated model. In place
Can one tenant's agent touch another tenant's data? No: an agent's tools are endpoints of its own project's fork, resolved by a server-side handle; another project is unreachable by construction. An agent reads governed data only through endpoints that carry the caller's grant, so the row filter bounds it exactly as it bounds a screen; the safeguards additionally refuse an answer no tool result backs. In place

Build once, run many

The same export serves both models. A dedicated deployment is the customer archive of that tenant's project. A shared deployment is one archive whose data carries the tenant column and whose delivery distributes the governance companion if the enterprise wants to edit policies off the platform. In both, the images are ordinary and the CI is generated, so "run many" is a matter of how many times the same images are deployed with different environment files.

Still to do

Gap Today Next step
A per-tenant connection map inside one application To do The platform injects one environment per project. Part of the enterprise profile: a tenant-resolution convention for the scaffold (a tenant-keyed secret set in the environment, resolved from the verified subject's tenant attribute) so the hybrid model is generated the same way every time rather than designed per application.
Tenant-level upgrade waves in the shared model Partial Per-consumer flags in the data exist as the business rollback layer. Nothing platform-side; the flags are the mechanism and the runbook documents them.
Fleet-wide upgrade of dedicated deployments Partial One export per project; a prototype chain propagates engine changes, not application-service trees. A base application-service tree shared through the prototype with per-fork overrides, for the dedicated model at scale.