Repository navigation
fix(identity): clear a copied private key, name restore failures, fix storage copy - #3236
Conversation
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 Approved at 40e9756.
The previously reported issues are addressed: Linux expiry reads move off the GTK main thread, the active recovery screen displays the classified restore causes, and expiry work retains a SHA-256 fingerprint instead of the original copied key. The admission guard now constructs ownership only after successful acquisition, so rejected attempts cannot release another reader’s flag.
The consecutive-rejection regression was exercised with the extracted production helper: all four checks passed, including release and unwind behavior. Restoring the prior eager-construction implementation caused both rejection checks to fail. Earlier Chromium/WebKit checks covered copy interaction and restore error/retry/fallback behavior with modeled native IPC; those frontend checks were not rerun for this Rust-only repair.
Native Linux/Windows clipboard behavior and production timeout scheduling remain unverified in an isolated OS environment. A blocked dependency read can still retain one worker and partial clipboard bytes; the repair bounds additional reader admission rather than cancelling that read. No new actionable defect was established in the repair review.
… storage copy - Copy private key goes through the host clipboard on every platform, which clears it after 60 seconds if it still holds the key. - Restore: a declined browser sign-in reads as canceled, a timed-out browser step as timed out, and no answer from Builderlab as "Couldn't reach Builderlab" instead of the generic retry text. - A damaged saved org sign-in (storage-corrupt) no longer reads as a permissions problem. - "This Mac" in the key-already-saved refusal now says "this computer". 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]>
…s clear on re-copy - A secret copy is set with arboard's history exclusion (macOS and Linux clipboard managers; Windows history and cloud sync). - Only a successfully written copy counts, and only the latest copy's wait may clear, so copying the key again doesn't clear it early and a failed copy leaves the earlier clear in place. - The storage-corrupt text no longer suggests Sign out of Buzz: duplicate Linux keyring items report the same code and can't be deleted that way. - Copy says Buzz tries to clear the clipboard. 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]>
…text The secret copy now holds the key only in Zeroizing buffers in our code. The storage-corrupt text no longer says signing in again can't replace it, since a post-write verify mismatch can succeed on retry. Docs say clipboard managers skip the copy only if they honor the hint. 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]>
After a key copy, a copy inside Buzz makes WebKitGTK the clipboard owner. The expiry check then read the clipboard on that same main loop, which could not answer while blocked: arboard waits up to 4 s on X11 and without limit on Wayland. On Linux the check now reads from a worker with its own handle and gives up after 10 s; only the clear runs on the main thread, and it checks the generation again. 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]>
KeyRestore, the screen a returning user sees, showed one generic line for every error, so the canceled, timed-out and offline causes never reached it. It now shows the native cause, then offers key entry. Unavailable and refused recovery, and the missing- and partial-backup copy, are unchanged. 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]>
Review: the expiry read on Linux runs in a blocking task. When a Wayland owner never finishes a transfer, the read never returns and the timeout only drops the join handle, so the task kept its copy of the private key, and each later copy could add another stuck worker. The wait now keeps only a SHA-256 fingerprint of the key, and the read compares against that. At most one expiry read runs at a time; while one is stuck, later checks leave the clipboard alone, as a read that times out already does. 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]>
…used Reading::begin built its guard eagerly with then_some, so a refused admission dropped a guard whose Drop cleared the flag the running read still held, and the next read was admitted. The guard now exists only after the flag is taken. The test checks two refusals in a row. 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]>
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]>
40e9756 to
285315e
Compare
* origin/main: fix(identity): show a backed-up key as backed up, and drop dead retries (block#3223) fix(browser): open Builderlab account connections in the system browser (block#3287) Expose exact captured-message reads (block#3264) docs(agents): keep internal discussion out of public repo content (block#3258) fix(identity): clear a copied private key, name restore failures, fix storage copy (block#3236) fix(channels): list workspaces that load after `#` opens (block#3277) feat(profiles): show a larger avatar in the hover profile preview (block#3232) fix(identity): ask for credentials on the next sign-in after signing out (block#3231) fix(relay): keep saved channels when the community refuses sign-in (block#3215) Signed-off-by: Joah Gerstenberg <[email protected]>
* origin/main: (38 commits) Fix reminder counts with compact dock corner tabs (block#3126) Add conditional undo for explicit reads (block#3291) fix(composer): edit channel links as atomic chips (block#3312) fix(agents): show remote instruction limit (block#3325) NEXUS-4033: Offer session skills in the core task composer (block#2790) feat(github): name pasted repository and commit links (block#3268) Let plugins give standing instructions to every agent turn (block#3285) fix(relay): read a channel's creation once, not per metadata version (block#3244) fix(messages): remove unconfirmed sends from this device (block#3317) fix: expose proven non-delivery for artifacts (block#3300) feat(plugins): let plugins mark a person's name in @mention suggestions (block#3260) fix(mcp): strip metadata from images agents attach (block#3311) fix(identity): name a linked key that isn't here, and keep Restore after a failed backup check (block#3238) feat(changesets): show the files a local agent changed on its reply (block#3214) fix(identity): show a backed-up key as backed up, and drop dead retries (block#3223) fix(browser): open Builderlab account connections in the system browser (block#3287) Expose exact captured-message reads (block#3264) docs(agents): keep internal discussion out of public repo content (block#3258) fix(identity): clear a copied private key, name restore failures, fix storage copy (block#3236) fix(channels): list workspaces that load after `#` opens (block#3277) ...
Summary
storage-corrupt) told the user to check credential permissions. Now it says Buzz can't read it, that signing in again may not replace it, and to contact support if it keeps happening. It doesn't suggest Sign out of Buzz: that deletes a damaged record, but not duplicate Linux keyring items, which report the same code.Details
src-tauri/src/clipboard.rs:clipboard_write_texttakes an optionalclear_after_secs(capped at 10 minutes). With it, the text is set with arboard's history exclusion (exclude_from_historyon macOS and Linux,exclude_from_monitoringon Windows). The copied text is held inZeroizingbuffers in Buzz's code.copy_secretcounts a copy only after it was written; after the delay,clear_secretclears only if no later counted copy happened and the clipboard text still equals it. Both run on the main thread with the clipboard held. No new command or permission.src/shared/clipboard.ts:writeClipboardSecretuses that host path on every platform (a browser build can't read the clipboard back, so there it only copies).PrivateKeyuses it for Copy private key.src-tauri/src/nsec_backup.rs:error=access_deniedmaps toCANCELED. Othererrorvalues stayRETRY.oauth_callback::TIMED_OUT.OFFLINEmessage covers a failed send on the code exchange, a failed send on account reads (newReadError::Unreachable), and the backup client'sTransporterror. A backup pass still reportsUnreachableas before.src/features/federated-identity/CommunitySignIn.tsx:recoveryMessagehas its own text forstorage-corrupt. Otherstorage-*codes keep the permissions text.src/features/identity/setup.ts: "This Mac" → "this computer".docs/identity.mdanddocs/buzz-help.mddescribe the clipboard and restore rules.CANCELEDand anothererrorisRETRY, both with no account request. An unreachable service isOFFLINE, and a backup pass still maps it toUnreachable.clipboard.rs, fake clipboard): a copy is cleared when its wait ends; a second copy of the same key keeps the first wait from clearing it; a failed second copy leaves the first clear in place; anything else on the clipboard is left alone.clearAfterSecs: 60.CommunitySignInshows the unreadable-sign-in text forstorage-corruptand not the permissions text.Known limits
🤖 Generated with Claude Code