fix(desktop): restrict shared-agent sync to dev data dirs#1597
Merged
Conversation
sync_shared_agent_data's only guards were environmental (BUZZ_SHARE_IDENTITY=1 + a parseable BUZZ_PRIVATE_KEY), so a release build with the prod bundle identifier launched from an env-armed shell (macOS `open` passes the caller's env) ran the dev shared-roster sync against the prod data dir — deleting the real agent stores with no backup. - Gate the sync on the data-dir name: is_dev_data_dir_name (exact canonical dev identifier or dot-separated worktree suffix), shared by run_boot_migrations, sync_shared_agent_data, and reconcile_target_dir. - Back up real files/dirs to timestamped .bak.* names (ms precision, collision-probed) instead of deleting; roll the backup back if the symlink fails; route the sibling seed path through the same helper. - Extract create_symlink/symlink_points_to/backup_path/ replace_with_symlink into util.rs and adopt them in repos.rs and nest.rs where behavior-preserving.
2bd823f to
4ef8350
Compare
tlongwell-block
pushed a commit
that referenced
this pull request
Jul 7, 2026
* origin/main: docs(readme): add Getting started section routing install paths (#1606) fix(desktop): restrict shared-agent sync to dev data dirs (#1597) feat(desktop): restart-required badge from spawn-time config hash (#1602) feat(desktop): boot-time reconcile of managed agents to relay events (#1601) feat(desktop): canonical <PubKey> component — hover to view/copy full keys, owner "you" labels (#1589) fix(desktop): hydrate reactions for Inbox context messages (#1596) fix: cleanup old screenshots that my agents committed (#1598) chore(release): release Buzz Desktop version 0.3.46 (#1585) fix(desktop): preserve agent model/provider when persona snapshot fields are blank (#1583) feat(acp,desktop): identify and reap stale agent harness processes (#1582) feat(desktop): active-draft badge, send-from-drafts confirm dialog, thread-deleted state (#1581) fix(desktop): treat baked build env vars as satisfying required agent config (#1580) feat(desktop): add "Copy image" to image right-click context menu (#1579) fix(nest): use buzz-dev symlink name for dev builds (#1587) fix(composer): address image-editor follow-up nits on #1491 (#1565) fix(desktop): render black static boot screen (#1570) feat(agents): group activity tool bursts (#1571) feat(desktop): aggregated overview rail, commit detail page, and full breadcrumbs (#1573) fix(desktop): fetch profiles for reaction actors and thread-reply authors (#1550)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
this bit me on 2026-07-07: with
BUZZ_SHARE_IDENTITY=1and a validBUZZ_PRIVATE_KEYin my shell, i ranopenon ajust desktop-release-buildartifact. macOSopeninherits the caller's environment, so the release build'ssync_shared_agent_datasaw the dev-share env vars and happily synced againstxyz.block.buzz.app— the prod data dir. it deleted the realmanaged-agents.json,personas.json, andteams.jsonwith no backup and replaced them with symlinks into the dev store.two-part fix, now fully landed:
dev-dir guard — extracted
is_dev_data_dir_name(name: &str) -> booland added it as an early-return guard insync_shared_agent_data. it now returns immediately if the data dir name is not the canonical dev identifier (xyz.block.buzz.app.dev) or a dot-separated worktree variant (xyz.block.buzz.app.dev.my-branch). prefix collisions likexyz.block.buzz.app.developercorrectly fail the check. the same predicate is now shared byrun_boot_migrationsandreconcile_target_dir, replacing their inlinestarts_withchecks.backup-before-replace — introduced
replace_with_symlink(moved into the sharedutil.rsmodule so other features can use it). when the destination is a real file or real directory, it renames it to<full-filename>.bak.<yyyymmdd-HHMMSS.ms>before creating the symlink. timestamps are millisecond-precision with a collision-safe-2…-100suffix probe. if the backup succeeds but the symlink creation fails, the helper attempts to rename the backup back and logs an actionable error if that rollback also fails. wrong or broken symlinks are still just removed — they carry no data worth backing up. the first-time sibling-dir seed block now goes through the same safe helper. stale-symlink removal logs on failure instead of silently discarding the error.the shared
util.rsmodule also exposescreate_symlink(the unix/non-unix cfg wrapper) andsymlink_points_to(raw link-value comparison without canonicalization, needed for relative symlink targets).repos.rsandnest.rsadopt these where the refactor is behavior-preserving;ensure_repos_symlink's "refuse non-empty real dir" policy stays unchanged since it has different semantics from backup-and-replace.tempfilestays in[dependencies]—nest.rsusestempfile::NamedTempFilein production code for atomic writes toAGENTS.mdandSKILL.md.tests: 9 new tests in total — 4 predicate tests for
is_dev_data_dir_name(including the prefix-collision case) and 5 helper-behavior tests forreplace_with_symlink(file backup, dir backup, correct-symlink no-op, wrong-symlink replace, broken-symlink replace). full suite: 1011 passed, 0 failed.