Document WebDAV sync, workspace theming, and credential hardening
Update CLAUDE.md to reflect completed WebDAV sync and expanded config/sync features. The docs now describe AppConfig fields (mode, theme, WebDAV URL), WorkspaceMode enum, WebDAV client details and credential handling (scoped keyring keys `com.onyx.webdav.<domain>::<username>` with auto-migration from legacy dot-separated format on load), three-way sync with a 60s timeout and auto-creation of the Onyx/ remote subfolder, a 10MB PROPFIND response cap, plus UI changes (setup flow, per-workspace theme options) and other sync/setup UI improvements.
This commit is contained in:
parent
fa87dbe12b
commit
513acc5606
18
CLAUDE.md
18
CLAUDE.md
|
|
@ -37,7 +37,9 @@ Two-crate workspace (`resolver = "2"`, edition 2021) plus a Tauri app:
|
||||||
|
|
||||||
- **Storage trait** (`storage.rs`): Strategy pattern for task persistence. `FileSystemStorage` reads/writes markdown files with YAML frontmatter and JSON metadata files.
|
- **Storage trait** (`storage.rs`): Strategy pattern for task persistence. `FileSystemStorage` reads/writes markdown files with YAML frontmatter and JSON metadata files.
|
||||||
- **Repository** (`repository.rs`): `TaskRepository` wraps a `Storage` impl and provides the public API for task/list CRUD, ordering, and grouping. Tests live here.
|
- **Repository** (`repository.rs`): `TaskRepository` wraps a `Storage` impl and provides the public API for task/list CRUD, ordering, and grouping. Tests live here.
|
||||||
- **Config** (`config.rs`): `AppConfig` manages named workspaces with paths. Stored in platform-specific config dirs via the `directories` crate.
|
- **Config** (`config.rs`): `AppConfig` manages named workspaces with paths, mode (local/webdav), theme, and WebDAV URL. Stored in platform-specific config dirs via the `directories` crate.
|
||||||
|
- **Sync** (`sync.rs`): Three-way diff sync with offline queue. Auto-appends `Onyx/` to WebDAV URL. Wrapped in `tokio::time::timeout` (60s) to handle unreachable servers on Windows.
|
||||||
|
- **WebDAV** (`webdav.rs`): reqwest client with rustls-tls, 30s request timeout, 10s connect timeout. Credentials stored via `keyring` crate (feature-gated). `Zeroizing<String>` for credential fields. Scoped keyring keys (`com.onyx.webdav.<domain>::<username>`); auto-migrates legacy dot-separated format on load. 10MB PROPFIND response cap.
|
||||||
|
|
||||||
### On-disk format
|
### On-disk format
|
||||||
|
|
||||||
|
|
@ -49,8 +51,8 @@ The GUI uses Svelte 5 runes mode (`$state`, `$derived`, `$effect`, `$props()`).
|
||||||
|
|
||||||
- **Sliding drawer**: Left panel (lists) slides with main content as one piece via `translateX`. 80vw wide. List items show checkmark for active list and chevron on hover.
|
- **Sliding drawer**: Left panel (lists) slides with main content as one piece via `translateX`. 80vw wide. List items show checkmark for active list and chevron on hover.
|
||||||
- **Three-panel slide**: Main content area is 300% wide with three panels (task list, task detail, subtask detail) that slide via `translateX` using a `taskStack` array. Stack depth 0 = list, 1 = task detail, 2 = subtask detail.
|
- **Three-panel slide**: Main content area is 300% wide with three panels (task list, task detail, subtask detail) that slide via `translateX` using a `taskStack` array. Stack depth 0 = list, 1 = task detail, 2 = subtask detail.
|
||||||
- **Settings popup**: Floating overlay card with backdrop, not a sliding panel.
|
- **Settings modal**: Per-workspace settings opened from workspace kebab menu. Shows WebDAV config (for webdav workspaces), sync controls, and theme selector.
|
||||||
- **Workspace switcher**: Custom drop-up menu in drawer footer (left), settings gear (right).
|
- **Workspace switcher**: Custom drop-up menu in drawer footer (left), kebab menu per workspace (right) with Settings option.
|
||||||
- **Task animations**: Grid-rows `0fr`/`1fr` trick for smooth collapse/expand. Module-level `animateInIds` Set coordinates expand-in after toggle.
|
- **Task animations**: Grid-rows `0fr`/`1fr` trick for smooth collapse/expand. Module-level `animateInIds` Set coordinates expand-in after toggle.
|
||||||
- **Inline editing**: Click task to edit, auto-save on blur. `debouncedSave` snapshots task before timer to prevent stale-reference errors on component destroy.
|
- **Inline editing**: Click task to edit, auto-save on blur. `debouncedSave` snapshots task before timer to prevent stale-reference errors on component destroy.
|
||||||
- **Kebab menus**: Tasks and lists use kebab menus with custom `ConfirmDialog` component (not native `confirm()`). "Move to..." is inline in the menu (not a submenu) to avoid overflow.
|
- **Kebab menus**: Tasks and lists use kebab menus with custom `ConfirmDialog` component (not native `confirm()`). "Move to..." is inline in the menu (not a submenu) to avoid overflow.
|
||||||
|
|
@ -60,7 +62,7 @@ The GUI uses Svelte 5 runes mode (`$state`, `$derived`, `$effect`, `$props()`).
|
||||||
### Current state (2026-04-03)
|
### Current state (2026-04-03)
|
||||||
|
|
||||||
- **Phase 1** (Core + CLI): Complete
|
- **Phase 1** (Core + CLI): Complete
|
||||||
- **Phase 2** (WebDAV sync): Backend done, CLI done, GUI wired (settings auto-populates credentials)
|
- **Phase 2** (WebDAV sync): Complete — CLI + GUI sync working, auto-creates `Onyx/` subfolder on remote
|
||||||
- **Phase 3** (GUI MVP): Complete
|
- **Phase 3** (GUI MVP): Complete
|
||||||
- **Phase 4** (Mobile): Tauri Android cfg-gated, needs `tauri android init` + build
|
- **Phase 4** (Mobile): Tauri Android cfg-gated, needs `tauri android init` + build
|
||||||
|
|
||||||
|
|
@ -73,7 +75,7 @@ The GUI uses Svelte 5 runes mode (`$state`, `$derived`, `$effect`, `$props()`).
|
||||||
- Sliding lists drawer with checkmark selection
|
- Sliding lists drawer with checkmark selection
|
||||||
- Settings popup overlay
|
- Settings popup overlay
|
||||||
- Workspace switcher drop-up with add/remove
|
- Workspace switcher drop-up with add/remove
|
||||||
- Dark mode (GNOME-style neutral grays, cyan-blue accent)
|
- Per-workspace theme system (System default, Light, Dark, Nord, Dracula, Solarized Dark) via CSS `data-theme` attribute
|
||||||
- Completed tasks section with animated show/hide
|
- Completed tasks section with animated show/hide
|
||||||
- Due date picker/editor (DateTimePicker in new task + task detail); `has_time: bool` field tracks whether time is set
|
- Due date picker/editor (DateTimePicker in new task + task detail); `has_time: bool` field tracks whether time is set
|
||||||
- Move task between lists (inline list in kebab menu, no submenu)
|
- Move task between lists (inline list in kebab menu, no submenu)
|
||||||
|
|
@ -81,11 +83,13 @@ The GUI uses Svelte 5 runes mode (`$state`, `$derived`, `$effect`, `$props()`).
|
||||||
- Group-by-due-date toggle per list (main panel kebab)
|
- Group-by-due-date toggle per list (main panel kebab)
|
||||||
- Delete completed tasks (main panel kebab + subtask kebab, with confirmation dialogs)
|
- Delete completed tasks (main panel kebab + subtask kebab, with confirmation dialogs)
|
||||||
- Keyboard shortcuts (Escape priority chain: settings → detail → list menu → drawer → menus)
|
- Keyboard shortcuts (Escape priority chain: settings → detail → list menu → drawer → menus)
|
||||||
- WebDAV setup flow (settings auto-populates URL/credentials from config + keychain)
|
- Setup screen with 2-step mode selection (Local Folder vs WebDAV Server), window dragging, "Open Existing Folder" option
|
||||||
|
- WebDAV setup flow with connection test, credential storage in system keychain
|
||||||
|
- WebDAV sync: auto-creates `Onyx/` subfolder on remote, 60s hard timeout, sync error display in settings
|
||||||
- File watcher (notify crate, 500ms debounce, auto-reloads on external changes)
|
- File watcher (notify crate, 500ms debounce, auto-reloads on external changes)
|
||||||
- Setup screen with window dragging + "Open Existing Folder" option
|
|
||||||
- Sync status indicators (last-sync time + upload/download counts chip)
|
- Sync status indicators (last-sync time + upload/download counts chip)
|
||||||
- Push/pull/full sync mode selection (session-only, in settings)
|
- Push/pull/full sync mode selection (session-only, in settings)
|
||||||
|
- WorkspaceMode enum (local/webdav) with per-workspace config
|
||||||
- Desktop packaging (Linux: AppImage + .deb; Windows: MSI)
|
- Desktop packaging (Linux: AppImage + .deb; Windows: MSI)
|
||||||
- Tauri desktop-only deps (notify, keyring) feature-gated for Android compilation
|
- Tauri desktop-only deps (notify, keyring) feature-gated for Android compilation
|
||||||
- Subtask hierarchy: subtask count shown on parent tasks in list, subtask detail via three-panel slide navigation, inline add at top of subtask list (new subtasks prepend), collapsible completed subtasks section, cascade delete (parent deletion removes all subtasks with confirmation warning)
|
- Subtask hierarchy: subtask count shown on parent tasks in list, subtask detail via three-panel slide navigation, inline add at top of subtask list (new subtasks prepend), collapsible completed subtasks section, cascade delete (parent deletion removes all subtasks with confirmation warning)
|
||||||
|
|
|
||||||
|
|
@ -318,6 +318,8 @@ let status = get_sync_status(Path::new("/home/user/tasks"))?;
|
||||||
|
|
||||||
Credentials are stored in the platform keychain (Windows Credential Manager, macOS Keychain, Linux Secret Service).
|
Credentials are stored in the platform keychain (Windows Credential Manager, macOS Keychain, Linux Secret Service).
|
||||||
|
|
||||||
|
Keyring service keys use the format `com.onyx.webdav.<domain>::<username>` — the `::` separator prevents key collisions when usernames contain dots. On first load, credentials stored in the legacy `.`-separated format (`com.onyx.webdav.<domain>.<username>`) are automatically migrated to the scoped format and the old entries are removed.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use onyx_core::webdav::{store_credentials, load_credentials, delete_credentials};
|
use onyx_core::webdav::{store_credentials, load_credentials, delete_credentials};
|
||||||
|
|
||||||
|
|
@ -363,6 +365,7 @@ client.delete_file("old-task.md").await?;
|
||||||
- **Conflict resolution**: Last-write-wins using file timestamps
|
- **Conflict resolution**: Last-write-wins using file timestamps
|
||||||
- **Offline queue**: Pending operations are queued and replayed when connectivity returns
|
- **Offline queue**: Pending operations are queued and replayed when connectivity returns
|
||||||
- **Sync state**: Stored in `.syncstate.json` within the workspace directory
|
- **Sync state**: Stored in `.syncstate.json` within the workspace directory
|
||||||
|
- **Response size cap**: PROPFIND responses are limited to 10 MB (checked via `Content-Length` header and actual body size) to prevent memory exhaustion from malicious servers
|
||||||
|
|
||||||
## Error Handling
|
## Error Handling
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue