feat(domain): package commands CRUD + cascade actions (task 27)
Summary
Implements Task 27: nine command handlers for package management (create, update, delete, set password, set priority, move folder, toggle auto-extract, add/remove downloads). All handlers wired through CommandBus and exposed via Tauri IPC. Package FK management via new attach_download/detach_download port methods. Domain events emitted for updates and deletes. Unblocks Task 28 (Queries) and Task 29 (Package UI).
Why
Complete CRUD foundation for packages. Cascade operations (priority → children, move → children) ensure consistency. Keyring-only password storage prevents secrets in SQLite. FK management (attach/detach) replaces manual patching with atomic repository semantics.
Changes
- Command Handlers (9): create_package.rs, update_package.rs, delete_package.rs, set_package_password.rs, set_package_priority.rs, move_package_to_folder.rs, toggle_package_auto_extract.rs, add_download_to_package.rs, remove_download_from_package.rs
- Domain Events (2): PackageUpdated, PackageDeleted (forwarded to frontend as package-updated, package-deleted)
- Repository Port: attach_download, detach_download methods for FK singleton management
- SQLite Adapter: Implement attach/detach via UPDATE downloads SET package_id
- CommandBus: Add with_package_repo builder and accessor
- Tauri IPC (9 commands): Wire handlers with PackagePatch three-state folder semantics (Some(Some(x)) set, Some(None) clear, None unchanged)
- Event Bridges: tauri_bridge and download_log_bridge match new events
- Test Support: InMemoryPackageRepo, InMemoryDownloadRepo (updated), InMemoryCredentialStore, build_package_bus factory
Testing
cargo test --workspace # 1257 pass / 0 fail
cargo clippy -- -D warnings # Clean
cargo fmt --check # Clean
43 application tests + 5 SQLite tests = ≥94% per-handler coverage (target: 85%)
- Cascade validation: priority set emits DownloadPrioritySet per child, skips dangling FK
- Delete modes: delete_downloads=true removes children, false detaches
- Password: keyring only (never SQLite)
- Folder path: three-state mutation (set/clear/unchanged)
Related Issues
- Closes #27
Notes for Reviewer
Large commit (2510 insertions, 21 files) — review by handler is suggested:
- Password/keyring semantics crucial (package_credential_service_key helper)
- Cascade logic in set_priority loops members; skip with debug log on dangling FK
- delete_package has two paths (detach vs remove via RemoveDownloadCommand)
- move_package_to_folder reuses ChangeDirectoryCommand (task 13 logic per child)
- Folder path mutation (Option<Option>) supports three states
Checklist
- Tests added and passing (1257 / 0 fail, ≥94% coverage)
- Docs updated (CHANGELOG.md, inline comments)
- No secrets committed (keyring-only passwords)
- Self-reviewed diff
- Clippy / fmt clean
Summary by cubic
Implements full package management for Task 27 with nine commands, robust keyring-only passwords (rollback and previous-secret restore on failure), cascades for priority and folder moves, and stricter invariants for download attach/detach. Adds repo support, IPC endpoints, and events so the UI can manage packages and stay in sync.
-
New Features
- Nine commands: create, update, delete, set password (keyring-only with rollback + previous-secret restore), set priority (cascades), move to folder (cascades, rejects relative paths), toggle auto-extract, add/remove download.
- Repository port:
attach_download/detach_downloadandfind_package_of_download; SQLite adapter implements all. - IPC and events: nine package commands wired; folder path uses three-state patch (
Some(Some),Some(None),None); emitspackage-created,package-updated,package-deleted. - Hardening: FK ownership validated before detach; reassignment emits
PackageUpdatedfor both source and destination; keyring failures roll back the marker and restore the previous secret; same-package reattach is a no-op that preserves order; relative folder paths are rejected.
-
Migration
- Listen for
package-updatedandpackage-deletedin the UI. - Use new IPC commands for package actions; apply folder changes via the three-state patch.
- For cascades: use
set_package_priority;update_packagedoes not cascade. - Move-to-folder requires absolute destinations.
- Listen for
Summary by CodeRabbit
-
New Features
- Full package management: create, update, delete, move packages; set/clear package passwords; set priority; toggle auto-extract; add/remove downloads; per-download move outcomes.
- Frontend receives real-time package events for updates and deletions.
- Account improvements: category-filtered Accounts UI, import/export with rollback, quota-based rotation and configurable auto-selection strategies.
-
Documentation
- Expanded changelog documenting packages, accounts, and selection behaviors.