Super-Admin Tenant Management
OP-069 adds the bootstrap workflow that makes the authenticated console usable for demos and pilots after Keycloak login is available.
What Changed
- Added system-admin-only APIs:
GET /api/v1/admin/tenantsPOST /api/v1/admin/tenantsPOST /api/v1/admin/tenants/{tenant_id}/users
- Added a Settings-page tenant onboarding panel that is rendered only for a
backend-session-derived
system_adminrole. - Added Postgres tenant bootstrap helpers that keep normal table RLS intact while allowing narrow cross-tenant platform administration.
- Added Keycloak Admin API bootstrap for tenant users. OP-071 makes this
mandatory for tenant-facing roles: the backend creates or updates the
Keycloak user, sets
tenant_id,oneprotect_role, andoneprotect_user_idattributes, verifies the Keycloak state, and commits the OneProtect role assignment only after verification passes. - Added frontend and backend tests for system-admin creation, role hiding, authorization denial, idempotency, and bootstrap behavior.
Security Boundaries
- Tenant admins, operators, and auditors cannot see or call the tenant onboarding UI successfully.
- The first
system_adminmust already exist through an operator-controlled Keycloak bootstrap path before OP-069 can create tenants or tenant users. - Bootstrap tenant users can receive
tenant_admin,operator, orauditorroles only. System-admin users remain an operator-controlled Keycloak bootstrap path. - Initial passwords are sent only to Keycloak when bootstrap is enabled. They are never stored by OneProtect and audit payloads record only that a password was supplied.
- Missing Keycloak config, weak temporary passwords, or failed Keycloak verification return a structured 4xx response and leave no durable tenant-user assignment.
- Every mutation and authorization denial is audited.
Validation
tests/test_platform_admin_runtime.pyfrontend/src/test/oneprotect-ui.test.tsx- OpenAPI contract entries for the platform-admin endpoints
Non-Scope
- No tenant self-service signup.
- No SCIM lifecycle replacement.
- No Terraform changes or deployment from the feature branch.
- No public Swagger/OpenAPI activation; that remains OP-070.