- Replace 2 production unwrap() calls in workspace.rs with proper error
handling to prevent panics on inconsistent state
- Add AppState::save_config() helper to eliminate 11 duplicated
save_to_file patterns in Tauri lib.rs
- Log file watcher errors instead of silently swallowing them
- Harden path traversal check in storage.rs: re-verify after
canonicalization to catch symlink escapes
- Add Windows reserved device name handling (CON, NUL, etc.) to
sanitize_filename
- Clean up stale .tmp files from interrupted atomic writes on startup
All 107 core tests pass.
https://claude.ai/code/session_01EnSrQsowc64rAwzD9BnJpc
Remove created_at/updated_at from Task struct and frontmatter. Add a
version counter (u64) that increments on every write, defaults to 1 for
old files. list_tasks now groups by UUID and auto-deletes stale
duplicates (keeping highest version), preventing sync-induced dupes from
surfacing in the UI. has_time and parent are omitted from frontmatter
when false/null.
Update CLI, Tauri frontend types, and Svelte components to match.
Rework WebDAV workspace setup to use .onyx-workspace.json instead of
.metadata.json and to let users pick a remote folder instead of forcing
an Onyx/ subfolder. This updates storage, sync, config types, tests, and
CLI/Tauri commands to store a webdav_path in WorkspaceConfig and to
combine webdav_url + webdav_path for sync.
Changes include:
- Rename .metadata.json → .onyx-workspace.json across storage, sync, and tests so workspace detection and root metadata use the new filename.
- Remove hardcoded automatic "Onyx/" subfolder in sync and use the user-selected remote path directly.
- Add webdav_path field to WorkspaceConfig (Rust and TypeScript types) and thread it through add_webdav_workspace and frontend addWebdavWorkspace.
- Add three Tauri commands (list_remote_folder, inspect_remote_workspace, create_remote_workspace) to support remote folder browsing, workspace preview, and remote workspace creation.
- Rewrite SetupScreen WebDAV flow to Connect → Browse (lazy folder explorer) → Preview or Create, and wire UI state/handlers to the new commands.
- Update CLAUDE.md to document the new on-disk filename and note development phase allowing breaking changes.
Add rollback to move_task: if delete-from-source fails after write-to-
destination, clean up the duplicate. Reject list names with path separators
or '..' to prevent traversal; canonicalize() failures now return errors
instead of silently falling back to unchecked paths. Add validation and
rollback to CLI workspace migration: check destination is empty, track
moved files, and reverse on failure.
Validate that resolved list paths stay within the workspace root to prevent
directory traversal via malicious list names. Enable Content Security Policy
in Tauri config instead of leaving it null. Fix CLI domain extraction to
strip userinfo (user:pass@) from URLs before using as keyring service name.
Replace the hours==0 && minutes==0 heuristic with an explicit has_time
bool field on Task. Existing files without the field deserialize as false
(date-only), preserving current behavior. Frontend components pass and
receive has_time through DateTimePicker's onchange callback.
Add TaskRepository::move_task() to move tasks between lists and
rename_list() to rename lists on the filesystem. Adds rename_list
to the Storage trait with FileSystemStorage implementation.
Includes tests for both operations plus duplicate-name error case.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>