Skip to main content
Version: Next

Tenant Management

Tenant Management is the authority for canonical organizations, owners, memberships, invitations, service grants and lifecycle. Its API and UI coordinate SSO Bridge, Wallet and Control Plane through authenticated provisioning APIs. Wallet keeps its keys and DIDs; Control Plane keeps protocol and domain state; SSO keeps login identities and OAuth state. The manager never writes their databases.

One organization has one Wallet and one Control Plane participant binding. An operator profile may also include other registered services. Every service in a selected profile must become ready before activation. Independent participant identities within one organization are outside this release.

Availability model​

Tenant Management is a runtime dependency of every managed service. Snapshots expire 50 seconds after creation; the manager renews them after about 20 seconds. A manager, database or delivery outage can therefore stop protected operations within 50 seconds of the last snapshot, including background jobs and subscriptions. Public Wallet DID and credential-status reads remain available. Use manager replicas with shared PostgreSQL and stable secrets, and monitor delivery age and retries before enabling managed access.

Snapshots go to each bound service and to SSO. Each tenant/service pair needs one delivery to its consumer and one to SSO per renewal. Delivery load grows with the number of bound services and organizations.

Concepts​

ConceptMeaning
OrganizationThe user-facing name for a canonical tenant with one immutable UUID.
Owner, administrator, memberOrganization roles. Exactly one active owner is required. These roles do not imply service access.
Service grantA principal's explicit permissions for one registered service instance.
ProfileOperator configuration that selects services, provisioning settings and grant ceilings.
OperationDurable provisioning or mutation work with receipts, retries and a visible state.
RevisionA counter used to reject stale updates. Authorization and configuration have separate revisions.

Creating an organization​

Sign in to the manager with a global SSO identity. A registered platform administrator can provision an organization for an existing or new customer account. The selected customer becomes its owner; the provisioning administrator is recorded as the actor and receives no implicit tenant membership or service access. Platform administrators can inspect and administer all organizations. Organization owners and administrators see only the organizations they administer. Ordinary members use the services directly and can accept an invitation without access to the manager's administrative views.

Self-service creation is disabled by default. An operator can register exact issuer/subject pairs in creators or explicitly enable selfServiceCreation for an exploratory deployment. Self-service creation makes the caller the owner. Creation reserves an immutable canonical UUID, URL name, owner and durable operation in one transaction. Repeating the same request with the same Idempotency-Key resumes that operation; different content with that key conflicts.

POST /tenants returns 202 Accepted with tenantId, operationId and state. The worker configures SSO and a tenant-bound workload, provisions Wallet, uses its actual DID/endpoints to persist Control Plane IAM, delivers paired authorization snapshots and activates the required services. Poll GET /operations/:id and GET /tenants/:id for progress and non-secret outputs. GET /tenants/:id/operations returns the latest 20 operations after a reload, including lifecycle and credential changes. GET /tenants returns lightweight navigation entries; fetch full details only for the selected tenant. Transient failures retry automatically with bounded backoff. Invalid contracts or rejected destination credentials stop with a sanitized error code. After an operator corrects the destination configuration, an owner or administrator can retry the current failed operation with POST /operations/:id/retry. A newer tenant revision supersedes old work. Wallet success followed by Control Plane failure resumes using the same Wallet receipt and key material.

The UI supports rename, membership revocation/restoration, invitation creation and acceptance, invitation revocation, ownership transfer, bounded service grants, suspension/resume, credential rotation and deletion. Invitations use explicit possession proof and optional exact principal restrictions. Email matching never establishes membership. Organization roles and service permissions are separate: an administrator cannot delegate service permissions they do not hold. Exactly one active owner is required; transfer is atomic.

Replacing or clearing a service grant requires authority over both its existing permissions and its requested replacement. An administrator with limited Wallet permissions cannot remove the owner's broader Wallet grant. Revoking or reactivating a member also clears their service grants and requires authority over those existing permissions for every bound service, unless the caller is a platform administrator. A caller can reduce their own grant, including to an empty set, but their organization role does not restore the lost permissions. Ownership transfer also leaves service grants unchanged. An explicitly registered platform administrator can restore the current owner's operator-profile baseline through POST /tenants/:id/grants/recover-owner with the current revision. Recovery preserves reviewed imported permissions and grants for other principals. See recovery policy.

Login accounts and SSO administration​

Signing out clears the manager's session. Its signed-out screen starts the next sign-in with prompt=select_account, so users can choose a different account. The regular sign-in screen also offers Use another account. The shared SSO session remains available to other services.

Tenant creation provisions the canonical organization in the registered SSO Bridge as well as Wallet and Control Plane. SSO uses that organization's membership and per-service grant snapshots when issuing tenant-bound tokens. Wallet and Control Plane request their service audience on the first login; a link from the manager also supplies the canonical tenant ID. Opening a service without a tenant link lets the user select an eligible organization at SSO.

Human login accounts remain in the shared SSO identity directory. Platform provisioning can create the initial owner's account or reuse a verified existing account. Organization administrators can add a new account or an exact existing account and assign initial service permissions within their delegation ceiling. The same identity can belong to multiple organizations. Removing a membership does not delete or reset the login account.

New users choose their own password through a single-use first-login setup link. When SMTP is configured, SSO delivers that link only by email. Administrators receive delivery confirmation and expiry, without the URL. Without SMTP, an authorized administrator can issue a link and share it directly. URLs are returned only by explicit setup-link actions without email delivery and never appear in public operation outputs. Reissuing a link invalidates the previous link. An organization administrator can issue a link only for an uninitialized account provisioned through that organization. Established account credentials and global account administration remain outside organization authority.

The manager shows usernames returned by the registered SSO provider for the organization's existing members. Names are display metadata; authorization and mutations always use the exact issuer/subject pair. If the provider is unavailable or cannot resolve a principal, the account ID remains visible and administration remains available.

Authorization and browser sessions​

For each canonical tenant and target instance, the manager delivers the same complete snapshot to that target and SSO. Snapshots contain only that target's grants and local principal mappings. Authorization revisions are independent of configuration revisions; membership changes do not regenerate keys or workloads.

Wallet and Control Plane retain encrypted access/refresh tokens on their servers, bound to login identity, client, canonical tenant and audience. A global login or ID token alone cannot authorize managed resources. Each cookie request validates its selected token and current projection with the same checks as a bearer request. Refreshes are serialized through database leases across replicas; an interrupted rotation requires login instead of replaying a possibly used refresh token. Logout, account changes and session expiry invalidate bindings. Tokens are absent from browser storage and user-info responses.

Server-side refresh tokens let background polling and concurrent requests renew authorization without navigating away from an edit. A database lease permits one refresh across replicas. Other requests wait for at most one second, then receive 503 and may retry. An expired lease deletes the token and requires login because the previous process may have consumed the rotating refresh token. Refresh responses must retain the same identity, tenant and audience and may only narrow scope and permissions.

Manager organization and invitation links use hash routes. OAuth return_to preserves the full path, query and hash through the callback, so the manager does not store a second copy of the requested organization or invitation. A user who opens a separate first-login setup link can return through the original invitation link after choosing their password.

Cookie mutations require an explicit request marker in addition to SameSite=Lax. The manager UI sends X-Tenant-Management: 1; shared Wallet and Control Plane UI requests send X-TSG-Request: 1. Bearer API requests do not need the cookie marker. Shared settings controllers declare platform authorization explicitly and require an exact human platformPrincipals match, independently of organization roles.

Tenant selection is explicit through a local tenant path or X-Tenant-Id. Browser selection is stored per tab; switching obtains the chosen tenant/audience grant, clears data and discards late responses. SDK callers must supply separate tenant/audience credentials for Control Plane and Wallet.

Wallet and Control Plane start login automatically when needed and preserve the requested page. SSO validates an organization supplied by a service link, automatically selects a sole eligible organization, or restores a valid previous choice for the current account and application. When several organizations remain without a preference, it shows one chooser. A valid session automatically returns to an explicitly trusted first-party browser application. Configure those client IDs in SSO tenancy.trustedBrowserClients; a shared registration alone does not permit silent authorization. An invalid explicit organization selection fails instead of silently opening another organization.

Lifecycle and retention​

Suspension and deletion revoke access through snapshots and consumer lifecycle receipts. In-flight work is not transactionally cancelled across services; fresh authorization checks deny subsequent protected steps. There is no destructive cross-service purge or automatic physical deletion. Canonical/local mappings and URL names remain reserved after deletion. Old configuration cannot resurrect a tombstone. Published DID documents, credential-status information, keys, credentials, catalogs and protocol/audit history remain stored for verification and operator retention policy. Wallet's public DID/status reads remain available; new protected credential/protocol operations fail closed. Take backups before any later operator-controlled purge. If deletion is requested during initial provisioning, the worker finishes required identity setup while access stays inactive, then commits consumer tombstones.

Internals​

SSO account bootstrap requests remain pending only until SSO acknowledges them. The worker then removes them from the retry queue; organization audit records remain stored separately.

Membership, ownership and grant operations deliver authorization snapshots only. Rename and credential rotation configure services and deliver snapshots; rename does not advance the authorization revision. Lifecycle operations deliver snapshots and lifecycle requests. Creation and import run the full setup path. A successor operation also completes unfinished configuration or lifecycle work since the last successful revision, including deletion during setup.

The manager stores each organization's memberships, grants, mappings and bindings as one JSON aggregate with revision checks. This is intended for tens to hundreds of organizations. Listing filters visibility in memory; concurrent edits to the same organization return 409 even when they affect different members. PostgreSQL stores these JSON fields as text, without indexes for membership queries.

The persistent outbox records each destination's acknowledgement. Workers use revision checks and database leases. Each destination has two concurrent delivery slots, and each worker tick selects at most 100 pending rows per destination. Authorization has separate request capacity from configuration, so a slow service does not occupy another service's renewal slots. Snapshots renew after 20 seconds with a 50-second deadline measured before the authority transaction. Delivery waits and replays never extend that timestamp. Consumers reject reordered revisions and conflicting content at the same revision. Divergent delivery denies requests on revision mismatch until the matching snapshot arrives.

The shared contract names the freshness and renewal intervals. Consumers allow 10 seconds of clock skew when checking whether an incoming deadline is implausibly far in the future; they still expire the stored snapshot at its exact validUntil. Keep clocks synchronized across manager, SSO and consumers. The delivery lease is 30 seconds and the operation lease is 90 seconds. These leases prevent duplicate work ownership; they do not extend authorization.

SQLite remains supported for local experiments and a single-host deployment. Its transaction queue serializes transactions in that process. Even a single-statement write to session, token or provisioning state must use databaseTransaction, because an unrelated rollback on the shared SQLite connection could otherwise undo it. Nested writes reuse the current transaction. Keep network calls outside these transactions. Do not share a SQLite file across hosts. Replicated deployments require PostgreSQL.

See deployment and migration, configuration reference, OpenAPI and shared tenancy contracts.