User Provisioning Runbook
Audience: HUPH admins adding counselors/admins. All steps are in Zitadel admin console unless noted.
Add user
Via admin console (preferred):
- https://auth.huph.val.id/ui/console → Users → New.
- Fields: Email, First/Last name, Username (= email).
- Initial password: generate, send via out-of-band channel (not the same email).
- Require "Change password on first login" — on.
- Enforce MFA (TOTP + WebAuthn) — on.
- Grant role in the HUPH project:
admin→ projecthuph-admin, roleIAM_OWNERif cluster-admin, elseORG_OWNER.counselor→ projecthuph-admin, rolecounselor, setcluster_idclaim.
Via API (scripted / bulk):
Bash
# Requires PAT with org.user.write
curl -X POST "https://auth.huph.val.id/management/v1/users/human" \
-H "Authorization: Bearer $ZITADEL_PAT" \
-H "Content-Type: application/json" \
-d '{
"userName": "new.counselor@huph.val.id",
"profile": { "firstName": "New", "lastName": "Counselor", "displayName": "New Counselor", "preferredLanguage": "en" },
"email": { "email": "new.counselor@huph.val.id", "isEmailVerified": false },
"password": { "password": "'"$(openssl rand -base64 24)"'", "changeRequired": true }
}'
Post-create checklist:
Text Only
[ ] User exists in Zitadel + admin.huph.val.id /admin/users shows them
[ ] Role is correct
[ ] cluster_id claim set (counselors only)
[ ] User received credentials via secure channel
[ ] Row added to HUPH audit_log (auto from admin proxy if using provisioning UI)
Deactivate user
Target revocation time: <5 minutes end-to-end.
- Zitadel console → Users → search → Deactivate.
- Console → Sessions (if visible) → Terminate all.
If not available: API
DELETE /management/v1/users/{id}/sessions. - Verify in HUPH admin:
- Zitadel signs new JWTs every 1h. Existing JWTs remain valid until expiry. For immediate kill:
- Shorten access token lifetime to 5m in Zitadel project settings (recommended default anyway), or
- Rotate the project's signing key: Projects → HUPH → Keys → Rotate. Invalidates all outstanding tokens system-wide (expect user-facing friction — only use for compromise).
Role change
- Who can: any user with
ORG_OWNERon the HUPH org. - Zitadel console → Users → select → Authorizations → edit role.
- User must re-login for new claims to appear in JWT (claims are minted at token issue).
- Log the change: Zitadel emits
user.grant.changedevent; also append todocs/ops/zitadel/role-change-log.md:
Audit trail
- Canonical: Zitadel events
eventstore.events— query via console (Admin → Events) or SQL: - HUPH side:
admin_audit_logtable (if wired) captures actions done via HUPH admin dashboard (not direct Zitadel console). - Review both monthly; mismatches = someone bypassed the dashboard.