snapshot-scope.d — extra state for state-snapshot.sh save / restore
===================================================================

state-snapshot.sh reads every *.list here (one per lane: <lane>.list) and
adds those paths to every restore point it saves, restores and fingerprints.
Implementation and tests: lib/snapshot-scope.sh,
scripts/tests/go-port-fixtures/run.sh.

Line format (`#` lines and blank lines are ignored)

    <abs path> [preserve | truncate-to-length | fingerprint:<cmd>]

  preserve (default)  saved in the restore point; restore mirrors it back
                      (rsync --delete). A path that did not exist at save time
                      is removed on restore. A trailing `/**` is accepted.
  truncate-to-length  an append-only file (a log): ONLY its length (decimal
                      bytes) is recorded, not its content; restore truncates it
                      back to that length, assuming the earlier bytes were not
                      rewritten.
                      A file that shrank below it makes the restore refuse.
  fingerprint:<cmd>   state too big or too live to save (a mail server's data
                      dir). <cmd> (bash -c, one line; $SNAPSHOT_FS_ROOT is
                      empty on the VM) is hashed at save time; before a restore
                      touches anything it must hash the same, otherwise the
                      restore REFUSES and names the path (the cure is the
                      Proxmox rollback, as for the existing drift guard).

Rules
  * The path must be absolute, use only [A-Za-z0-9._+@:/-], and sit STRICTLY
    BELOW /docker, /srv, /var/lib/whp, /var/log or /etc/whp (a root itself is
    refused: it would sweep up customer data). `..`, `.` and empty components
    are refused outright, and the path after symlink resolution (realpath -m)
    must still be below one of those roots. The resolved path is what is
    stored and acted on, and the manifest is re-validated at restore.
  * A bad line refuses the whole save (nothing is stopped or written) and the
    message names <file>:<line>.
  * PHP code paths only, as root over SSH, no customer data, idempotent: one
    file per lane, `<lane>.list`. State outside these roots (containers, OS
    users, the haproxy volume) is the Proxmox snapshot's job.
  * Every restore point is a full snapshot, so a lane's list also applies to
    `baseline-seeded` and to every named point (`<lane>-<what>`).
