tenant-identity-recovery

/home/avalon/.hermes/skills/software-development/tenant-identity-recovery/SKILL.md · raw

Tenant Identity Recovery

Use this skill when an operator or customer cannot enter a tenant-backed application and asks for a password reset, recovery link, passkey replacement, or direct admin login. It applies to products where a central identity service creates a separate tenant-local browser session, often through a signed handoff.

First classify the identities

Before touching credentials, write down which layer owns each identity:

  1. Messaging identity — Telegram/Discord allowlists control who may talk to an agent or tenant brain. They do not create browser sessions.
  2. Central web identity — owns login factors, account status/type, tenant directory, and handoff authority.
  3. Tenant-local session — accepted only after a central handoff and usually host-only.
  4. Runtime/provider identity — model/API credentials belong to the tenant runtime and are unrelated to human web login.

Do not tell the user that a bot connection means they are logged into the web admin. Do not infer that an account has a password because the user calls the problem a “password reset.” Inspect the live schema and routes first. A passkey record is not a password record.

Choose the smallest durable recovery

Prefer, in order:

  1. use an existing synced passkey on the user's current device/account;
  2. use the product's existing recovery or add-passkey flow;
  3. issue an established one-time central recovery flow that lets the user attach a new factor;
  4. when the user explicitly requests it and product policy allows, add a narrowly scoped central password fallback;
  5. use an emergency direct-entry bridge only as temporary access, never as durable recovery.

If the system has no password schema or route, say so plainly. A durable fallback is a feature addition, not a database “reset.”

Central password fallback contract

When a password fallback is appropriate, keep it at the central identity boundary and preserve the ordinary signed handoff into the tenant. Never re-enable a legacy tenant-local password for a tenant whose central identity is authoritative.

Require all of the following:

Keep an existing passkey valid unless the user separately asks to revoke it. Adding a fallback, replacing a passkey, and revoking an old factor are separate operations.

Stable login page behavior

A password login page should have a stable non-secret URL and:

  1. fetch public same-origin CSRF/client configuration;
  2. submit only the password to the central password-login endpoint;
  3. receive a central session cookie and safe account/tenant projection;
  4. call the existing authenticated handoff endpoint;
  5. form-POST the returned fields to the exact HTTPS tenant action;
  6. surface concise errors without exposing raw server diagnostics;
  7. never put the password or handoff token in query strings or fragments.

The signed central account type remains authoritative. Do not derive product admin from a legacy local tenant role, a configured password, or a stale cookie.

Secret-safe deployment and rotation

Generate the password into a permission-restricted temporary file. Compute the hash locally. Inject only the exact account ID and hash through the app's approved secret environment path. For PM2-managed services, update the environment deterministically, restart only the target process with updated env, then save PM2 state.

Deliver the plaintext privately to the verified user—prefer a protected direct message rather than a group. After accepted delivery, delete plaintext and temporary hash staging. Do not print secret values while verifying configuration; report only configured/unconfigured markers.

Rotating the fallback means generating a new password and replacing the stored hash. Prefer an application/operator endpoint or a managed secret store when one exists; environment-backed configuration is appropriate only for narrowly scoped operator fallback, not general customer passwords.

Emergency bridge pitfalls

A static HTML file containing a short-lived handoff token is fragile:

If a bridge is unavoidable, verify the public URL before sending, deliver it privately, state its exact expiry, make it single-use, remove it afterward, and label it temporary. Never call it a password reset or durable recovery.

End-to-end acceptance

Do not stop at unit tests or a PM2 online row. Verify the public path:

  1. login page returns 200 and identifies the intended admin surface;
  2. missing or hostile origin/CSRF is rejected;
  3. wrong password returns 401 and sets no session cookie;
  4. correct password returns 200, the expected account type, and a secure central cookie;
  5. authenticated handoff targets the exact intended tenant origin;
  6. form-POSTing the handoff succeeds;
  7. tenant session reports authenticated plus the expected role/account type;
  8. the service is healthy with account/hash configuration present, without printing values;
  9. browser visual and JavaScript checks pass;
  10. plaintext staging and obsolete recovery artifacts are gone.

When the user reports a failed recovery URL, reproduce that exact public URL first, explain the failure briefly, and replace it with a verified durable path rather than another unverified bearer file.

References