Tenancy and scope¶
Target
This page describes intended behaviour or structure. No implementation is claimed unless a section is explicitly marked Current implementation or Evidence.
Rewritten 2026-10-09
Replaces architecture/multi-tenancy.md. The earlier page described a Factory-specific isolation chain as if implemented. The Factory now inherits the canonical ConnectSoft decisions ADR-0100 (multitenancy resolution) and ADR-0101 (Identity Platform) and adds only its scope hierarchy; see ADR-0015 (Proposed) and the review note on ADR-0011.
Inherited baseline (canonical, binding)¶
| Rule | Source |
|---|---|
Tenant tokens per layer: JWT claim tid; HTTP header X-Tenant-Id untrusted until the gateway validates it; gRPC and messaging metadata tenant-id (including Orleans call context) |
ADR-0100 |
Resolution order: static configuration → JWT tid → HTTP hints → transport extraction; conflicting evidence fails closed in strict mode |
ADR-0100 |
| Installation modes: SharedDb, DatabasePerTenant, ResidencySilo, DedicatedSingleTenant | ADR-0100 |
| In shared-DB mode no load by key without a tenant predicate (NHibernate filters and query specifications) | ADR-0100 |
| Authorization Server is the only internal token issuer; Identity Service owns accounts, credentials, MFA, memberships; gateway validates tokens and route policy; backends enforce domain and tenant authorization; Blazor Shell owns frontend auth state; APIs accept access tokens, not ID tokens | ADR-0101 |
The former "premium database-per-tenant tier" is the canonical DatabasePerTenant mode; ResidencySilo and DedicatedSingleTenant are equally supported Factory modes.
Factory scope hierarchy (added)¶
flowchart TB
Org["Organization / tenant (tid)"] --> WS["Workspace / project"]
WS --> Env["Environment"]
Env --> Run["Run"]
Run --> Step["Step / attempt"]
WS --> Src["Source scope<br/>repositories · documents · tools permitted"]
Org --> Users["Memberships (Identity Service)"]
Every Factory contract carries the trusted tenant id and project id derived from the authenticated context: run request, execution snapshot, tool invocation, retrieval request, artifact reference, usage record, lifecycle event. Prompt text and caller-controlled headers never supply scope. Selecting a tenant or project in the console grants nothing; backends enforce every read and write, including retrieval before top-k selection (ADR-0013), tool execution, artifact access and projections.
Isolation layers (target)¶
| Layer | Mechanism |
|---|---|
| Identity | tid claim resolved into the ambient tenant context by ConnectSoft.Extensions.Saas.* |
| Application | Every command and query asserts tenant and project scope |
| Data | Tenant predicate on every shared-DB query; mode-specific stores otherwise |
| Messaging | Envelope carries tenant and project (ADR-0014); subscriptions filter by tenant |
| Knowledge | Scope enforced by the retrieval backend; cross-tenant knowledge only through explicitly published, classified assets |
| Secrets | Per-tenant secret references via the secret broker; never shared plaintext |
| Runtime | Generated products isolate their own tenants; Factory tenants and product tenants are distinct identities |
Roles and delegation (decided 2026-10-09)¶
Fixed by ADR-0015 point 5–6 (user decision D18). The Factory does not issue tokens or manage accounts itself; roles are claims from the Authorization Server, memberships live in the Identity Service, and every backend enforces them.
| Role | Scope of assignment | May do |
|---|---|---|
| Requester | project | Submit runs within project scope and budget; inspect own runs, artifacts and usage; cancel own runs |
| Reviewer | project | Decide approvals (accept, reject, request changes) on an exact run, artifact or action version, within authority and expiry; never on a run they requested |
| Asset maintainer | project | Author agents, skills, tool bindings and workflows; run evaluations; publish a release only with evaluation evidence attached |
| Operator | project | Retry, resume, cancel and replay runs; manage workers and sandboxes within scope; no approval authority |
| Workspace admin | project | Everything above for the project; manage membership and role assignments; set project policy that is stricter than platform policy, never looser; may decide approvals on runs they did not request |
| Platform admin | tenant | Everything; owns global policy, model profiles, provider connections and tenant-wide settings; may break glass on an approval with an audited reason |
| Observer | project or tenant | Read-only access to runs, artifacts, decisions, usage and audit for auditors and stakeholders; no commands |
- Roles are issued as claims by the Authorization Server (canonical ADR-0101) and enforced by every backend per request; menu visibility in the Studio grants nothing.
- Assignment is per project; Platform admin is the only tenant-wide role. Membership itself is per tenant (Identity Service).
- Separation of duties: the requester of a run cannot approve any proposal from that run, even if they also hold Reviewer or Workspace admin.
- Delegation: a role holder may delegate the same or a lesser role to another member for a bounded period; every delegation is recorded with grantor, grantee, scope, expiry and reason, is revocable at any time, and expires automatically. A delegated Reviewer inherits the separation-of-duties rule.
- Policy layering: platform policy is the ceiling; a project policy may tighten it (more approval gates, lower budgets, fewer tools) and may never loosen it.
No role model is implemented in the Factory libraries today; the Identity and Authorization Server templates provide roles and claims, and the mapping above is the Target binding.
Editions, quotas and metering¶
Commercial tenancy (tenants, editions, subscriptions, billing, usage metering, feature flags) is provided by the SaaS templates and ConnectSoft.Extensions.Saas.* libraries (BC-33). Quota enforcement is part of usage accounting (BC-05); entitlement definitions come from BC-33. Whether the first stage needs customer billing or only internal budget controls is open question Q-15.
Generated products¶
Generated SaaS inherits the same canonical model through the ConnectSoft.Saas.* templates, with its own tenants, stores and audience. Any mapping between a Factory customer and a product tenant is an explicit contract of the generation recipe.
Current implementation¶
ConnectSoft.Extensions.Saas.*(abstractions, AspNetCore, NHibernate, Orleans, options, testing) and the Identity / Authorization Server templates exist and run in DerechHaLev.- Factory libraries carry no tenant or project identity (
AgentTraceContext,AgentEventEnvelope, retrieval options, tool calls). The isolation layers above are therefore Target for the Factory.
Related¶
- Control plane · Security by plane · Knowledge & Memory
- SaaS platform foundations · Generated SaaS pack
- Canonical: ConnectSoft.Documentation
decisions/adr/adr-0100-connectsoft-saas-multitenancy-resolution.md,adr-0101-connectsoft-identity-platform.md