Auth And Config Recovery¶
Purpose¶
Use this guide when login works on one machine but not another, a support run uses the wrong Bullpen profile, copied credentials fail to decrypt, or auth diagnostics mention missing local credential files. Start with read-only diagnostics and generated command references before removing local state.
This guide covers local auth and profile recovery only. It does not repair server-side account, KYC, wallet-routing, or funds state.
Before You Start¶
- Run every command from the same shell, machine, and Bullpen account that saw the failure.
- Do not delete
~/.bullpenas the first recovery step. It can remove config, logs, local keys, and wallet-routing evidence. - Do not copy or paste private keys, seed phrases, JWTs, API tokens,
credentials.json.enc, or full config files into support tickets. - Set both
BULLPEN_HOMEandBULLPEN_CONFIGwhen isolating a support or CI profile. Setting only one can mix credentials from one profile with config from another. - Keep local/dev binaries on a separate
BULLPEN_HOMEfrom the official release profile. Do not let a local or development binary write the default~/.bullpencredential home unless you intentionally opt in to testing that profile.
Safe First Command¶
Run status, auth, and config diagnostics before reauthentication or local reset.
status, doctor auth, and config show are read-only. Use
doctor auth --refresh --output json only when stale or expired session
evidence is needed, support asks for it, or diagnostics explicitly request
refreshed evidence before login or reset.
status reports local login and environment state. doctor auth reports token
health, onboarding state, wallet readiness, local credential-file health, and a
credential_storage object without refreshing credentials.
The storage object is non-mutating and helps support distinguish encrypted
credentials, legacy plaintext credentials, both files, no local credentials,
and ephemeral test stores without decrypting or rewriting local auth files.
config show reports effective config without printing secrets. See the generated
doctor auth and
config show references for exact flags.
A logged-in session is three credentials with different lifetimes: the JWT
access token (~15 minutes, auto-refreshed), the refresh token (~30 days), and
the signing session (~7 days). A normal access-token expiry should refresh
automatically. Run bullpen login only when diagnostics report that the refresh
token was rejected or the signing session must be renewed. Do not delete local
state unless the CLI explicitly identifies unrecoverable credential storage.
If a command fails during a transient refresh, run
bullpen doctor auth --refresh --output json once and follow its structured
next action.
Refresh responses must contain a non-empty access_token and a non-empty
refresh_token. Missing or empty token fields are not treated as a partial
success: a missing or empty refresh_token fails closed as
AUTH_REFRESH_PERSISTENCE_FAILED, leaves the old on-disk credentials untouched,
and requires storage/service diagnostics before local reset or re-login. Keep
the existing credential files available, run the diagnostics above, and branch
only on the structured recovery fields.
Newer builds also include nullable session_recovery metadata on
bullpen status --output json and bullpen doctor auth --output json.
When it is present, branch on session_recovery.code, requires_login,
safe_to_retry, and next_command. session_recovery.code is not the same
field as a top-level error code; it uses snake_case values such as
auth_login_required and auth_refresh_rejected. Do not start login, forced
logout, or file cleanup from prose alone.
Failed device-login and email-verification attempts may also include an
auth_incident object. If it reports
safe_to_retry: false, follow its auth_incident.next_command exactly as
emitted. A bullpen support next command means the attempt needs inspection;
do not rewrite that field to a different command. Repeating login or requesting
another email code can hide the original state.
For account-level recovery, use the recovery_plan object when bullpen fix
--refresh, bullpen recover polymarket
--refresh --output json, or bullpen support bundle --output json emits it.
For auth-attempt recovery, use auth_incident. Do not infer a reset, forced
logout, wallet repair, or support handoff from prose alone. If you need a
passive support artifact, optionally run bullpen support bundle --output
json. The support bundle includes a root privacy_contract that discloses
retained operational identifiers, exact balances, and local paths. It remains
local until you attach it to a ticket.
doctor auth reports local credential-store failures as sanitized
credentials_error text plus nullable credential_error_class. Non-null class
values are missing, decrypt_failed, decode_failed, permission_denied,
store_locked, or unknown. Use that class for support routing; do not ask
for raw credential-store error chains.
Example output
{
"status": "error",
"error_code": "AUTH_REAUTHENTICATION_REQUIRED",
"credentials_valid": true,
"token_valid": false,
"token_expires_in_secs": null,
"refresh_token_expires_in_secs": null,
"credentials_error": null,
"credential_error_class": null,
"keypair_checked": false,
"keypair_valid": false,
"wallet_ready": false,
"trade_auth_state": "reauthentication_required",
"trade_auth_blocked": true,
"trade_auth_blocker_reason": "No local Bullpen session is available.",
"turnkey_signing_session_present": true,
"turnkey_signing_session_expired": true,
"session_recovery": {
"state": "login_required",
"code": "auth_login_required",
"requires_login": true,
"safe_to_retry": false,
"next_command": "bullpen login"
},
"remediation": {
"action": "reauthenticate",
"command": "bullpen login",
"message": "Refresh local Bullpen and Turnkey credentials, then retry the real trade."
},
"privacy_contract": {
"schema_version": 1,
"broad_pii_redaction_claimed": false,
"credentials_redacted": true,
"wallet_addresses_included": false,
"transaction_ids_included": false,
"order_ids_included": false,
"trade_ids_included": false,
"condition_ids_included": false,
"exact_balances_included": false,
"account_resource_ids_included": false,
"local_paths_included": false,
"raw_provider_bodies_included": false,
"raw_credential_error_chains_included": false,
"absolute_local_paths_included": false,
"support_safe": true
}
}
If the issue involves a copied headless profile, run the deployment diagnostic from the destination machine too.
See the generated
doctor deploy-auth reference.
Choose The Recovery Path¶
Use the smallest recovery action that matches the diagnostic result.
| Diagnostic result | Next safe action |
|---|---|
bullpen status --output json and bullpen doctor auth --output json report login is required, the device code expired, or the browser did not open |
Run bullpen login or bullpen login --no-browser. |
A device-login or email-verification auth_incident says safe_to_retry: false and next_command: "bullpen support" |
Preserve the exact auth_incident.next_command. If you need a passive support artifact, optionally run bullpen support bundle --output json and attach the generated JSON file. Do not repeat the same auth attempt. |
You were away and signing/trading now fails, or turnkey_signing_session_expired is true |
Run bullpen status --output json and bullpen doctor auth --refresh --output json; run bullpen login only when diagnostics require login. Do not delete ~/.bullpen first. |
credentials.json.enc or credential_salt.bin is missing or corrupt |
Run bullpen login only when diagnostics require a fresh session; it moves unreadable local auth files aside before login. Run bullpen status --output json and bullpen doctor auth --output json first if you need support to inspect copied-home state; use refresh only if support or diagnostics asks for it. |
Refresh fails with AUTH_REFRESH_PERSISTENCE_FAILED after a missing or empty returned refresh_token |
Keep the old credential files untouched and collect bullpen status --output json plus bullpen doctor auth --refresh --output json. Treat it as storage/service diagnostics, not a partial refresh success. |
| You choose to reset unrecoverable local auth state | Run bullpen logout for a normal active-session local reset, or bullpen logout --force only as the last-resort broader local reset. Start a fresh login afterward only when diagnostics require it. |
doctor auth says local keypair repair is applicable |
Save the read-only JSON first, then run bullpen doctor auth --repair --yes without --output json. If destructive repair is applicable, repair is refused with --output json; no-op or not-applicable diagnostics may still return JSON. Destructive repair requires table mode and typing REPAIR; --yes alone does not confirm it. |
| The command is using the wrong account, environment, or config file | Create or inspect an isolated profile with both BULLPEN_HOME and BULLPEN_CONFIG. |
| A partial copied credential bundle, changed absolute home, or username mismatch is blocking unattended deployment | Restore the complete source bundle or run bullpen status --output json plus bullpen doctor auth --output json on the destination machine before any fresh login; do not keep copying partial auth files. Use refresh only if support or diagnostics asks for it. |
For copied homes, confirm that credentials.json.enc, credential_salt.bin,
and keys/ came from the same source profile. Use the same absolute
BULLPEN_HOME and the same BULLPEN_USERNAME_OVERRIDE on both machines, then
run bullpen doctor deploy-auth --output json on the destination host before
running unattended commands.
Use a local persistent filesystem for copied-home auth. NFS mounts,
cloud-synced folders, and container volumes can behave differently from the
release environment. Run doctor deploy-auth, status, and
doctor auth --refresh on the exact runtime that will use the copied profile;
those diagnostics do not guarantee every NFS/cloud-sync/container lock and fsync
behavior is safe. If the path, username component, or bundled files differ, run
bullpen status --output json plus bullpen doctor auth --output json on the
destination host before creating a fresh login there. Do not try to
repair copied pieces independently.
Use the generated login,
logout, and
doctor auth references before running a
destructive reset.
For deterministic CI or release smoke runs, set
BULLPEN_DISABLE_UPDATE_CHECK=1 before read-only diagnostics. This disables the
background update-check cache write only; it does not change credential loading,
refresh, or trading behavior.
Isolate A Support Profile¶
Create a profile that keeps config, credentials, and logs together. This does
not touch the default ~/.bullpen profile.
This is a non-runnable sequence: run config init only when creating the
isolated profile.
export BULLPEN_HOME="$PWD/.bullpen-support-home"
export BULLPEN_CONFIG="$BULLPEN_HOME/config.toml"
mkdir -p "$BULLPEN_HOME"
bullpen config init
bullpen config show --output json
config init writes a local config file in the isolated profile. It does not
log in or move funds. If BULLPEN_CONFIG points to a missing file, Bullpen
fails closed instead of silently using the default profile.
After config show confirms the expected path, inspect auth state. This is not copy-pasteable
as one sequence: log in to that profile only when diagnostics require login.
After any required login, rerun passive status:
Use --no-browser when the login browser is on a different machine or when you
need to copy the device-code URL into an existing browser session, and only
after diagnostics require login.
Local Reset Boundaries¶
Local reset commands only affect files on the current machine and profile. They do not repair server-side account state, wallet routing, missing deposits, or trading permissions.
This is a non-runnable sequence: run normal logout only when the credential store is readable and you intentionally want to clear the active local session.
State change: This removes the session credentials that logout captured when it started and deletes the local offline signing key when that captured session still matches the active profile. If another login or refresh saves a newer local session first, Bullpen preserves the newer session material instead of deleting it. Normal logout does not delete config, logs, support bundles, installed binaries, or server account/wallet state.
This is a non-runnable sequence: use forced logout only as a last-resort local
reset after bullpen login cannot move unreadable local auth aside or support
asks for a full local reset.
State change: This clears local auth files for the active profile. Keep
bullpen status --output json and bullpen doctor auth --output json output
before running it when possible. After forced logout, rerun passive diagnostics
and start a fresh login only if diagnostics require it.
When you need a machine-readable reset report for support, use
bullpen logout --force --output json. The JSON report returns top-level
server_warning and force_wipe fields, redacts local absolute paths, and
marks the reset as destructive.
This is a non-runnable sequence: use auth repair only when the diagnostic output names that repair.
State change: This backs up and removes a corrupt local keypair file when
doctor auth says the repair is applicable. It is not the generic fix for
missing encrypted credentials or missing salt files. When destructive repair is
applicable, it must run in table mode, is refused with --output json, and
still requires typing REPAIR at the prompt even when --yes is present.
No-op or not-applicable repair diagnostics may still return JSON.
Support Capture¶
For support tickets, include sanitized output from the failing profile. This is not copy-pasteable as a recovery sequence: run refreshed auth diagnostics only when refreshed evidence is needed for the support case.
bullpen --version
bullpen status --output json
bullpen doctor auth --output json
bullpen config show --output json
If the issue involves copied credentials or a headless host, include:
Do not attach secrets, full config files, full logs, credential files, key directories, JWTs, or private keys. Raw logs are exceptional evidence; attach them only when support asks after JSON artifacts are insufficient, and manually scrub credentials, tokens, private keys, auth headers, raw provider bodies, raw credential error chains, and unrelated local paths first. If support needs wallet-routing or funds evidence too, switch to the Wallet Routing And Funds Recovery guide.