feat(domain): package commands CRUD + cascade actions (task 27)

Merged
MP
6mo ago
+3113-35

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

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_download and find_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); emits package-created, package-updated, package-deleted.
    • Hardening: FK ownership validated before detach; reassignment emits PackageUpdated for 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-updated and package-deleted in the UI.
    • Use new IPC commands for package actions; apply folder changes via the three-state patch.
    • For cascades: use set_package_priority; update_package does not cascade.
    • Move-to-folder requires absolute destinations.

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.