Protect restore planning from symlinks

This commit is contained in:
2026-09-02 00:51:19 +00:00
parent 1e418d6929
commit 45b27ad562
6 changed files with 201 additions and 23 deletions

View File

@@ -37,8 +37,12 @@ Planner behavior:
generation. Coherent legacy state remains on the isolated compatibility path;
- remote-to-local mapping is traversal-safe;
- actions are sorted by local relative path and then remote key;
- planning opens the selected session root and inspects every target by its
normalized session-relative path. Missing ancestors produce a missing target;
an ancestor or leaf symlink is a non-regular conflict and is never opened for
hashing;
- force converts differing eligible regular files from conflicts to downloads;
directories and other non-regular targets remain conflicts.
directories, symlinks, and other non-regular targets remain conflicts.
For a non-dry-run restore, planning/classification happens only after acquiring
the session lock. Runner manifest/reuse checks acquire that same lock first.

View File

@@ -445,7 +445,11 @@ Optional:
- `--include-audio` to include `audio/**`
- `--force` to overwrite eligible conflicting regular files; it never replaces
directories or other non-regular local targets
directories, symlinks, or other non-regular local targets
Restore treats a local leaf symlink or any symlinked ancestor beneath the
selected session root as a conflict, even when the linked content matches the
selected remote object. `--force` does not override that conflict.
Restore writes an execution report at `reports/restore-latest.json`.

View File

@@ -416,7 +416,7 @@ recursive traversal, no-follow handle chains, and sorting machinery.
## Stage 5 — Make Restore Planning Symlink-Safe And Root-Relative
**Status: Pending**
**Status: Completed**
### Goal

View File

@@ -549,6 +549,8 @@ Symptom:
Likely cause:
- local durable files differ from remote restore sources.
- a restore target or one of its ancestors is a symlink or another non-regular
filesystem entry.
Diagnostics:
@@ -559,7 +561,8 @@ narratio session restore 2026-04-04 --dry-run
Safe fix:
- review conflicts;
- rerun with `--force` only when remote state should overwrite local.
- rerun with `--force` only when remote state should overwrite an eligible
regular local file; repair a symlink or other non-regular conflict first.
Relevant reference: [Operations: Restore Workflow](./operations.md#restore-workflow).