Add regression tests for the bugs found in this smoke test:
- resolve_workspace: by-name, by-UUID, unknown-identifier, current-fallback,
actionable no-workspace message.
- DateTimePicker: selected-day highlight must be month-scoped; committing
after navigating months uses the selected month, not the viewed one.
- create_task: version is saturating_add on u64::MAX (doesn't panic/wrap).
Also fixes the three pre-existing clippy warnings (WorkspaceMode now uses
#[derive(Default)] + #[default], repository test drops unused binding,
sync test uses struct-update syntax instead of field-reassign-default).
onyx task edit wrote the task body to /tmp/onyx-<uuid>.md with the
default umask, leaving it world-readable on shared multi-user systems
for the duration of the editor session. Open with O_CREAT|O_TRUNC +
mode 0600 via OpenOptionsExt on unix; Windows keeps the existing
behaviour since unix-style mode bits don't apply.
When RUST_BACKTRACE was set in the environment, every user-facing error
dumped a 20-line Rust backtrace at the user — e.g. running 'onyx list
show' with no workspace gave them a stack trace through anyhow, clap,
and libc start. Replace 'fn main() -> Result' with an explicit error
printer that walks the anyhow cause chain using Display, and exits 1.
Programming-bug panics still surface through the default panic handler.
Three related CLI bugs found during smoke testing:
1. `get_repository` used `config.get_workspace(name)` which expects the
UUID string, so `onyx list create -w dev` or `onyx task add -w dev`
always failed with "Workspace 'dev' not found". Unified CLI resolution
into a single `resolve_workspace()` helper that accepts either the
display name or the UUID; removed sync.rs's duplicated local copy.
2. `workspace switch`/`remove`/`retarget`/`migrate` only accepted the
display name — the error message even suggested "Use the workspace ID
instead" on ambiguous names, but IDs were then rejected. Updated
`resolve_name` to try the map key first.
3. `onyx workspace add` never set `current_workspace`, so the very next
command failed with "No workspace set. Use 'onyx init'..." even
though a workspace was just created. Now sets the new workspace as
current whenever none was previously selected, and reports the fact.
Updated the error message to point at the correct `workspace add` /
`workspace switch` commands instead of `init`.
The complete(), delete(), and edit() functions each had an identical
loop searching for a task by ID across all lists. Extract a shared
find_task() helper that returns the list ID and task.
https://claude.ai/code/session_013ooJht2HrZUTXgNJFU79cV
The kebab menu and docs referred to a task "due date" but the field was
just a date; this change renames due_date/group_by_due_date and related
identifiers to date/group_by_date across Rust, TypeScript, Svelte, CLI,
docs and tests to keep terminology consistent. Updates include
API/command names, storage/models, repository methods, UI text, JS
variables and builder/parse functions so code, tests and documentation
all use "date" semantics.
Preserve old "group_by_due_date" field name
Add serde alias to ListMetadata.group_by_date so older .listdata.json
files that used the previous field name (group_by_due_date) can still be
deserialized correctly. This fixes serialization/deserialization issues
encountered at /home/trztn/Documents/Onyx and
/var/home/trztn/Nextcloud/Onyx.
the frontmatter due should be date... I don't want due anywhere
- Renamed `TaskFrontmatter.due` → `TaskFrontmatter.date`; YAML key on disk is now `date:` instead of `due:`
- Added `#[serde(alias = "due")]` so existing task files with `due:` frontmatter still deserialize correctly
- Updated google_tasks.rs to write `date:` instead of `due:` in generated YAML
- Renamed CLI `--due` flag to `--date`; updated function signature and display string "Due:" → "Date:"
Remove serde aliases and rename due→date
Drop backwards-compat aliases and update frontmatter/metadata to use the
canonical "date"/"group_by_date" fields. The aliases for
group_by_due_date and due were removed to avoid maintaining
backward-compatibility and to reflect the current schema. Updated
storage types to rename the fields and adjusted serialization attributes
so YAML/JSON frontmatter and .listdata.json files now use group_by_date
and date consistently.
- 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.
Change workspace identifiers from display names to UUID strings so
multiple workspaces can share the same display name. WorkspaceConfig now
stores a name field; add_workspace returns a generated UUID. Update all
CLI, Tauri commands, frontend stores and screens, WebDAV managed
directories, and tests to use/resolve workspace IDs; add helpers
find_by_name/resolve_name to map display names to IDs when needed. This
removes duplicate-name checks, avoids filesystem conflicts, and
preserves display names while using stable unique IDs internally.
- Handle Result from WebDavClient::new in CLI sync, core sync, and Tauri
- Unwrap Zeroizing<String> at Tauri serialization boundary
- Use .as_str() for basic_auth calls with Zeroizing<String> fields
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.