move policy docs to docs/ for cleaner root

This commit is contained in:
2026-06-03 02:19:23 +02:00
parent 030f50f90d
commit 476a0c1aed
5 changed files with 0 additions and 0 deletions
+54
View File
@@ -0,0 +1,54 @@
# Security Audit
**Project:** NotAlterra (Subnautica 2 save-file manager)
**Date:** 2026-06-01
**Scope:** Full source code — `src/`, `examples/`, build pipeline
## Summary
No malicious or exploitable behavior detected. NotAlterra is an offline
terminal application with no network access, no unsafe code, and
no data exfiltration surface.
## Audit Results
| Category | Finding |
|---|---|
| `unsafe` blocks | None |
| Network (sockets, HTTP, TLS) | None — zero network dependencies |
| Process spawning | `guard.rs` (tasklist / pgrep) — dormant, not called |
| Dynamic loading | None |
| `include_bytes!` / obfuscation | None |
| Thread spawning | Whale animation only — benign |
## Process Guard
`guard.rs` contains code to detect a running Subnautica 2 instance via
`tasklist` (Windows) and `pgrep` (Linux). This code is **dormant**
`check_game_not_running()` is never called from `main.rs`.
The intent is to prevent accidental save corruption by warning the user
if the game is running during backup or recovery operations.
This feature may be re-introduced in a future release provided it does not trigger false positives or interfere with normal system operation.
## File I/O
All file writes are confined to declared paths:
- `config.ini` — save-path cache, scan timestamp, disclaimer flag
- `NotAlterra_Backups/` — backup archives
- `transaction.log` — timestamped action log
No writes outside these directories. No reads beyond the Subnautica 2
Saved folder tree.
## Dependencies
No dependency introduces network access or code execution risks. Full
dependency tree is pinned via `Cargo.lock`.
## Conclusion
NotAlterra is safe to use. It operates entirely within the user's
local filesystem and performs only the save-management operations it
declares.
+60
View File
@@ -0,0 +1,60 @@
# Code Signing Policy
NotAlterra uses automated, auditable pipelines to ensure every release
artifact is traceable to its source.
## Build & Signing Process
All release binaries are built from this repository by GitHub Actions on
tag push. The CI workflow runs on `ubuntu-latest`, installs the
required toolchain via `dtolnay/rust-toolchain@stable`, and produces
deterministic artifacts using a locked `Cargo.lock` and pinned
dependency versions.
## AI Usage Disclosure
This project uses agentic AI coding tools (e.g., DeepSeek TUI,
GitHub Copilot) as assistive aides for code generation and review. AI
tools operate under human supervision only:
- Every code change is reviewed and committed by a human maintainer.
- AI-generated code is identified in commit history — no attempt is made
to obscure or anonymize the source.
- All contributions pass the same lint and verification gates as any
human-authored change.
## Integrity
AI tools do not have direct write access to the release pipeline or the
repository's tag namespace. Builds are triggered exclusively by signed
Git tags, which can only be created by a human maintainer with access to
the project's GPG key.
## Privacy
NotAlterra does not collect, transmit, or store any personal user data.
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.
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.
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.
## Signing
> **Status: pending certification.** No binaries have been signed by
> SignPath yet. This policy exists for transparency and privacy
> documentation while the project prepares for certification.
Only binaries produced by the official CI runner from the `master`
branch will be submitted to SignPath for signing. Manual or off-CI
builds are never shipped as signed releases.
+112
View File
@@ -0,0 +1,112 @@
# 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.
+113
View File
@@ -0,0 +1,113 @@
# Governance
NotAlterra is maintained by a single developer. This document describes how
decisions are made, how access is controlled, and what happens if the
maintainer becomes unavailable.
## Decision Making
| Area | Process |
|---|---|
| Feature scope | Maintainer decides. Community input via issues and discussions is encouraged but non-binding. |
| Code review | All changes pass through CI (`cargo check`, `cargo test`, `cargo doc`). Human review is performed by the maintainer before signing. |
| Release | Signed GPG tag by the maintainer. No automated tag creation. CI builds, packages, and attaches provenance. |
| Policy documents | Maintainer drafts. Significant changes are committed with justification in the commit message. |
| Security issues | Reported via email. Patched within 48 hours. Disclosed publicly after patch release. |
## Maintainer
- **GitHub**: [forkless](https://github.com/forkless)
- **Contact**: forkless@protonmail.com
- **GPG key**: [314BB48A3C72D8EC2830B8BED2B0DF63E2CBEA16](https://github.com/forkless.gpg)
## Bus Factor
NotAlterra has a bus factor of one — only the maintainer holds the GPG key
and push access to the repository.
### Proposed Mitigation
An emergency signing key stored on a USB stick in a sealed envelope, held
by a non-technical trusted person. The envelope also contains the passphrase.
The key is independent from the maintainer's daily key and revocable if
compromised.
The envelope is to be opened only if the maintainer is unreachable for 90+
consecutive days with no public activity. A technical contact would be
designated to sign releases using the emergency key.
*This mitigation is not yet in place — documented here as intent.*
### Access Recovery Plan
If the maintainer becomes unavailable for an extended period (unreachable
for 90+ days with no public activity), the following steps are available to
the community:
1. **Fork the repository.** All code, documentation, and build scripts are
publicly available under the MIT license. The project can be continued
under new maintainership.
2. **Contact GitHub Support.** Repository transfer can be requested through
GitHub's deceased user policy or owner unreachability process.
3. **Replace the GPG key.** The signing key belongs to the maintainer and
cannot be transferred. A new maintainer should generate a new key, add
it to the CI secrets, and update this document.
4. **Re-establish provenance.** SLSA provenance will need to be regenerated
under the new maintainer's identity. Historical provenance for prior
releases remains valid.
### What the Maintainer Periodically Verifies
- GPG key expiration (checked quarterly).
- CI pipeline is functional (every commit push triggers it).
- Backup of repository and signing subkey exists in offline storage.
## Code of Conduct
Be respectful. Be constructive. Assume good intent.
This project is maintained by someone learning as they go. Questions are
welcome. Patience is appreciated. Kindness is non-negotiable.
## Release Checklist
CI now creates releases as drafts — binaries are built and uploaded but
not published. The maintainer tests the draft binaries before publishing.
Before signing a release tag, the maintainer verifies:
- [ ] Impact analysis completed — all call sites for new/changed functions identified and updated
- [ ] `cargo test --workspace` — all tests pass (including new integration tests for features shipped in this release)
- [ ] `python3 tests/_check.py` — 100% doc coverage
- [ ] CHANGELOG.md has an entry for the new version
- [ ] `git status` — no uncommitted changes
- [ ] `_release.md` is updated for the new version
After the CI run completes:
- [ ] Download draft binaries from the GitHub releases page
- [ ] Test on target platform(s) — basic menu flow, backup, restore, inspect
- [ ] Click **Publish release** on GitHub when satisfied
## Roadmap
Planned changes for upcoming releases, ordered by priority.
| Target | Item |
|--------|------|
| v0.4.0 | ✅ All v0.4.0 items completed — released 2026-06-03 |
| 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 |
Items may shift between releases depending on feedback and urgency.
## Changes to This Document
This document is versioned with the repository. Proposed changes should be
filed as pull requests. The maintainer has final approval.
Last updated: 2026-06-02.
+8
View File
@@ -0,0 +1,8 @@
# Known Issues
## Stale config.ini from prior versions
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.
**Planned**: Auto-remove stale `config.ini` on first launch after upgrade.