- crates/onyx-core/src/webdav.rs: rename `getpassword`/`setpassword`
(7 call sites) to `get_password`/`set_password` so `cargo build`
and the CLI compile again under the default `keyring-storage` feature.
- ConfirmDialog.svelte: intercept Escape at window capture phase and
expose a module-level open-count so TasksScreen's Escape handler can
defer; previously Escape on a dialog both dismissed the dialog AND
popped the task-detail view behind it. Cancel is also focused on
mount for keyboard users.
- TasksScreen.svelte: extend the taskStack cleanup effect to collapse
back to parent detail when only the subtask is gone (was leaving a
blank third panel); focus the new-list input when it appears; reset
the Completed section's expand state when switching lists.
- TaskDetailView.svelte: re-sync local title/description state when
the task prop's content changes (unless the user is editing), so a
sync pull doesn't get silently overwritten on next save. Bail out of
the parent delete if a subtask delete fails instead of orphaning.
- app.svelte.ts: deleteTask now returns a success boolean; move the
"No Date" group to the end of the grouped-by-date view so Overdue
and Today surface first.
- SetupScreen.svelte: strip trailing separators before splitting the
picked folder path so "…/MyTasks/" yields "MyTasks" instead of the
literal fallback "workspace".
Verified live under Xvfb for the three user-visible cases (ConfirmDialog
Escape, orphan subtask collapse, new-list autofocus). Screenshots in
screenshots/smoke-test/. cargo test --lib -p onyx-core is green
(162/162); npm run build succeeds.
The fields _client, _base_url, _username, _password were all actively
used throughout the struct's methods. The underscore prefix convention
signals unused fields, which was misleading for readers.
https://claude.ai/code/session_013ooJht2HrZUTXgNJFU79cV
Security:
- Fix path traversal via backslash bypass in sync validate_sync_path()
- Replace silent HTTP client fallback with proper error propagation
- Add 64KB YAML frontmatter size limit to prevent DoS via crafted files
Data integrity:
- Reorder delete operations: update metadata before removing files to
prevent orphaned metadata entries on crash
- Fix task deduplication to use file mtime as tiebreaker when versions
are equal, preventing non-deterministic data loss
- Add rollback on conflict recovery failure (remove orphaned duplicate
files when metadata update fails)
- Clean up temp files on atomic write rename failure
- Add file-based sync lock to prevent concurrent sync operations
- Use saturating_add for task version to prevent overflow
Error handling:
- Surface move_task rollback failures as structured errors instead of
silent warnings
- Log WebDAV parallel request failures instead of silently swallowing
- Emit watcher-error events to frontend instead of only printing to stderr
Frontend:
- Fix focus listener leak in auto-sync (clean up if stopAutoSync called
while promise pending)
- Add prefers-reduced-motion CSS media query for accessibility
- Add ARIA labels, roles, and keyboard handlers to TaskItem, BottomSheet,
and ConfirmDialog components
- Replace BottomSheet children: any with Snippet type
https://claude.ai/code/session_01AJoK28N4vqLqzskq6ybGri
Add WebDAV MOVE support and update workspace rename flow to handle both
local and WebDAV-backed workspaces. The Tauri rename_workspace command
is made async and now performs filesystem rename for local workspaces
and issues a WebDAV MOVE (via a new WebDavClient::move_resource) for
remote workspaces, updating stored paths and credentials accordingly. A
confirmation dialog is added to SettingsScreen to prompt users before
renaming, and minor UI/default tweaks are included (SetupScreen default
name). This ensures renames update both local folders and remote WebDAV
folders reliably and with user confirmation.
- Use :: separator in scoped keyring keys to prevent ambiguity with
usernames containing dots (e.g. com.onyx.webdav.host::user)
- Auto-migrate legacy credentials to scoped format on load, removing
old unscoped entries after successful migration
- Add 10MB response size limit on PROPFIND to prevent memory exhaustion
from malicious servers (checks Content-Length header + actual body)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Enforce HTTPS for WebDAV URLs (reject http:// to prevent plaintext credentials)
- Replace String with Zeroizing<String> for credential fields and load_credentials return
- Remove manual Drop impl (Zeroizing handles zeroize-on-drop automatically)
- Scope keyring password entries by domain+username to prevent collisions
- Add migration fallback for legacy unscoped keyring entries
- Sanitize error messages to not leak keyring service patterns or env var names
- Add log warnings when falling back to env var credentials
- Add log dependency to onyx-core
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Back up local files before overwriting during ConflictRemoteWins so data
is never silently lost. Fix false-positive change detection by parsing
timestamps before comparing (different formats like RFC3339 vs HTTP date
were never equal as strings). Add zeroize crate to zero WebDAV credentials
in memory on drop, preventing exposure in core dumps.
Make keyring optional behind keyring-storage feature in onyx-core.
Make notify/notify-debouncer-mini optional behind desktop feature in Tauri.
Gate all file watcher code behind #[cfg(not(target_os = "android"))].
Provide env-var-only credential fallbacks when keyring is disabled.