Remove local auth and user-management endpoints in favor of Keycloak-backed metadata users, project context, admin metadata APIs, and agent auth context.
3.4 KiB
TJWater Authentication and Metadata Management
Ownership
Keycloak owns login identity, credentials, token issuance, and token expiry. TJWater metadata stores only business snapshots and authorization data:
users.keycloak_idis the stable identity binding.users.username,users.email, andusers.last_login_atare Keycloak claim caches.users.role,users.is_active, andusers.is_superusercontrol TJWater system access.user_project_membership.project_rolecontrols project access.
The backend does not accept passwords, does not issue local JWTs, and does not trust frontend-supplied user IDs.
Login Snapshot Refresh
Every authenticated metadata-user resolution validates the Keycloak access token
and reads sub, preferred_username or username, and email claims. The
backend finds users by keycloak_id = sub, rejects inactive or missing users,
then refreshes username, email, and last_login_at.
This keeps local display data current without changing the identity binding. There is no Keycloak webhook requirement; second-level user or permission sync is out of scope unless explicitly requested later.
Admin APIs
All admin APIs require metadata admin access: users.is_superuser = true or
users.role = 'admin'.
User and membership management:
GET /api/v1/admin/mePOST /api/v1/admin/users/syncPOST /api/v1/admin/users/sync/batchGET /api/v1/admin/usersGET /api/v1/admin/users/{user_id}PATCH /api/v1/admin/users/{user_id}GET /api/v1/admin/projects/{project_id}/membersPOST /api/v1/admin/projects/{project_id}/membersPATCH /api/v1/admin/projects/{project_id}/members/{user_id}DELETE /api/v1/admin/projects/{project_id}/members/{user_id}
Project configuration:
GET /api/v1/admin/projectsPOST /api/v1/admin/projectsPATCH /api/v1/admin/projects/{project_id}GET /api/v1/admin/projects/{project_id}/databasesPUT /api/v1/admin/projects/{project_id}/databasesDELETE /api/v1/admin/projects/{project_id}/databases/{db_role}POST /api/v1/admin/projects/{project_id}/databases/{db_role}/health
Secret Handling
Admins submit plaintext DSNs only through HTTPS admin APIs. Operators should not write encrypted columns manually.
project_databases.dsn_encryptedis encrypted withDATABASE_ENCRYPTION_KEY.- Admin responses return only
has_dsn. - Audit logs record whether a secret was updated, but never store plaintext DSNs or other secrets.
Generate the database encryption key with:
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
Keep keys stable for the lifetime of encrypted metadata. Rotating a key requires decrypting with the old key and re-encrypting with the new key.
Metadata Schema Patches
Apply metadata patches in order:
resources/sql/004_metadata_auth_management.sqlresources/sql/005_metadata_project_configuration.sql
004 creates Keycloak-backed metadata users and project memberships. 005
creates project and project database routing tables with uniqueness, role/type,
and pool-size constraints.
Frontend System Management
/system-admin is shown only after GET /api/v1/admin/me confirms metadata
admin access. The page lets admins maintain metadata users, project members,
projects, project database routing for biz_data and iot_data, connection
health checks. This replaces direct SQL editing for normal project onboarding.