Why: - Remote and UI-echoed file descriptions could reach transaction and storage code one entry at a time, so a hostile late path could mutate earlier files. - Per-file consensus also accepted malformed peer lists and let duplicate rows inflate a source's vote. What: - Add a complete protocol-7 manifest adapter with catalog-root confinement, portable path and alias rules, reserved-path protection, shape and size caps, symlink/reparse inspection, and zero-mutation tests. - Keep download selection in the peer core, validate every peer manifest before consensus, and pass only the validated manifest into storage/orchestration. - Canonicalize locally advertised paths, cap exact chunk receives, and preserve the local-only install fast path. - Record the chosen safety limits and follow-up ownership/catalog decisions. Test Plan: - just clippy - just test - just frontend-test - just build - just fmt (Rust/TOML/Prettier completed; rumdl reports 39 pre-existing issues) - git diff --cached --check
72 lines
3.6 KiB
Markdown
72 lines
3.6 KiB
Markdown
# Peer authentication refactor decisions
|
|
|
|
This file records implementation choices that are not fully determined by
|
|
`PEER_AUTH_PLAN.md`, especially choices where every available option has a
|
|
meaningful downside.
|
|
|
|
## 2026-08-09 — Bound protocol-7 download descriptions generously
|
|
|
|
**TL;DR:** Until catalog manifests replace remote descriptions, accept at most
|
|
100,000 entries, 1 TiB per ordinary file, 64 KiB for the in-memory `version.ini`
|
|
sentinel, 255 bytes per path component, 900 bytes per relative path, and 16 TiB
|
|
in aggregate for one game. Resolved destinations are capped at 1,000 platform
|
|
path units.
|
|
|
|
The plan requires count, per-file, and aggregate limits but intentionally does
|
|
not prescribe values. These limits are far above the expected game and CLI
|
|
fixture sizes while bounding allocation, planning work, and arithmetic.
|
|
|
|
Alternatives:
|
|
|
|
- Lower product-sized limits would reject abusive inputs earlier, but risk
|
|
inventing constraints that real large games or mod packs exceed.
|
|
- Limits near `usize`/`u64` maxima avoid practical compatibility concerns, but
|
|
do not meaningfully bound memory or work.
|
|
- Configurable limits add settings and test combinations without a current user
|
|
need; protocol safety limits should be consistent between installations.
|
|
|
|
## 2026-08-09 — Track download ownership; never infer it from unknown files
|
|
|
|
**TL;DR:** Persist an atomic per-game set of successfully downloaded paths under
|
|
application state. On replacement, remove only paths in the previous owned set
|
|
that are absent from the new authoritative manifest. If old or corrupt state has
|
|
no trustworthy set, preserve unknown root files.
|
|
|
|
The existing game directory has no provenance information. Deleting every
|
|
non-reserved path would remove stale downloads, but could also delete a user's
|
|
own files and contradict the plan's preservation rule. The first update after
|
|
upgrading may therefore leave legacy stale files; subsequent successful
|
|
downloads have exact ownership and can clean safely.
|
|
|
|
Alternatives:
|
|
|
|
- Bootstrap ownership from the current directory. This is seamless, but can
|
|
permanently misclassify user files as Lanspread-owned and later delete them.
|
|
- Delete every non-reserved file missing from the new manifest. This is simple
|
|
and cleans legacy state completely, but is unsafe for user files.
|
|
- Delete only familiar archive suffixes such as `.eti`. This avoids most user
|
|
files, but bakes package naming guesses into the security boundary and cannot
|
|
clean general catalog payloads.
|
|
- Never clean stale files. This is safest for user data, but fails the explicit
|
|
successful-replacement requirement and can keep serving obsolete payload.
|
|
|
|
## 2026-08-09 — Generate production manifests outside the source checkout
|
|
|
|
**TL;DR:** Provide a small deterministic generator binary that runs next to the
|
|
canonical production packages and writes the JSON manifest artifacts that are
|
|
then stored and packaged with Lanspread.
|
|
|
|
This checkout has catalog metadata for 186 games but canonical package bytes
|
|
only for a small CLI fixture set. Hashes cannot be derived honestly without the
|
|
bytes. Keeping the generator here makes the format reproducible without
|
|
requiring production game packages in Git.
|
|
|
|
Alternatives:
|
|
|
|
- Store production packages in this repository. That would make generation
|
|
self-contained, but is impractical for size and distribution reasons.
|
|
- Generate hashes at application runtime. This would make local peer bytes the
|
|
authority, defeating catalog-owned verification and adding startup work.
|
|
- Accept hashes announced by peers. This is easy to deploy, but provides no
|
|
protection against a peer that supplies both the bytes and their claimed hash.
|