Repository navigation
fix(identity): keep an unbacked key safe on Replace and unblock a corrupt saved key - #3233
Conversation
…rupt key First run's Replace deleted the key saved here even when it had no confirmed backup, with no way to copy it. Now it shows the private-key controls and Replace waits until the key was revealed or copied. A backed-up key keeps the one-step Replace. A saved key native can't parse left launch on a Retry that could never work, with Settings out of reach. That page now offers Remove from device, which confirms and signs out as Sign out of Buzz does; the next launch deletes the key and opens first run to restore or import. The launch read's denied message no longer says no identity was created. Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Logan Johnson <[email protected]>
…licate keyring entries Replace of a device key with no confirmed backup now needs a reveal or copy and "I have my key", the same gate as Settings' Remove from device. Keyring's Ambiguous (several items matching one entry) was mapped to Corrupt, so the launch page offered Remove from device. Deletes refuse for it too, so the pending sign-out would fail every later launch. A new credential-store Error::Ambiguous keeps every other caller's mapping and gives the identity read its own message with Retry. Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Logan Johnson <[email protected]>
Removing the acknowledgement reset left every Replace test passing. A second sign-in after Cancel must start with Replace disabled and "I have my key" unchecked and disabled. Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Logan Johnson <[email protected]>
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 Approved based on review of 32790b9. The PR has since advanced to 215ad26; this approval does not validate that later delta.
No production defect was established in the reviewed identity replacement/removal flows. Confirmation and acknowledgement gates, account binding, credential-error distinctions, and reuse of the existing non-wiping sign-out contract were reviewed. Browser checks exercised the actual application with modeled native IPC/account replies in Chromium and WebKit; credential-store tests passed. Real native credential deletion/restart remains unverified, and the broad local test run did not complete cleanly.
The existing P3 comment is non-blocking: add a regression test proving that Cancel followed by signing in again starts replacement with a fresh, unchecked acknowledgement. Current behavior passed that scenario; the gap is durable test coverage.
* origin/main: NEXUS-4029: Offer folder chips in the composer (block#2789) perf(css): narrow effort button invalidation (block#3297) NEXUS-4433: Expose saved plugin installation source kind (block#3242) fix(identity): keep an unbacked key safe on Replace and unblock a corrupt saved key (block#3233) Expose Solo region state before a component mounts (block#3296) fix(builderlab): say a 401 was refused, not expired, and show each sign-in failure once (block#3241) feat(agents): file new Solo chats in explicit personal workspaces (block#2857) perf(css): limit broad style invalidation (block#3267) Delay and fade in the Bestie badge celebration (block#3292) fix(github): show private-repo body images from signed links (block#3252) NEXUS-4029: Preserve semantic chips in the core composer (block#2303) Make plugin signature enforcement opt-in (block#2212) NEXUS-4156: Add workspace Leads and choose a chat's workspace (block#2788) feat(plugins): report conclusively retired update providers (block#3263) feat(messages): let attachment renderers open files from the host file card (block#2239) feat(charts): bundle a Charts code-block renderer (block#3226) Expose native reply grouping through Conversation.ui (block#3245) Signed-off-by: Joah Gerstenberg <[email protected]> # Conflicts: # src/features/conversation/ComposerCompletions.test.tsx # src/features/conversation/ComposerCompletions.tsx # src/features/messages/MessageComposer.tsx
The Replace tests from #3233 read the copied key from the browser clipboard. This branch copies a private key through the host on every platform and clears it after a minute, so the tests now answer that command and check the host write. Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Logan Johnson <[email protected]>
Summary
Details
src/features/identity/Welcome.tsx:PrivateKeyand an I have my key checkbox when the key has no confirmed backup. The checkbox is enabled after a reveal or copy (onInteraction), and Replace needs both. Each new question starts over.MALFORMED_IDENTITY) and shows Remove from device in place of Retry secure storage access. Its confirmation callsidentity.signOut({ wipe: false, removeAgents: false }). A native refusal stays in the dialog with its reason, and the button can be pressed again. Other launch errors keep Retry.src/features/identity/service.ts:MALFORMED_IDENTITYholds native's exact text. A test readsidentity.rsand checks it still matches, as the recovery messages already do.crates/credential-store: a newError::Ambiguousfor keyring'sAmbiguous, which wasCorrupt. Every other caller maps it as it mappedCorrupt, so only the identity read changes.src-tauri/src/identity.rs:Ambiguousgets its ownAMBIGUOUSmessage, so the launch page keeps Retry. The launch read's denied message now ends "nothing was changed". Writes keep "no identity was created".docs/identity.mdanddocs/buzz-help.mddescribe both changes.identity.test.tsx):Known limits
LinkedKeyCheck) is unchanged. It already warns, and Settings → Identity is reachable there for a copy.🤖 Generated with Claude Code