fix(peer): preserve untracked download files

Reject exact manifest destinations that are not covered by the last committed ownership set before creating a baseline or parking version.ini. Align Windows device-name validation with the confined filesystem backend and keep cleanup capability-relative.

Replace recursive downloaded-game removal with an empty ownership generation. The operation now removes only proven-owned files and the sentinel, preserves unknown files and directories, and remains recoverable and idempotent across crashes.

Test Plan:
- just clippy
- just test
- just fmt (Rust, TOML, and Prettier completed; rumdl still reports 39 pre-existing issues)
This commit is contained in:
2026-08-09 19:46:10 +02:00
parent 691176e1d5
commit 08b1cb5c1d
10 changed files with 630 additions and 301 deletions
+8 -4
View File
@@ -185,10 +185,12 @@ Reserved per-game paths:
- `.lanspread_owned` inside `.local.*` directories proves Lanspread ownership
when the current intent is `None`.
Downloaded-file removal is not an uninstall transaction. It removes the whole
game root only for a catalog ID that is a single direct child of the configured
game directory, has a regular root-level `version.ini`, and has no `local/`,
`.local.installing/`, or `.local.backup/` path.
Downloaded-file removal is not an uninstall transaction. For a catalog ID that
is a single direct child of the configured game directory, it requires a valid
ownership record and regular root-level `version.ini`, and refuses `local/`,
`.local.installing/`, or `.local.backup/`. It journals an empty pending
generation, deletes only committed downloader-owned files and the sentinel, and
keeps the game root plus every unknown file or directory.
Recovery reads app-state `install_intent.json` and combines the recorded intent
with the observed `local/`, `.local.installing/`, and `.local.backup/` state.
@@ -214,6 +216,8 @@ Most scans become O(number of game dirs), with full recursion only when needed.
`ValidatedDownloadManifest` before any destination mutation. It contains
canonical game-root-relative paths and rejects aliases, reserved state, shape
conflicts, and bounded-size violations as one unit.
- A new manifest target that already exists without prior committed ownership is
rejected before the sentinel, ownership journal, or payload is mutated.
- Download mutation holds a capability handle for the direct catalog game root.
Directory components and final files are reopened relative to that handle
without following links or Windows reparse points; chunk writes and checks use