5.3 KiB
5.3 KiB
Cutover Runbook — bermooda_usermanager → UserManager (IdP)
Operational steps for cutting Hamsoo over to UserManager as the identity provider, and for rolling back if verification fails. Every gate below has a command; do not advance while a gate is red.
1. Preconditions (all must be green)
| Gate | Command | Required result |
|---|---|---|
| Hamsoo suite | manage.py test --noinput (in hamsoo_backend) |
OK (1 documented skip) |
| UserManager suite | manage.py test --noinput (in apps/api) |
OK |
| Migration drift | manage.py makemigrations --check (in apps/api) |
No changes detected |
| Export | python apps/identity/migration/export_identity_dump.py --db-name <legacy-db> --output dump.json |
counts match the legacy tables |
| Import dry-run | manage.py import_legacy_identity <dump> --report import_report.json |
has_problems: false, exit 0, 0 collisions |
| Phone OTP | covered by manage.py test apps.sms (43 tests) |
OK |
| Shadow divergence | Hamsoo: manage.py auth_divergence_report |
blocking = 0 |
Export notes:
- The exporter reads MySQL directly (
authmanager_useraccount,workspacemanager_workspace,workspacemanager_workspacemember) and needs no Django. It runs with any Python that haspymysqlormysqlclient; in a venv without a driver it falls back to the machine's global CPython 3.12 site-packages (mysqlclient). - Connection settings:
--db-host/--db-port/--db-name/--db-user/--db-passwordorLEGACY_DB_*environment variables. No password default. - Rehearsal source on this machine:
auth_staging_new_2(144 users / 198 workspaces / 0 members — verified against the 10-11 dump). Point--db-nameat the production legacy database for the real cutover.
2. Production environment
UserManager (apps/api)
| Variable | Value | Notes |
|---|---|---|
DJANGO_ENV |
production |
boot refuses dev defaults |
DJANGO_SECRET_KEY |
secret | |
JWT_SIGNING_KEY |
secret (≥32 bytes) | boot fails on dev default |
OIDC_ISSUER |
https://<idp-host> |
embedded in iss; must match what clients validate |
SSO_COOKIE_DOMAIN |
.hamsoo.me |
parent-domain cookie for SSO |
SSO_TRUSTED_REDIRECT_HOSTS |
hamsoo.me,www.hamsoo.me |
post-login allow-list |
SMS_PROVIDER |
kavenegar |
boot refuses console in production |
KAVENEGAR_API_KEY / KAVENEGAR_SENDER |
secret / sender id | |
EMAIL_FROM_ADDRESS |
no-reply domain address | |
MAIL_DOMAIN, MAIL_INBOUND_SECRET |
mailbox domain + secret | |
MEDIA_ROOT |
persistent volume | mailbox uploads |
DJANGO_ALLOWED_HOSTS, CORS_ALLOWED_ORIGINS, CSRF_TRUSTED_ORIGINS |
IdP host + https://hamsoo.me |
Hamsoo backend (hamsoo_backend)
| Variable | Value | Notes |
|---|---|---|
IS_PRODUCTION |
1 |
|
IDENTITY_PLATFORM_BASE_URL |
https://<idp-host> |
|
IDENTITY_PLATFORM_ISSUER |
same as OIDC_ISSUER |
iss validation |
IDENTITY_PLATFORM_CLIENT_ID / CLIENT_SECRET |
secret | BFF-only; never expose to the browser |
IDENTITY_PLATFORM_REDIRECT_URI |
https://hamsoo.me/sso/callback |
registered in the hamsoo OAuth client |
IDENTITY_PLATFORM_JWKS_URL / AUDIENCE |
JWKS endpoint / audience | |
SSO_FRONTEND_BASE_URL |
https://hamsoo.me |
3. Cutover sequence
- Freeze writes to the legacy usermanager (announce maintenance window).
- Export the legacy database → fresh dump (schema_version 1).
- Dry-run
import_legacy_identity <dump> --report import_report.json; confirmhas_problems: falseand zero phone/username/email collisions. - Backup the UserManager database (
mysqldump/snapshot). - Apply
import_legacy_identity <dump> --apply --report import_report.json. The import is idempotent — re-running only updates, never duplicates. - Verify counts from the report (users / organizations / memberships / profiles match the dry-run numbers exactly).
- Phone OTP spot-check: sign in with a migrated number, receive + verify a code, receive access + refresh tokens.
- Switch traffic: point Hamsoo at the IdP env (section 2), deploy
hamsoo_backend+ frontend, enable the SSO login path. - Watch
manage.py auth_divergence_reportduring the window — everyblockingrow is a session that would break; target is 0 before full traffic.
4. Rollback
Roll back before the legacy service is decommissioned — the legacy database is the restore point for the whole window.
- Stop the SSO login path in Hamsoo (feature flag / previous frontend build).
- Re-point Hamsoo auth config to the previous identity service (previous env values + previous deployment).
- Restore UserManager DB from the step-4 backup if it was mutated (the import only added rows; restoring removes them cleanly).
- Confirm: legacy login works,
auth_divergence_reportshows no new blocking rows for the rolled-back path. - Keep the dump +
import_report.jsonartifacts for the next attempt.
Rolling back does not lose data as long as the legacy database was frozen only for the window and un-frozen at step 1 of rollback.
5. After cutover (deferred, needs explicit approval)
- Remove
bermooda_usermanagercode/tables and the shadow tables. - Rewrite git history for the RSA key committed in
54d5891(rotate first). - Normalize legacy phone numbers (
normalize_phonesbackfill). - Decommission the legacy service.