v0.4.1: persistent config, split-layout picker, backup location, security docs

This commit is contained in:
2026-06-09 11:39:51 +02:00
parent e2ed45c444
commit 73147b6be1
16 changed files with 804 additions and 111 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ What happened? What did you expect to happen instead?
### Environment
- **OS**: (e.g. Windows 11, Ubuntu 24.04, Steam Deck)
- **NotAlterra version**: (shown in the title bar, e.g. v0.4.0)
- **NotAlterra version**: (shown in the title bar, e.g. v0.4.1)
- **Subnautica 2 install**: (Steam, Xbox, Epic, custom)
### Logs
+13 -12
View File
@@ -32,23 +32,24 @@ the project's GPG key.
## Privacy
NotAlterra does not collect, transmit, or store any personal user data.
The application runs entirely offline:
NotAlterra does not collect or transmit any personal user data — it has
no network access, no telemetry, and no analytics. The application runs
entirely offline:
- No telemetry, no analytics, no crash reporters.
- No network requests — the binary never opens a socket.
- All configuration is stored locally in `config.ini` alongside the
executable.
- Configuration is stored locally in `app.ini` under the platform config
directory (e.g. `%LOCALAPPDATA%\NotAlterra\config\app.ini`).
The only potentially identifying information stored is the game's
save-folder path in `config.ini`, which includes the current Windows
username. This path never leaves the local machine — it is read once on
startup and used exclusively to locate saves and configuration files.
The `app.ini` file stores your save-folder path and backup root — the
minimum needed to avoid re-entering them each session. These paths may
include the current system username (e.g. `C:\Users\jane\...`). This
information never leaves the local machine. The file is plain text and
can be inspected or deleted at any time.
Because no data is collected or transmitted, there is nothing to share,
sell, or expose. This section serves as a safe-harbor statement:
NotAlterra is designed to respect user privacy by collecting nothing at
all.
Because no data is transmitted, there is nothing to share, sell, or
expose. This section serves as a safe-harbor statement: NotAlterra is
designed to respect user privacy by never sending data anywhere.
## Signing
> **Status: pending certification.** No binaries have been signed by
+1 -1
View File
@@ -55,7 +55,7 @@ triggers the issue.
### Affected versions
- NotAlterra version(s): (e.g. v0.4.0)
- NotAlterra version(s): (e.g. v0.4.1)
- Platform: (Windows / Linux / both)
### Impact assessment
+104
View File
@@ -110,3 +110,107 @@ does not require decompressing the entire archive.
Existing `NotAlterra_Backups/` directory-tree backups are detected and
transparently imported on first run after upgrade. No manual migration
required.
---
## GVAS Heuristic Parser vs Structural Walker (v0.4.0)
### Problem
The GVAS save-file parser in `src/gvas.rs` uses byte-scanning to find
property names as raw string patterns. It does not walk the full UE5 GVAS
schema tree. This means:
- Properties the scanner isn't written to look for are silently skipped
- Byte sequences that happen to match a property name can produce false
positives (mitigated by validating the preceding length field)
- Overall GVAS structure (header magic, version, property ordering) is not
validated
The GVAS format is defined by the public Unreal Engine 5 source code — the
SaveGame system and its binary serialization are part of the engine's
open API.
### Decision
Keep the heuristic byte-scan parser. Marked as Won't fix.
### Rationale
**No published schema** — Unknown Worlds does not publish the GVAS property
layout for Subnautica 2. A structural walker would require reverse-
engineering the full property type system without ground truth.
**No user-facing benefit** — the tool reads six properties (SlotName,
DisplayName, bIsMultiplayerSave, playtime, etc.) for display purposes. The
byte-scan finds all of them reliably on known save files. A structural
walker would produce the same output.
**Graceful degradation** — when the scanner cannot find a property, the
picker falls back to the filename. The tool never crashes or presents
incorrect data.
**Fuzz coverage** — three fuzz targets (`parse_gvas`, `full_metadata`,
`backup_roundtrip`) verify the parser does not panic on adversarial input.
If a future game update changes the binary layout, fuzzing will catch it.
---
## Dead-Code Cleanup (v0.4.0)
### Problem
`src/main.rs` had `#![allow(dead_code)]` at the crate level, silencing
compiler warnings for four unused functions. This prevented the compiler
from flagging real dead code.
### Decision
Remove `_game_running_windows()` and `_backup_root()`. Retain
`_game_running_linux()` and `available_space()` for planned future use.
### Rationale
**Removed:**
- `_game_running_windows()` — process detection via `tasklist` was
intentionally disabled across the project to avoid Windows Defender
false positives (Trojan:Win32/Wacatac.C!ml). The startup reminder modal
is the replacement. No plan to re-enable.
- `_backup_root()` — returned the legacy `NotAlterra_Backups/` path,
replaced by `backups/saves/` and `backups/config/` in v0.4.0.
**Retained (each with its own `#[allow(dead_code)]`):**
- `_game_running_linux()` — kept for possible opt-in process detection
on Linux where AV false positives are not a concern.
- `available_space()` — kept for a planned disk-space warning before
backup operations.
---
## Persistent app.ini vs Session-Only Paths (v0.4.1)
### Problem
Save-folder and backup-root paths were session-only — re-entered each
time the tool launched. This was a deliberate privacy choice (v0.3.2),
but in practice users expected paths to persist between sessions.
### Decision
Persist both paths to `app.ini` under the platform config directory
(`data_local_dir/NotAlterra/config/`). Backup data stays in
`~/NotAlterra/backups/` (user-facing, not in AppData).
### Rationale
**Usability** — re-entering paths every session was friction with no
real privacy benefit. The paths already existed on the user's filesystem;
persisting them simply saves keystrokes.
**Transparency, not silence** — instead of claiming "no data stored,"
the documentation now accurately describes what is stored (save-folder
and backup-root paths, which may contain the system username), why
(minimal convenience data), and that it never leaves the machine.
**Platform standards** — config goes to the OS-designated config
directory (`AppData/Local` on Windows, `~/.local/share` on Linux).
User-facing backup data stays in the home directory where users expect
to find it. This separation is standard convention.
**Plain text, user-controlled**`app.ini` is a simple key=value file.
Users can inspect or delete it at any time. No binary format, no
registry, no opaque storage.
+2 -2
View File
@@ -99,9 +99,9 @@ Planned changes for upcoming releases, ordered by priority.
| Target | Item |
|--------|------|
| v0.4.0 | ✅ All v0.4.0 items completed — released 2026-06-03 |
| v0.4.1 | ✅ Persistent app config, backup location picker, split-layout metadata, security docs, pip menus — released 2026-06-09 |
| v0.5.0 | CLI flags: `--backup`, `--extract <archive>`, `--inspect <savefile>` (`.sav`/`.bak`), `--list` |
| v0.5.0 | Add migration notification dialog on startup (user sees old backups converted, old files untouched) |
| v0.5.0 | Move existing `transaction.log` into `logs/` directory on first launch |
| v0.5.0 | Migration notification dialog on startup (user sees old backups converted, old files untouched) |
Items may shift between releases depending on feedback and urgency.
+89 -4
View File
@@ -1,8 +1,93 @@
# Known Issues
## Stale config.ini from prior versions
## `game_running()` returns hardcoded `false`
Users upgrading from v0.3.0 or earlier will have a `config.ini` file next to
the binary that no longer serves any function. It can be safely deleted.
The process-detection guard in `guard.rs` intentionally returns `false` on
both platforms to avoid Windows Defender false positives
(Trojan:Win32/Wacatac.C!ml). The startup reminder modal ("Please close
Subnautica 2 before using NotAlterra") is the real safety mechanism, but
the function name implies active detection.
**Planned**: Auto-remove stale `config.ini` on first launch after upgrade.
The dormant `_game_running_linux()` function (kept for future use) contains
a working code path that is unreachable behind the hardcoded `false` return.
## GVAS parser is heuristic, not a structural walker
`src/gvas.rs` extracts GVAS properties by scanning for property names as
raw byte sequences and validating preceding length fields — it does not
walk the full GVAS schema tree. It works on known Subnautica 2 save files
but:
> The GVAS format is defined by the public Unreal Engine 5 source code —
> the SaveGame system and its binary layout are part of the engine's
> open API.
- Will silently skip properties it wasn't written to look for
- May produce false positives if a matching byte sequence appears in
unrelated data
- Does not validate overall GVAS structure (header magic, version, etc.)
**Decision**: Won't fix. A structural walker would require reverse-
engineering the full UE5 GVAS property tree without a published schema,
with no significant benefit for the tool's feature set. The six properties
the UI displays (SlotName, DisplayName, bIsMultiplayerSave, playtime, etc.)
are found reliably by the current approach. The three fuzz targets
(`parse_gvas`, `full_metadata`, `backup_roundtrip`) ensure the parser does
not crash on adversarial input. When a property cannot be found, the picker
falls back to the filename — the tool degrades gracefully rather than
erroring out.
## No TUI / menu-flow test coverage
`src/main.rs` contains 1,227 lines of event-loop code (menu dispatch,
picker interactions, confirmation dialogs, .ini submenu) with zero
automated tests. All other modules (ops, gvas, guard, config) have
integration tests, but UI regressions are only caught through manual
testing.
This is common for terminal applications but means menu-flow changes
carry higher risk.
## Discovery module carries vestigial code
`src/discovery.rs` is 442 lines, but the primary save-folder workflow is
manual path entry via **Set save folder**. The module still contains:
- `scan_other_users()` — scans `/home/*` (Linux) or `C:\Users\*` (Windows)
for other user profiles
- `walk_for_subnautica()` — broad filesystem walk for custom installs
- `discover_save_folders()` — full discovery entry point
These were downgraded from primary to fallback in v0.3.2 for privacy
reasons, and `quick_discover()` (checking only the current user's default
paths) is now the only automated startup check. The heavy scanning code
could be removed if manual path entry remains the sole workflow.
## No CLI flags for scripting
The tool is TUI-only. There is no `--backup`, `--extract <archive>`,
`--inspect <savefile>`, or `--list` flag. This means it cannot be used in
cron jobs, scheduled tasks, or automated backup scripts.
**Planned**: v0.5.0 roadmap includes CLI flags.
## Bus factor mitigation documented but unimplemented
`docs/GOVERNANCE.md` describes a planned emergency signing key stored with
a non-technical trusted person. The envelope and key do not yet exist. The
designated technical contact is not confirmed. If the maintainer becomes
unreachable, the only viable path is a fork.
## Resolved
### Dormant functions removed (v0.4.0)
`_game_running_windows()` and `_backup_root()` were removed as dead code.
Neither was called from any code path. `_game_running_linux()` and
`available_space()` are retained for planned future use — each has its own
`#[allow(dead_code)]` annotation.
**Rationale**: `_game_running_windows()` was never wired up (process
detection was intentionally disabled to avoid AV false positives).
`_backup_root()` pointed at the legacy `NotAlterra_Backups/` directory
which was replaced by `backups/saves/` and `backups/config/` in v0.4.0.