Skip to content

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)"]
Hold "Alt" / "Option" to enable pan & zoom

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.