Idempotent CLI script that creates or promotes a site-wide super_admin
on any environment. Solves the prod bootstrap case where no admin
exists yet — dev's seed_test_users.py only runs in dev, self-serve
signup is still gated, and even when enabled, signup creates owner
roles, not super_admins.
The script:
- Reads --email (required), normalizes to lowercase.
- If user does not exist: creates an Account + super_admin User as
the account owner, with email_verified_at stamped at creation and
password_hash=NULL (forces the reset flow on first login).
- If user exists: promotes is_super_admin=true and backfills
email_verified_at if null. Idempotent — re-running is safe.
- Mints a password-reset JWT, stores the token hash in
password_reset_tokens, and either emails the link
(--send-reset) or prints it to stdout (--print-reset). Email
send is best-effort with a fallback URL on stdout so a
misconfigured EmailService never blocks login.
- --promote-only flag: skips creation, only promotes an existing
user. Useful for promoting an already-self-served user without
triggering an unnecessary reset.
Uses ADMIN_DATABASE_URL when set (BYPASSRLS — required because users
is RLS-enabled and the script has no tenant context at bootstrap).
Smoke-tested in dev against all three paths: fresh create, re-run
idempotency on the same email, --promote-only on an existing user
with no password.
Intended invocation on prod, once Stripe/EIN unblocks:
railway run python -m scripts.create_site_admin \
--email michael@resolutionflow.com \
--send-reset
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>