Skip to main content
Version: Next

Tenant Management configuration

The manager requires a stable SESSION_SECRET and TENANCY_SECRET with at least 32 characters, shared by its replicas. Inject them from Kubernetes Secrets. Never include production credentials in a ConfigMap. Register the exact manager service principal independently at SSO, Wallet and Control Plane before enabling provisioning.

The manager uses tenancy.mode: authority for global identity login. Managed consumers use tenancy.mode: managed. Register both the browser client and the separate provisioning service client before starting tenant creation.

Authorization deadlines use shared contract constants: 50 seconds of freshness and renewal after 20 seconds. Consumers allow 10 seconds of clock skew when accepting a future deadline, then check the stored validUntil without extending it. These values are not independent deployment settings. See the availability model before enabling managed mode.

For unattended local startup, initTenants declares canonical UUIDs, names, slugs, profiles and owner principals from SSO initUsers. The manager queues normal provisioning locally and retries while receiving services start. Optional serviceGrants give explicitly configured SSO workload clients access to selected services without making them human members. SSO workload clients remain bound to the exact canonical UUID and request a separate audience for each service.

Optional members entries declare an existing SSO principal, an admin or member role, and grants containing service IDs and permissions. Each member is applied once per principal, independently of the tenant seed. New members can be added to existing initialized tenants without changing ownership or resetting state. Subsequent membership and grant edits survive restarts; changing an already applied member entry fails with an idempotency conflict.

Initialization creates defaults once. Restarts preserve later membership, grant and lifecycle edits. Removing an entry does not delete a tenant. Changed entries or conflicting IDs/slugs fail; use the management API for later changes.

KeyRequiredTypeDescriptionDefault
InitialTenantConfig
initTenantsInitialTenantConfig[]Create these tenants once at startup through managed provisioning. Restarts preserve memberships, grants and lifecycle changes; removal does not delete tenants[]
initTenants[].tenantIdYesStringExplicit canonical UUID, also used in worker execution scopes
PrincipalDto
initTenants[].ownerYesPrincipalDtoExisting SSO login principal, for example from SSO initUsers
initTenants[].owner.issuerYesStringRegistered SSO issuer URL
initTenants[].owner.subjectYesStringStable SSO user ID or workload client ID
InitialMemberConfig
initTenants[].membersInitialMemberConfig[]Additional members applied once per principal, including to existing initialized tenants; restarts preserve later edits
PrincipalDto
initTenants[].members[].principalYesPrincipalDtoExisting SSO login principal
initTenants[].members[].principal.issuerYesStringRegistered SSO issuer URL
initTenants[].members[].principal.subjectYesStringStable SSO user ID or workload client ID
initTenants[].members[].roleYes"admin" | "member"Organization role; ownership stays with the configured owner
ManagedAccountGrantDto
initTenants[].members[].grantsYesManagedAccountGrantDto[]Initial service permissions for this member
initTenants[].members[].grants[].serviceInstanceIdYesStringReceiving service selected by the tenant profile
initTenants[].members[].grants[].permissionsYesStringInitial permissions for this member and service
InitialServiceGrantConfig
initTenants[].serviceGrantsInitialServiceGrantConfig[]Additional initial service grants, for example tenant-bound workload clients registered in SSO initClients
PrincipalDto
initTenants[].serviceGrants[].principalYesPrincipalDtoExact SSO workload issuer and subject
initTenants[].serviceGrants[].principal.issuerYesStringRegistered SSO issuer URL
initTenants[].serviceGrants[].principal.subjectYesStringStable SSO user ID or workload client ID
initTenants[].serviceGrants[].serviceInstanceIdYesStringReceiving service selected by the tenant profile
initTenants[].serviceGrants[].permissionsYesStringInitial permissions for this principal and service
initTenants[].nameYesStringOrganization display name
initTenants[].slugYesStringImmutable URL slug
initTenants[].profileYesStringOperator-selected service profile
ExistingTenantServiceGrantConfig
initServiceGrantsExistingTenantServiceGrantConfig[]Apply explicit workload grants once to existing tenants. Does not create human memberships; restarts preserve later revocation. Register tenant-bound workload clients in SSO separately[]
initServiceGrants[].tenantIdYesStringCanonical UUID of an existing managed tenant
PrincipalDto
initServiceGrants[].principalYesPrincipalDtoExact SSO workload issuer and subject
initServiceGrants[].principal.issuerYesStringRegistered SSO issuer URL
initServiceGrants[].principal.subjectYesStringStable SSO user ID or workload client ID
initServiceGrants[].serviceInstanceIdYesStringReceiving service selected by the tenant profile
initServiceGrants[].permissionsYesStringInitial permissions for this principal and service
SharedDataPlaneConfig
sharedDataPlanesSharedDataPlaneConfig[]Shared worker audiences available to operator-selected profiles[]
sharedDataPlanes[].serviceInstanceIdYesStringUnique service instance ID referenced by profiles
sharedDataPlanes[].dataplaneIdYesStringWorker signaling audience; must match the worker's controlPlane.dataplaneId and an SSO managedSignalingTargets audience
AuditModuleConfig
auditAuditModuleConfigAudit logging configuration
audit.enabledBooleanEnable audit loggingtrue
audit.minSeverity"debug" | "info" | "warning" | "error" | "critical"Minimum severity level to log"info"
audit.logDeniedBooleanAlways log denied access attempts regardless of action typetrue
audit.logDelegatedBooleanLog delegated access attempts when enabled, while still respecting action-specific success filterstrue
audit.logMutationsBooleanLog successful mutation actions (create, update, delete, manage)true
audit.logExecuteBooleanLog successful execute actionsfalse
audit.logReadsBooleanLog successful read actions — disabled by default as reads are frequent and rarely relevant for auditingfalse
audit.sensitiveResourcesArrayResources logged regardless of minimum severity, while still respecting action-specific success filters["w.key","w.credential","sso.user"]
AuditHandlersConfig
audit.handlersAuditHandlersConfigHandler configuration
audit.handlers.consoleBooleanEnable console audit log handlerfalse
audit.handlers.databaseBooleanEnable database audit log handlertrue
audit.handlers.otlpBooleanEnable OTLP audit log handlerfalse
OtlpAuditHandlerConfig
audit.otlpOtlpAuditHandlerConfigOTLP audit log handler configuration
audit.otlp.urlStringOTLP HTTP logs endpoint URL"http://localhost:4318/v1/logs"
audit.otlp.headersObjectAdditional HTTP headers to include in OTLP requests
audit.otlp.timeoutMillisNumberOTLP export timeout in milliseconds5000
audit.otlp.concurrencyLimitNumberMaximum number of concurrent OTLP export requests1
audit.otlp.serviceNameStringService name included on OTLP log attributes"tsg-dsp-api"
audit.otlp.serviceVersionStringOptional service version included on OTLP log attributes
DatabaseConfig
dbYesDatabaseConfigDatabase configuration
db.retryAttemptsNumberConnection attempts during application startup, three seconds apart10
db.typeYes"sqlite" | "postgres"Type of database
db.databaseYesStringName of the database
db.synchronizeBooleanSynchronize database schemafalse
db{type=sqlite}YesSQLiteConfigDatabase configuration
db{type=sqlite}.retryAttemptsNumberConnection attempts during application startup, three seconds apart10
db{type=sqlite}.type"sqlite" | "postgres"Type of database"sqlite"
db{type=sqlite}.databaseYesStringName of the database
db{type=sqlite}.synchronizeBooleanSynchronize database schemafalse
db{type=postgres}YesPostgresConfigDatabase configuration
db{type=postgres}.hostYesStringHost of the database
db{type=postgres}.portYesNumberPort of the database
db{type=postgres}.usernameYesStringUsername of the database
db{type=postgres}.passwordYesStringPassword of the database
db{type=postgres}.sslObjectSSL configuration of the databasefalse
db{type=postgres}.retryAttemptsNumberConnection attempts during application startup, three seconds apart10
db{type=postgres}.type"sqlite" | "postgres"Type of database"postgres"
db{type=postgres}.databaseYesStringName of the database
db{type=postgres}.synchronizeBooleanSynchronize database schemafalse
ServerConfig
serverYesServerConfigServer configuration
server.listenStringIP address the server listens on"0.0.0.0"
server.portNumberPort the server listens on3000
server.publicDomainStringPublic domain of the server"localhost"
server.publicAddressStringPublic address of the server"http://localhost:3000"
server.subPathStringSub path of the server
AuthConfig
authYesAuthConfigManagement authentication configuration
auth.signalingIdStringReceiving plane identity for signaling tokens. Defaults to clientId.
auth.expectedIssuerStringExpected API token issuer; defaults to the discovered OpenID issuer
auth.expectedAudienceStringExpected API token audience; defaults to clientId.
auth.enabledBooleanEnable authenticationtrue
auth.openIdConfigurationURLStringOpenID configuration URL
auth.callbackURLURLCallback URL the auth service will redirect users
auth.redirectURLURLRedirect URL to UI after login/logout
auth.clientIdStringClient ID
auth.clientSecretStringClient secret (required for client_secret_post authentication)
auth.tokenEndpointAuthMethod"client_secret_post" | "private_key_jwt"Token endpoint authentication method: client_secret_post (default) or private_key_jwt"client_secret_post"
auth.privateKeyJwkObjectPrivate key in JWK format for private_key_jwt authentication. Alternative to privateKeyJwkFile.
auth.privateKeyJwkFileStringPath to file containing private key JWK for private_key_jwt authentication. Alternative to privateKeyJwk.
auth.permissionPathStringJSON path to extract permissions from the token"$.permissions[*]"
ProvisioningClientConfig
provisioningYesProvisioningClientConfigIndependently bootstrapped operator client; separate from the public browser login client
provisioning.clientIdYesStringOAuth client ID used for provisioning calls
provisioning.clientSecretStringClient secret, for client_secret_post
provisioning.tokenEndpointAuthMethod"client_secret_post" | "private_key_jwt"Token endpoint authentication method"client_secret_post"
provisioning.privateKeyJwkObjectPrivate JWK for private_key_jwt
provisioning.privateKeyJwkFileStringPath to a private JWK file for private_key_jwt
ManagedTenancyConfig
tenancyManagedTenancyConfigTenancy authority configuration
tenancy.mode"managed" | "authority"Tenancy mode: managed receives Tenant Management state; authority runs Tenant Management with global identity login. Both modes require strict OAuth validation and stable session secrets."managed"
tenancy.serviceInstanceIdStringOperator-registered receiving service instance""
tenancy.managementUrlStringTenant Management UI URL
tenancy.provisioningIdentitiesObjectExact manager issuer/subject, audience and allowed provisioning operations[]
tenancy.platformPrincipalsObjectExact human principals permitted to change shared process settings; organization roles grant no platform authority[]
RegisteredService
ssoYesRegisteredServiceOperator-controlled issuer and provisioning destinations; never supplied by tenant callers
sso.serviceInstanceIdYesStringUnique service instance ID referenced by profiles and grants
sso.audienceYesStringUnique OAuth audience of the service
sso.apiUrlYesURLBase URL of the service's provisioning API
sso.uiUrlURLPublic browser entry point; omit for services without a user interface
sso.kindYes"sso" | "wallet" | "control-plane" | "generic"Service kind, which selects its provisioning contract
sso.outputFieldsStringProvisioning outputs exposed to the tenant; only used for generic services[]
sso.configurationObjectStatic configuration sent to generic services on provisioning{}
RegisteredService
servicesRegisteredService[]Provisioned services that profiles can select[]
services[].serviceInstanceIdYesStringUnique service instance ID referenced by profiles and grants
services[].audienceYesStringUnique OAuth audience of the service
services[].apiUrlYesURLBase URL of the service's provisioning API
services[].uiUrlURLPublic browser entry point; omit for services without a user interface
services[].kindYes"sso" | "wallet" | "control-plane" | "generic"Service kind, which selects its provisioning contract
services[].outputFieldsStringProvisioning outputs exposed to the tenant; only used for generic services[]
services[].configurationObjectStatic configuration sent to generic services on provisioning{}
ConnectedApplicationConfig
applicationsConnectedApplicationConfig[]Connected use-case app links. Their own APIs still enforce access; these are not provisioning targets[]
applications[].idYesStringundefined
applications[].nameYesStringundefined
applications[].uiUrlYesURLundefined
applications[].serviceInstanceIdYesStringManaged service whose tenant permissions authorize the application
applications[].profilesYesStringTenant profiles where this application is offered
applications[].permissionsYesStringAt least one of these service permissions is needed to open the app
profilesObjectOperator-owned service/profile and grant ceilings{}
creatorsObjectExact human principals permitted to create tenants for themselves[]
selfServiceCreationBooleanAllow authenticated humans to create tenants with themselves as ownerfalse
platformPrincipalsObjectExact human platform administrators permitted to provision customer tenants, administer organizations, import tenants and recover owner service access[]