Skip to content

Recovery CLI

The recovery CLI is a break-glass tool. It runs inside the container, using the configured database connection — there's no network surface, no auth bypass. It exists for the situations where the admin UI cannot help: no admin can sign in, the projections desynced after a schema change, a legacy client needs a Phase-2C retrofit, etc.

Every invocation is written to the auth log.

Entry point

bash
dotnet Modgud.Api.dll recover <command> [args...] [--realm <slug>]

The --realm flag defaults to system. Commands that don't need a tenant context ignore it.

Commands

list

List every active user with UserName · Email · Active · Admin · 2FA · Passkeys.

bash
dotnet Modgud.Api.dll recover list

Admin means the user holds realm:admin (typically via the System Admin role inside the seeded Administratoren group).

reset-2fa <username>

Disable TOTP and Email-OTP, delete every stored passkey credential, and clear the grace-period stamp so the user gets a fresh secure-setup window on next login.

bash
dotnet Modgud.Api.dll recover reset-2fa alice

set-email <username> <new-email>

Update the user's email and append a UserUpdatedEvent so projections

  • SignalR-driven admin grids refresh live.
bash
dotnet Modgud.Api.dll recover set-email alice alice@example.com

Issue a one-time magic-link URL and print it to stdout. Useful for nudging a locked-out user back in without resetting their password.

bash
dotnet Modgud.Api.dll recover magic-link alice

rebuild-projections

Rebuild all Marten projections (inline + async). Bootstrap path for the first migration after a breaking schema change — runs without any admin authentication.

bash
dotnet Modgud.Api.dll recover rebuild-projections

bootstrap-admin

Create the first admin in a realm. Default realm: system. Two modes — Direct (password set immediately) and Invite (a magic-link URL is printed and emailed if SMTP is configured).

bash
# Direct mode
dotnet Modgud.Api.dll recover bootstrap-admin \
  --email admin@example.com \
  --username admin \
  --firstname Admin \
  --lastname User \
  --password 'ChangeMe1!'

# Invite mode (no --password)
dotnet Modgud.Api.dll recover bootstrap-admin \
  --email admin@example.com \
  --username admin

Flags:

FlagRequiredNotes
--emailyesEmail — required in both modes.
--usernamenoDefaults to the local-part of the email.
--firstnamenoOptional.
--lastnamenoOptional.
--passwordnoIf present: Direct mode. Validated against the configured Identity password rules. If absent: Invite mode.
--realm <slug>noDefaults to system.

migrate-cc-credentials

Phase-2C retrofit. For every OAuth client that still has the client_credentials grant without a LinkedServiceAccountId (i.e. pre-Phase-2C clients), auto-provision a Service Account named legacy.{clientId} and backfill the link so the standard SA-managed mutation guard applies.

Idempotent — already-linked clients are skipped; existing legacy.* SAs are re-used.

bash
dotnet Modgud.Api.dll recover migrate-cc-credentials --realm system

realm-list

List every active realm with its slug and configured domains. Useful first probe after a fresh deploy — shows the system realm's seeded localhost domains so you know which Host header to use.

bash
dotnet Modgud.Api.dll recover realm-list

realm-add-domain

Add a domain to an active realm's Domains list. Typically used once after a fresh deploy to add the production hostname to the system realm.

bash
dotnet Modgud.Api.dll recover realm-add-domain \
  --slug system \
  --domain auth.example.com

Flags:

  • --slug <slug> — required.
  • --domain <hostname> — required. Stored verbatim; case-insensitive match at request time.

realm-remove-domain

Remove a domain from an active realm's Domains list. No-op if not present.

bash
dotnet Modgud.Api.dll recover realm-remove-domain \
  --slug system \
  --domain old.example.com

help

Show the usage summary.

bash
dotnet Modgud.Api.dll recover help

Audit trail

Every recovery invocation writes a Auth: Recovery <command> entry to the auth log via Serilog. Successful operations log at Warning level (to make them stand out in the log stream); failures log at Error.

When to reach for the CLI

  • No admin can sign inbootstrap-admin (Direct mode) creates a fresh admin in one shot.
  • A user lost their 2FA devicereset-2fa <username> then magic-link <username> so they can log in and re-enrol.
  • Production hostname doesn't route to a realmrealm-list to confirm what's configured, then realm-add-domain to bind the new hostname.
  • Marten projections out of sync after a schema changerebuild-projections.
  • Legacy client_credentials clients fail mutation guardmigrate-cc-credentials provisions the linked SA they need.

For the operational story of first-time admin setup (when there's no admin yet to invite anyone), see First-time setup.

Released under the Apache-2.0 License.