Skip to content

fix(imports): support weak storage moves - #864

Draft
therobbiedavis wants to merge 3 commits into
canaryfrom
fix/827-compatible-publication
Draft

fix(imports): support weak storage moves#864
therobbiedavis wants to merge 3 commits into
canaryfrom
fix/827-compatible-publication

Conversation

@therobbiedavis

Copy link
Copy Markdown
Collaborator

Summary

Allows imports from filesystems that cannot expose durable file or directory generation identity. A requested move now degrades to a verified copy that explicitly retains the source, instead of blocking the import, while durable-storage moves keep their existing source-retirement contract.

Fixes #852
Related to #827

Changes

Added

  • Added a configurable weak-storage publication policy that defaults to CopyAndRetainSource and can be disabled.
  • Added a compatibility publication journal and startup reconciliation for content-verified, additive-only imports.
  • Added path-only registration leases and recovery ownership for primary audio files and unregistered companion files.
  • Added root-folder and import UI disclosures that state weak-storage moves copy files and retain the source.

Changed

  • Source capability checks now fall back to a content-only proof when durable filesystem identity is unsupported.
  • Manual and automatic imports now report requested action, effective action, source disposition, and warning details.
  • Primary audio files, tracked audio companions, and unregistered companions share the same publication-policy decision while retaining distinct recovery ownership.
  • Deferred download cleanup downgrades remove_and_delete to non-destructive client removal when any imported source was retained.

Fixed

  • Fixed NFS/CIFS imports being rejected solely because the storage cannot expose a durable file handle or inode generation.
  • Fixed durable cross-volume companion publication recovery so registration state is committed before exact source retirement.
  • Fixed weak-storage destination planning so an existing byte-identical but unowned pathname is not adopted as ownership proof.

Testing

  • dotnet build listenarr.slnx --no-restore
  • dotnet test listenarr.slnx --no-build --no-restore — 2,952 passed, 202 skipped
  • Production service graph validation with ValidateScopes and ValidateOnBuild
  • Focused publication, compatibility recovery, cleanup, companion, architecture, hosted-service, and migration-schema tests
  • dotnet ef migrations has-pending-model-changes ... --no-build — no pending model changes
  • dotnet format listenarr.slnx --no-restore --verify-no-changes --verbosity minimal
  • npm run test:unit -- --run — 89 files, 597 tests passed
  • npm run build, npm run lint:check, and npm run format:check
  • Native Linux weak-publication/recovery and real cross-volume companion verification
  • Docker Linux compatibility/recovery verification
  • Real NFSv4 and CIFS/SMB3 publication verification for both primary and companion files

Notes

  • The compatibility path is intentionally additive-only: it never overwrites an existing destination and never deletes the source.
  • A weak-storage Move is therefore successful as Copy with SourceDisposition=Retained; this is surfaced before import in the UI and after import in API/job history.
  • The final Windows test run is on this commit. Linux, Docker, NFSv4, and CIFS/SMB3 checks were run during implementation; a final full-source Docker mount was not repeated because the execution environment blocked exposing the repository read-write to an external container.

- copy and retain sources when durable identity is unavailable
- journal compatibility publications and recover registration state
- disclose effective move policy across API and UI
@therobbiedavis therobbiedavis added the patch patch version bump - backward compatible bug fixes label Aug 21, 2026
- Keep identity-state tests independent of Linux mount probing
- Preserve dedicated coverage for storage access capability
- Avoid re-reading a nullable journal property inside the EF query
- Make committed-publication ownership checks statically non-null
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

patch patch version bump - backward compatible bug fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A cross-volume Move is refused deliberately, but the refusal is invisible, so the import just never happens

1 participant