Skip to content

feat(storage): add custom data path and safe migration - #1294

Merged
vastsa merged 4 commits into
mainfrom
feat/custom-storage-location-1213
Oct 2, 2026
Merged

vastsa merged 4 commits into
mainfrom
feat/custom-storage-location-1213

Conversation

@vastsa

@vastsa vastsa commented Oct 2, 2026

Copy link
Copy Markdown
Owner

Closes #1213

Adds a configurable storage location in Settings and a cold-start migration that copies and verifies desktop and Chromium data before switching the active roots. The migration window reports stages and file/byte progress; the original data remains available as a backup until the user explicitly removes it. Settings also provides safe cache cleanup for rebuildable cache paths.

Validation on the task candidate:

  • Desktop production build and TypeScript checks
  • 731 host-core tests, Clippy, and Rust formatting
  • Storage maintenance, settings, migration, and bootstrap tests/E2E
  • i18n tests, Biome, style-token checks, and PR-base check

Move desktop and Chromium state through a cold, verified migration so host and browser data stay consistent across drives. Keep the original roots as backups until explicit cleanup, and limit cache clearing to rebuildable paths.
Copilot AI balanced review requested due to automatic review settings October 2, 2026 02:30
Keep the architecture decision discoverable and satisfy the docs index check.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Failed copies can become untracked, destination permissions can expose credentials, and several user-facing errors remain unlocalized.

Review effort: Balanced
Findings: 1 High severity · 1 Medium severity · 3 Low severity

Open (5)
What changed in this PR

Adds configurable storage relocation for issue #1213, including cold migration, cache maintenance, backup cleanup, localized Settings UI, and startup integration.

Changes:

  • Adds verified file copying and Rust-owned persisted-path relocation.
  • Adds storage IPC, Settings controls, localization, and release notes.
  • Adds unit, integration, and Electron E2E coverage plus specifications.
File Description
scripts/​e2e/​storage-settings.jsx Exercises storage Settings interactions.
scripts/​e2e-storage-settings.mjs Runs isolated Settings Electron E2E.
scripts/​e2e-storage-migration.mjs Tests end-to-end host migration.
scripts/​e2e-storage-bootstrap.mjs Tests cold Electron bootstrap.
packages/​shared/​src/​storage.ts Defines storage IPC data types.
packages/​shared/​src/​protocol.ts Adds storage IPC channels.
packages/​shared/​src/​index.ts Exports storage types.
packages/​shared/​src/​changelog-zh-TW.ts Adds Traditional Chinese release note.
packages/​shared/​src/​changelog-zh-CN.ts Adds Simplified Chinese release note.
packages/​shared/​src/​changelog-tr.ts Adds Turkish release note.
packages/​shared/​src/​changelog-pt-BR.ts Adds Portuguese release note.
packages/​shared/​src/​changelog-ko.ts Adds Korean release note.
packages/​shared/​src/​changelog-fr.ts Adds French release note.
packages/​shared/​src/​changelog-es.ts Adds Spanish release note.
packages/​shared/​src/​changelog-en.ts Adds English release note.
packages/​shared/​src/​changelog-de.ts Adds German release note.
packages/​i18n/​test/​catalogs.test.mjs Validates maintenance translations.
packages/​i18n/​src/​locales/​zh-TW/​index.ts Adds Traditional Chinese storage copy.
packages/​i18n/​src/​locales/​zh-CN/​index.ts Adds Simplified Chinese storage copy.
packages/​i18n/​src/​locales/​tr/​index.ts Adds Turkish storage copy.
packages/​i18n/​src/​locales/​pt-BR/​index.ts Adds Portuguese storage copy.
packages/​i18n/​src/​locales/​ko/​index.ts Adds Korean storage copy.
packages/​i18n/​src/​locales/​fr/​index.ts Adds French storage copy.
packages/​i18n/​src/​locales/​es/​index.ts Adds Spanish storage copy.
packages/​i18n/​src/​locales/​en/​index.ts Adds English storage copy.
packages/​i18n/​src/​locales/​de/​index.ts Adds German storage copy.
package.json Registers storage E2E suite.
docs/​spec/​06-delivery/​04-e2e-test-plan.md Documents storage E2E coverage.
docs/​spec/​04-ux/​06-settings-ia.md Specifies storage Settings behavior.
docs/​spec/​03-runtime/​04-data-storage.md Specifies migration and cleanup semantics.
docs/​adr/​custom-storage-location.md Records the storage architecture decision.
docs/​adr/​0094-single-instance-per-data-directory.md Amends locking architecture.
crates/​host-core/​src/​main.rs Adds offline relocation CLI dispatch.
crates/​host-core/​src/​data_relocation/​tests.rs Tests persisted-path relocation.
crates/​host-core/​src/​data_relocation.rs Implements offline Rust relocation.
apps/​desktop/​test/​storage-maintenance.test.mjs Tests migration and cleanup safety.
apps/​desktop/​test/​single-instance.test.mjs Tests revised startup locking.
apps/​desktop/​test/​development-profile.test.mjs Updates profile bootstrap contracts.
apps/​desktop/​src/​styles/​settings.css Styles storage controls and confirmation.
apps/​desktop/​src/​lib/​settings-search.ts Adds storage search terms.
apps/​desktop/​src/​lib/​api.ts Exposes storage renderer APIs.
apps/​desktop/​src/​features/​settings/​StorageSettingsSection.tsx Implements storage Settings UI.
apps/​desktop/​src/​features/​settings/​SettingsPage.tsx Mounts the storage section.
apps/​desktop/​electron/​main/​storage/​preferences.ts Persists storage bootstrap state.
apps/​desktop/​electron/​main/​storage/​ipc.ts Implements storage IPC handlers.
apps/​desktop/​electron/​main/​storage/​files.ts Implements copying and cleanup.
apps/​desktop/​electron/​main/​storage/​bootstrap.ts Runs cold maintenance at startup.
apps/​desktop/​electron/​main/​ipc/​register.ts Registers storage IPC.
apps/​desktop/​electron/​main/​installation.ts Extracts installation identity and locking.
apps/​desktop/​electron/​main/​index.ts Uses prepared storage and restart workflow.
apps/​desktop/​electron/​main/​host-process.ts Exports host binary resolution.
apps/​desktop/​electron/​main/​entry.ts Adds pre-runtime storage bootstrap entry.
apps/​desktop/​electron.vite.config.ts Switches Electron’s main entrypoint.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +23 to +29
export async function validateTarget(path: string, source: StorageRoots, anchor: string, retryId?: string): Promise<string> {
if (!isAbsolute(path) || path.includes("\0")) throw new Error("Select an absolute directory.");
const target = await realpath(path);
if (!(await lstat(path)).isDirectory() || (await lstat(path)).isSymbolicLink()) throw new Error("Select a real directory, not a symbolic link.");
for (const sourcePath of [source.data, source.browser, anchor]) {
const canonical = await canonicalPath(sourcePath);
if (contains(canonical, target) || contains(target, canonical)) throw new Error("The destination must be separate from the current storage directories.");
Comment on lines +81 to +85
writeStoragePreferences(file, { version: 1, roots: next,
backups: [...preferences.backups, {
data: existsSync(preferences.roots.data) ? await realpath(preferences.roots.data) : preferences.roots.data,
browser: await realpath(preferences.roots.browser),
}] });
Comment on lines +38 to +39
await dialog.showMessageBox({ type: "error", title: copy.failedTitle,
message: copy.unavailableHint, detail: error instanceof Error ? error.message : String(error) });
<Button disabled={disabled} onClick={() => void confirm()}>{busy ? t("settings.storage.restarting") : t(confirmation === "migrate" ? "settings.storage.migrateRestart" : confirmation === "cache" ? "settings.storage.cacheRestart" : "settings.storage.backupRestart")}</Button>
</div>
</div> : null}
{error ? <p className="settings-storage-message error" role="alert">{t("settings.storage.operationError", { error })}</p> : null}
Comment thread packages/shared/src/changelog-ko.ts Outdated
version: "0.15.9",
date: "2026-09-27",
highlights: [
"설정에서 데이터 저장 위치를 지정하고 이전 진행률을 확인하며 재생성 가능한 캐시를 안전하게 정리하세요.",
Place the storage migration highlight in the current release so every locale has the same versioned highlight count.
Assert application identity and early error handlers where the startup split installs them, while preserving the logger wiring check in the composition root.
@vastsa
vastsa merged commit 3e34ca0 into main Oct 2, 2026
5 checks passed

This branch was previously deployed

1 inactive deployment
Preview — 600f4840 Deployed Oct 2, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] 增加自定义缓存路径的选项

2 participants