Files
NotAlterra/DECISIONS.md
T

113 lines
4.0 KiB
Markdown

# Design Decisions
This file captures the rationale behind significant architecture and format
choices, so the reasoning is preserved for future maintainers (including
yourself six months from now).
---
## Sentinel File vs config.ini (v0.3.2)
### Problem
`config.ini` persisted the save folder path to disk, including the user's
filesystem-username. This is a privacy concern — paths are visible next to
the binary.
### Decision
Remove `config.ini` entirely. The save folder is session-only — set it each
time via **Set save folder**. The disclaimer acceptance is tracked via a
0-byte sentinel file (`NotAlterra_LICENSE_ACCEPTED`) alongside the binary.
### Rationale
**Privacy** — no paths written to disk. The save folder exists only in
memory while the tool runs.
**Simplicity** — no config parsing, no INI format to maintain, no migration
code for renamed keys.
**Sentinel, not config** — a 0-byte file communicates exactly one boolean
(disclaimer accepted). It cannot grow into a configuration file over time.
The format intentionally prevents scope creep.
**What was removed:**
- `AppConfig` struct (save_path, ini_path, save_scan, disclaimer_accepted)
- `load_config()` / `save_config()` with INI parsing
- Cached `ini_path` — now derived from save folder at runtime
- Four integration tests for config round-trips
---
## Manual Path Entry vs Auto-Discovery (v0.3.0)
### Problem
Auto-discovery scanned user profiles and system directories for Subnautica 2
save folders. This is a privacy concern — it traverses `/home/*` (Linux) and
`C:\Users\*` (Windows).
### Decision
Replace full auto-discovery with manual path entry via **Set save folder**.
Keep a lightweight `quick_discover()` that checks only the current user's
default install paths at startup.
### Rationale
**Privacy** — no scanning of other users' profiles or system drives.
**Current-user convenience**`quick_discover()` checks 1 path on Windows,
3 paths on Linux, all within the current user's own directories. Returns
the first match silently, no UI. If nothing is found, the user enters their
path manually.
**Discovery module retained**`validate_custom_path()` and
`derive_ini_path()` still live in `discovery.rs` for the manual entry flow.
The aggressive scan functions (`discover_save_folders()`, `scan_other_users()`,
`walk_for_subnautica()`) are removed.
---
## tar.gz Backup Format (v0.4.0)
### Problem
Directory-tree backups (`NotAlterra_Backups/notalterra_copy_<timestamp>/`)
are messy, uncompressed, and have no integrity guarantees.
### Decision
One `tar.gz` archive per backup event, stored in `backups/saves/`.
### Rationale
**No vendor lock-in** — standard `tar -xzf` recovers data without the tool.
If NotAlterra stops working, the user's backups are still accessible with
standard system utilities.
**Single file per event** — reduces clutter. One backup = one file, not
a directory tree with 15+ loose save files.
**Compression** — save files compress well (~75MB → ~20MB). Reduces disk
usage without user effort.
**Pure Rust implementation**`tar` + `flate2` crates, 200M+ downloads
combined. No system dependencies, no external tools.
**Per-entry restore** — extracting a single save file from the archive
does not require decompressing the entire archive.
### Safeguards
- **Atomic write**: backup written to `.tmp` file, then atomically renamed.
Power loss during backup discards a temp file, not a real backup.
- **Integrity check after creation**: archive is read back and validated
before reporting success.
- **SHA256 manifest**: a `MANIFEST` file inside each archive records the
hash of every contained save file. On restore, each extracted file is
verified against its expected hash — silent bit-rot detected before bad
data reaches the save folder.
- **Fuzz target**: round-trip fuzzing (create archive from diverse inputs →
restore → compare) catches logic bugs.
### Migration
Existing `NotAlterra_Backups/` directory-tree backups are detected and
transparently imported on first run after upgrade. No manual migration
required.