Skip to content

Commit e32f27a

Browse files
authored
Merge pull request #97 from gajendraxdev/fix/macos-keychain-prompts
Stabilize desktop identity and quiet passive keychain reads
2 parents eaed022 + 5862feb commit e32f27a

12 files changed

Lines changed: 490 additions & 56 deletions

File tree

.github/workflows/release.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,6 @@ jobs:
9696
- name: Install frontend dependencies
9797
run: npm ci --legacy-peer-deps
9898

99-
- name: Patch macOS Bundle ID
100-
if: matrix.platform == 'macos-latest'
101-
run: |
102-
node -e 'const fs=require("fs"); let c=JSON.parse(fs.readFileSync("src-tauri/tauri.conf.json")); c.identifier="com.zync.desktop"; fs.writeFileSync("src-tauri/tauri.conf.json", JSON.stringify(c, null, 2));'
103-
10499
- name: Build the app
105100
uses: tauri-apps/tauri-action@v0
106101
env:

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@ All notable changes to Zync are documented in this file. The format is based on
44

55
## [Unreleased]
66

7+
### Changed
8+
- **Canonical desktop app identity**: Standardized the Tauri bundle identifier to `in.thesudoer.zync` across platforms and added copy-only first-launch migration from legacy default app data/config directories (`zync`, `com.zync.desktop`) while preserving custom `dataPath` locations.
9+
710
### Fixed
11+
- **macOS Keychain prompt reduction**: Avoided passive status reads of OS credential-store secrets for Vault remember-device state, sync collection cache state, and Google sync status so macOS prompts are limited to real secret use instead of routine refreshes.
12+
- **Sync collection key recovery states**: Preserved first-time setup with provider-selected collection IDs while keeping remote relink failures explicit when no recoverable key wrap exists.
13+
- **Legacy Google token migration**: Preserved migration of plaintext refresh tokens into the OS credential store even when only metadata/status is read.
814
- **Command palette theme switching**: Preserved active plugin worker requester across quick-pick dispatches and fallback resolution, restoring `Preferences: Color Theme` selection from the command palette. ([e3f1732])
915
- **Default Dark theme in theme picker**: Added `builtin_dark` plugin registration and included `'dark'` in trusted built-in theme choices so `Dark (Default)` is available in the theme selection list and Appearance settings. ([e3f1732])
1016
- **Quick-pick lifecycle & abandonment cleanup**: Extracted `cancelActiveQuickPick` helper in `CommandPalette.tsx` to dispatch cancellation on `Escape`, backdrop close, mode switches, and before request replacement, preventing dangling worker promises. ([e3f1732])

docs/SETTINGS_SYSTEM.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ No local override file should be assumed active unless explicitly implemented in
7979

8080
If canonical native settings are missing, backend performs one-time migration from legacy candidates (for example old app-data path or `~/.zync/settings.json`).
8181

82+
The canonical Tauri bundle identifier is `in.thesudoer.zync`. On first launch after this identity change, backend performs a copy-only migration from legacy default app data/config directories for `zync` and `com.zync.desktop` when the new default directory is empty. User-configured `dataPath` values are respected and are not moved automatically.
83+
8284
## Key Files
8385

8486
### Frontend

src-tauri/src/commands.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,17 @@ fn get_legacy_settings_candidates(app: &AppHandle) -> Vec<std::path::PathBuf> {
145145
if let Ok(app_data_dir) = app.path().app_data_dir() {
146146
candidates.push(app_data_dir.join("settings.json"));
147147
}
148+
candidates.extend(
149+
crate::identity_migration::legacy_app_data_dir_candidates(
150+
app.path().app_data_dir().ok().as_deref(),
151+
)
152+
.into_iter()
153+
.map(|path| path.join("settings.json")),
154+
);
148155
if let Ok(home_dir) = app.path().home_dir() {
149156
candidates.push(home_dir.join(".zync").join("settings.json"));
150157
}
151-
candidates
158+
crate::identity_migration::dedupe_paths(candidates)
152159
}
153160

154161
/// Write file content atomically via temporary file + rename.
@@ -501,6 +508,12 @@ pub fn get_data_dir(app: &AppHandle) -> std::path::PathBuf {
501508
.unwrap_or_else(|_| std::path::PathBuf::from("."));
502509
let merged_settings =
503510
read_effective_settings(app).unwrap_or_else(|_| Value::Object(serde_json::Map::new()));
511+
let has_custom_data_path = merged_settings
512+
.get("dataPath")
513+
.and_then(|v| v.as_str())
514+
.is_some_and(|value| !value.trim().is_empty());
515+
516+
crate::identity_migration::migrate_default_dirs(app, &default_dir, has_custom_data_path);
504517

505518
let (resolved, cache_result) =
506519
if let Some(data_path) = merged_settings.get("dataPath").and_then(|v| v.as_str()) {

0 commit comments

Comments
 (0)