Runbook — Authority break-glass recovery

Use this when: an operator is locked out of Authority, or Authority itself is broken, and no normal admin surface can fix it. This is the estate’s most privileged path. Every use is recorded, expires, and shows up as a Critical doctor finding until someone acknowledges it.

Sprint: SPRINT_20260722_016 AUTH-11. Design: docs/modules/authority/break-glass-access-design.md(owner sign-off 2026-08-14).


What this is, and what it is not

Break-glass here is not a network endpoint, a bootstrap flag, or a standing emergency account. It is the stella admin users password-set --confirm-authority-access tool, run as a one-shot container that opens Authority’s database directly and resets one user’s credential.

That shape is deliberate, and the argument is worth knowing before you reach for something else:

It is not a way to create an administrator. It resets an EXISTING user’s password, the credential expires (default 15 minutes), and the use is on the record.


Before you start

You need:

  1. Shell on the host running the compose stack.
  2. STELLAOPS_POSTGRES_AUTHORITY_CONNECTION set in the compose .env (the tool refuses to run without an Authority storage environment marker — that is its environment gate).
  3. A reason. --reason is required. It is written into the audit ledger and it is the only field that answers the question a post-incident review actually asks.
  4. The username and tenant. Break-glass is restricted to structural tenants — installation and default. A per-tenant password reset is a support question answered through the normal admin surface, not through the auth root; the tool refuses other tenants and names the permitted ones.

Procedure

cd devops/compose

# Linux/macOS
./scripts/authority-password-set.sh admin \
  --tenant default \
  --reason "INC-1234: operator locked out after failed logins" \
  --password-stdin <<< 'NewStrongPassword@2026!'
# Windows
./scripts/authority-password-set.ps1 -Username admin `
  -Tenant default `
  -Reason "INC-1234: operator locked out after failed logins" `
  -PasswordStdin

Password policy is enforced by the tool before it touches the database: at least 12 characters with upper, lower, digit and symbol.

On success it prints the expiry and tells you the use was recorded:

Set password for Authority user 'admin' in tenant 'default'. Lockout counters were cleared.
This credential EXPIRES at 2026-08-18 09:15:00Z (900s). Change the password through Authority before then.
The use was recorded in authority.break_glass_events and doctor will report CRITICAL until it is reconciled.

Then, immediately

  1. Log in and change the password through Authority. The break-glass credential is entry, not an account. When it expires the credential stops working — the grant path enforces password_expires_at, so walking away leaves an expired credential rather than a permanent administrator.
  2. Reconcile the event (below). Until you do, doctor.authority.break-glass.unreconciled reports Critical.

If you need longer than 15 minutes

--expires-in-seconds 3600

Bounded to 60 … 86400. The value you choose is stamped into the audit row, so a stretched window is visible after the fact rather than invisible. The air-gapped case is why this is configurable at all: an operator with no console may genuinely need longer.


Reconciling a use

This is part of the procedure, not an optional tidy-up. The doctor check clears on explicit acknowledgement and never on a timer — a Critical that ages out would train operators to wait rather than reconcile.

# What is outstanding?
stella admin break-glass list --unreconciled-only

# Acknowledge one
stella admin break-glass reconcile <event-id> \
  --by "ops-lead@example" \
  --note "reviewed at incident standup; password rotated"

--by is required: an acknowledgement that names nobody clears a Critical without attaching anyone to the decision.

Reconciliation is recorded once. A second attempt is refused rather than overwriting who accepted it — enforced by a database trigger, not just by the CLI.


What the ledger records, and what it cannot

authority.break_glass_events carries, per use: when, which tenant and subject, the actor (OS user + host — break-glass runs when Authority cannot authenticate anyone, so the operating system’s identity is the only one available), the reason, the tool version, the resolved expiry and the configured window, and the reconciliation.

Three properties worth knowing:


Doctor

doctor.authority.break-glass.unreconciled (category data-integrity):

StateReport
Ledger table missingCritical — a reset would run unaudited; migration 025 has not converged
Unreconciled uses existCritical — names the count and the oldest occurrence
All uses reconciledInfo / healthy
No uses recordedInfo / healthy, and the message says it is not a claim of never-used

Reaching it: GET /doctor/authority/checks on authority, scope-gated on ops.health.


The drill

The scenario is exercised end-to-end by StellaOps.Authority.Plugin.Standard.Tests.BreakGlass.BreakGlassRecoveryDrillTests against a real PostgreSQL with Authority’s real migration chain: converge a fresh database, log in, manufacture a real lockout through repeated failed logins (not by writing locked_until), confirm login fails, recover through the shipped break-glass store, confirm login succeeds and exactly one audit row exists and is undeletable, then advance the clock past the expiry and confirm the recovered credential stops working.

That last step is the one most likely to be dropped and the only one that tests the constraint the pre-hardening mechanism most clearly violated.