Source-grounded rewrite of 529 published docs pages with per-unit information-loss verification: 1,713 factual corrections cited to src/**, generated surfaces regenerated, frontmatter titles preserved for i18n, release notes pages untouched. All docs gates green. Closes #100141
6.7 KiB
summary, title, read_when
| summary | title | read_when | ||
|---|---|---|---|---|
| Canonical credential eligibility and resolution semantics for auth profiles | Auth credential semantics |
|
These semantics keep selection-time and runtime auth behavior aligned. They are shared by:
resolveAuthProfileOrder(profile ordering)resolveApiKeyForProfile(runtime credential resolution)openclaw models status --probeopenclaw doctorauth checks (doctor-auth)
Stable probe reason codes
Probe results carry a status bucket (ok, auth, rate_limit, billing, timeout, format, unknown, no_model) plus a stable reasonCode when the probe never reached a model call:
reasonCode |
Meaning |
|---|---|
excluded_by_auth_order |
Profile omitted from the explicit auth order for its provider. |
missing_credential |
No inline credential or SecretRef is configured. |
expired |
Token expires is in the past. |
invalid_expires |
expires is not a valid positive Unix ms timestamp. |
unresolved_ref |
Configured SecretRef could not be resolved. |
ineligible_profile |
Profile is incompatible with provider config (includes malformed key input). |
no_model |
Credentials exist but no probeable model candidate resolved. |
Eligibility checks report ok as the reason code for usable credentials.
Token credentials
Token credentials (type: "token") support inline token and/or tokenRef.
Eligibility rules
- A token profile is ineligible when both
tokenandtokenRefare absent (missing_credential). expiresis optional. When present it must be a finite number of Unix epoch milliseconds greater than0and no larger than the maximum JavaScriptDatetimestamp (8640000000000000).- If
expiresis invalid (wrong type,NaN,0, negative, non-finite, or beyond that maximum), the profile is ineligible withinvalid_expires. - If
expiresis in the past, the profile is ineligible withexpired. tokenRefdoes not bypassexpiresvalidation.
Resolution rules
- Resolver semantics match eligibility semantics for
expires. - For eligible profiles, token material may be resolved from the inline value or
tokenRef. - Unresolvable refs produce
unresolved_refinmodels status --probeoutput.
Agent copy portability
Agent auth inheritance is read-through. When an agent has no local profile, it resolves profiles from the default/main agent store at runtime without copying secret material into its own credential store (agents/<agentId>/agent/openclaw-agent.sqlite).
Explicit copy flows, such as openclaw agents add, use this portability policy:
api_keyandtokenprofiles are portable unlesscopyToAgents: false.oauthprofiles are not portable by default because refresh tokens can be single-use or rotation-sensitive.- Provider-owned OAuth flows may opt in with
copyToAgents: trueonly when copying refresh material across agents is known safe; the opt-in only applies when the profile carries inline access/refresh material.
Non-portable profiles remain available through read-through inheritance unless the target agent signs in separately and creates its own local profile.
Config-only auth routes
auth.profiles entries with mode: "aws-sdk" are routing metadata, not stored credentials. They are valid when the target provider uses models.providers.<id>.auth: "aws-sdk", the route the plugin-owned Amazon Bedrock setup writes. These profile ids may appear in auth.order and session overrides even when no matching entry exists in the credential store.
Do not write type: "aws-sdk" into the credential store; stored credentials are only api_key, token, or oauth. If a legacy auth-profiles.json has such a marker, openclaw doctor --fix moves it to auth.profiles and removes the marker from the store.
Explicit auth order filtering
- When
auth.order.<provider>or the auth-store order override is set for a provider,models status --probeonly probes profile ids that remain in the resolved auth order for that provider. The stored override wins overauth.orderconfig. - A stored profile for that provider that is omitted from the explicit order is not silently tried later. Probe output reports it with
reasonCode: excluded_by_auth_orderand the detailExcluded by auth.order for this provider.
Probe target resolution
- Probe targets can come from auth profiles, environment credentials, or
models.json(resultsource:profile,env,models.json). - If a provider has credentials but OpenClaw cannot resolve a probeable model candidate for it,
models status --probereportsstatus: no_modelwithreasonCode: no_model.
External CLI credential discovery
- Runtime-only credentials owned by external CLIs (Claude CLI for
claude-cli, Codex CLI foropenai, MiniMax CLI forminimax-portal) are discovered only when the provider, runtime, or auth profile is in scope for the current operation, or when a stored local profile for that external source already exists. - Auth-store callers choose an explicit external-CLI discovery mode:
nonefor persisted/plugin auth only,existingfor refreshing already stored external CLI profiles, orscopedfor a concrete provider/profile set. - Read-only/status paths pass
allowKeychainPrompt: false; they use file-backed external CLI credentials only and do not read or reuse macOS Keychain results.
OAuth SecretRef Policy Guard
SecretRef input is for static credentials only. OAuth credentials are runtime-mutable (refresh flows persist rotated tokens), so SecretRef-backed OAuth material would split mutable state across stores.
- If a profile credential is
type: "oauth", SecretRef objects are rejected for any credential material field on that profile. - If
auth.profiles.<id>.modeis"oauth", SecretRef-backedkeyRef/tokenRefinput for that profile is rejected. - Violations are hard failures (thrown errors) in startup/reload secret preparation and profile resolution paths.
Legacy-Compatible Messaging
For script compatibility, probe errors keep this first line unchanged:
Auth profile credentials are missing or expired.
Human-friendly detail and the stable reason code follow on subsequent lines in the form ↳ Auth reason [code]: ....