Fix Keychain read-failure recovery - #71
Conversation
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 50 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughKeyring identity read failures now use legacy-file recovery when migration is incomplete, or locked recovery with an ephemeral key otherwise. New tests simulate failed keyring reads and verify both paths. The file-size override documents and permits the added regression handling. Confidence: 99%. ChangesKeyring recovery behavior
Estimated code review effort: 3 (Moderate) | ~20 minutes Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant Resolver as resolve_identity_with_store
participant Keyring as IdentityKeyStore
participant Legacy as identity.key
participant Ephemeral as Ephemeral identity
Resolver->>Keyring: load identity
Keyring-->>Resolver: read failure
Resolver->>Legacy: inspect legacy file and migration marker
Legacy-->>Resolver: legacy keys or unavailable
Resolver->>Ephemeral: generate key when legacy fallback is unavailable
Ephemeral-->>Resolver: ephemeral identity with KeyringLocked
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@desktop/src-tauri/src/app_state.rs`:
- Around line 479-500: Keep legacy fallback errors within locked recovery: in
desktop/src-tauri/src/app_state.rs lines 479-500, handle load_key_file failure
without propagating it, leave the legacy file untouched, and fall through to the
existing ephemeral RecoveryState::KeyringLocked path. In
desktop/src-tauri/src/app_state_keyring_read_failure_tests.rs lines 71-98, add a
corrupt legacy-file test asserting KeyringLocked, no keyring writes or deletes,
and no legacy-file deletion.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 2353e956-da9d-42f4-be10-1e337bd84fd0
📒 Files selected for processing (3)
desktop/scripts/check-file-sizes.mjsdesktop/src-tauri/src/app_state.rsdesktop/src-tauri/src/app_state_keyring_read_failure_tests.rs
📜 Review details
⏰ Context from checks skipped due to timeout. (13)
- GitHub Check: Desktop E2E Integration (2/2)
- GitHub Check: Desktop E2E Integration (1/2)
- GitHub Check: Windows Rust (x86_64-pc-windows-msvc)
- GitHub Check: Desktop Smoke E2E (3)
- GitHub Check: Desktop Smoke E2E (1)
- GitHub Check: Desktop Build (macOS)
- GitHub Check: Desktop Smoke E2E (4)
- GitHub Check: Desktop Smoke E2E (2)
- GitHub Check: Rust Lint
- GitHub Check: Desktop Core
- GitHub Check: Analyze (python)
- GitHub Check: Analyze (rust)
- GitHub Check: Analyze (javascript-typescript)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs
📄 CodeRabbit inference engine (AGENTS.md)
**/*.rs: Do not useunsafecode.
Do not introduce newunwrap()orexpect()calls in production paths; use?and proper error types instead.
New public Rust APIs must have doc comments.
Files:
desktop/src-tauri/src/app_state_keyring_read_failure_tests.rsdesktop/src-tauri/src/app_state.rs
🔇 Additional comments (3)
desktop/src-tauri/src/app_state.rs (1)
1099-1101: LGTM!desktop/scripts/check-file-sizes.mjs (1)
417-420: LGTM!desktop/src-tauri/src/app_state_keyring_read_failure_tests.rs (1)
1-68: LGTM!
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d4b08bf6db
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "buzz-desktop: keyring identity present but unreadable ({error}); \ | ||
| using legacy identity.key fallback for this boot" | ||
| ); | ||
| let keys = load_key_file(legacy_path)?; |
There was a problem hiding this comment.
Enter recovery when the fallback file is invalid
When a pre-migration identity.key exists without a marker but is unreadable, empty, or corrupt, this ? propagates the file error instead of continuing into KeyringLocked. The setup caller treats any identity-resolution error as fatal and exits the process, so users who cancel the keychain read in this state remain in the boot loop this change is intended to avoid. Handle the file-read failure by using the non-signing locked-recovery path rather than returning it.
Useful? React with 👍 / 👎.
| let loaded = match store.load(IDENTITY_KEY_NAME) { | ||
| Ok(value) => value, | ||
| Err(error) => { | ||
| if legacy_path.exists() && !migration_marker_path(data_dir).exists() { |
There was a problem hiding this comment.
Use a valid fallback file even when the marker exists
When migration successfully writes the marker but fails to delete identity.key, a valid copy of the identity remains alongside the marker. If the subsequent keychain load is cancelled or otherwise fails, this marker check ignores that usable copy and boots locked recovery unnecessarily; the existing KeyringProbe::Unreachable path explicitly uses a present valid file regardless of the marker for this same inaccessible-keyring state. Attempt the file fallback whenever it exists, while falling back to locked recovery if it cannot be parsed.
Useful? React with 👍 / 👎.
Summary
Present+ unreadable/cancelled reads without fatal boot retryKeyringLockedrecovery state without writing, deleting, or rotating identityidentity.keyfallback when no migration marker existsapp_state_tests.rsfileScope
This is an Internal Canary blocker fix for #66. It does not change OAuth server authority, relay policy, ATRIS/Hermes runtime behavior, native Buzz collaboration, or the existing durable identity/session grant contract.
Focused local proof
cargo test --manifest-path desktop/src-tauri/Cargo.toml present_keyring_read_failure --features evaos-teams-managedpnpm -C desktop exec node --import ./test-loader.mjs --experimental-strip-types --test src/features/evaosTeams/api.test.mjs src/features/evaosTeams/loginSuccess.test.mjs src/features/evaosTeams/managedRecovery.test.mjspnpm -C desktop checkpnpm -C desktop typecheckgit diff --checkProof boundary
Local source proof only until this PR's exact-head CI and independent auth/identity review pass. Installed primary operator/Benjamin/ATRIS canary resumes only after merge and a rebuilt cumulative artifact.
Fixes #66
Blocks #60
Part of #1