mirror of
https://github.com/forkless/NotAlterra.git
synced 2026-08-23 19:12:37 +02:00
v0.4.1: persistent config, split-layout picker, backup location, security docs
This commit is contained in:
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user