Track credential storage outcomes and redact sensitive errors (#49384)

## Why

Successful file fallback can hide a secure-store failure. Storage diagnostics need to distinguish that fallback from explicit file storage while keeping credential values out of error output.

## What changed

- Record credential load, save, delete, and fallback-file cleanup outcomes, including secure-store failures and fallback reasons.
- Preserve the initiating client's attribution across app-server requests, login tasks, sessions, turns, and blocking token persistence.
- Preserve storage error context and typed causes while redacting credential JSON data errors and payload-bearing keyring errors.
- Include sanitized fallback completion warnings in the default `codex login` file logs.

## Testing

Add coverage for storage policy and metric attribution, credential redaction, login diagnostics, concurrent app-server clients, device-code login, and token refresh during a turn.

GitOrigin-RevId: 6d5651c1718d184016fa77befa02aa528750b2ae
This commit is contained in:
Celia Chen
2026-09-29 22:24:09 +00:00
committed by copyberry
parent bd4204efc2
commit a44afa527c
24 changed files with 1465 additions and 353 deletions
+15 -8
View File
@@ -83,6 +83,7 @@ use codex_feedback::CodexFeedback;
use codex_goal_extension::GoalService;
use codex_home::CodexHomeUserInstructionsProvider;
use codex_login::AuthManager;
use codex_otel::auth_storage::AuthStorageOriginator;
use codex_protocol::ThreadId;
use codex_protocol::mcp::ClientMcpExtensions;
use codex_protocol::protocol::SessionSource;
@@ -1031,15 +1032,21 @@ impl MessageProcessor {
return;
}
let processor_for_request = Arc::clone(&processor);
let originator = AuthStorageOriginator::from_client_name(
session.app_server_client_name().unwrap_or("none"),
);
// Keep queued requests small to avoid large stack temporaries during construction.
let result = Box::pin(processor_for_request.handle_initialized_client_request(
connection_request_id,
codex_request,
request_context,
session,
event_stream_ready,
))
.await;
let result = originator
.scope(Box::pin(
processor_for_request.handle_initialized_client_request(
connection_request_id,
codex_request,
request_context,
session,
event_stream_ready,
),
))
.await;
if let Err(error) = result {
processor.outgoing.send_error(error_request_id, error).await;
}