diff --git a/installer/PLAN.md b/installer/PLAN.md index d2edf7d..2b068c0 100644 --- a/installer/PLAN.md +++ b/installer/PLAN.md @@ -894,12 +894,13 @@ operators who downloaded a bare binary being told to re-download a package. Defe costs nothing: nothing is published from `edge`, and the guide's Appendix A is the supported path meanwhile. -| Item | Decision | -|---|---| -| `.deb` for uo-link | **Dropped** (§5.1) | -| Windows MSI | **Dropped** (§5.1) | -| arm64 cross build | **Build** — Linux `aarch64`, both components (§5.2) | -| Backup before upgrade | **Build** — on by default, scoped to what a run overwrites (§5.3) | +| Item | Decision | State | +|---|---|---| +| `.deb` for uo-link | **Dropped** (§5.1) | — | +| Windows MSI | **Dropped** (§5.1) | — | +| arm64 cross build | **Build** — Linux `aarch64`, both components (§5.2) | In review: [installer#9](https://gitea.whitlocktech.com/RunicGateway/installer/pulls/9), [link#26](https://gitea.whitlocktech.com/RunicGateway/link/pulls/26), [installer#10](https://gitea.whitlocktech.com/RunicGateway/installer/pulls/10); step 3 waits on link's first arm64 release | +| Backup before upgrade | **Build** — on by default, scoped to what a run overwrites (§5.3) | In review: [installer#11](https://gitea.whitlocktech.com/RunicGateway/installer/pulls/11) | +| Docs the release invalidates | **Do** (§5.4) | Pending | #### 5.1 What ships is plain binaries: no `.deb`, no MSI @@ -961,6 +962,13 @@ lasts. Hence: `bundle.yml` is therefore edited on `main` only and never on `edge`, so the cutover merge has nothing to conflict over. +**What building it found.** Neither crate cross-compiles with the arm64 *compiler* alone. +`gcc-aarch64-linux-gnu` only **recommends** `libc6-dev-arm64-cross`, and both release workflows +install with `--no-install-recommends` — so the C that each crate pulls in (bundled SQLite under +`sqlx` for the sidecar, `ring` under `ureq`'s rustls for the installer) dies on a missing +`bits/libc-header-start.h` while every Rust dependency builds fine. Both halves were reproduced in a +`rust:1-slim-bookworm` container, failure then fix, before either workflow was written. + #### 5.3 Backup before overwrite **Scoped by what cannot be fetched again.** Not the sidecar binary or the overlay files — both are @@ -982,14 +990,28 @@ that is still downloadable, and the noise would bury the two files that matter. from, beside a `manifest.json` naming the source path, its SHA256, and the bundle moved from and to. In the state directory, not the ServUO tree — the same rule the tier's `patches/originals/` follows, and for the same reason: `uninstall` has promised never to clean up in there. -- **When:** on by default for `update`, and for an `install` over an existing record. A first - install overwrites nothing and writes no backup. `--verify` writes none either, for the reason it - runs no part of the sidecar half (Phase 2): a dry run must not create state. +- **When: whenever the run is about to overwrite something**, whichever verb was typed. This + section first said "`update`, and `install` over an existing record", justified by a first install + overwriting nothing — **which is wrong**, and building it is what showed that. A tree deployed by + hand per [`INSTALL.md`](INSTALL.md) Appendix A2 — the path this project recommends while the + binary is unreleased — has `.cs` files the first `install` plans as `Change` and overwrites, with + no prior record anywhere to notice. The direct test covers that case, and a genuine first install + onto a clean tree still writes nothing, because there is nothing to copy. `--verify` writes none + either, for the reason it runs no part of the sidecar half (Phase 2): a dry run must not create + state. +- **`sidecar.toml` joins a backup that is already being taken; it is never the reason for one.** + Nothing in the installer rewrites it, so treating it as a trigger would leave a dated directory + behind after every no-op `update` — the empty-backup problem one step along. It is copied so that + a restored set of files arrives with the token that matches it. - **`--no-backup`** opts out, for an operator with their own snapshotting. - **Retention is three.** Older ones are pruned as new ones are written; an unbounded directory of ServUO source copies on a shard host is its own support problem. `uninstall` keeps them and `--purge` drops them, alongside the config, the database and the cached patch set — same rule as Phase 4, and the same reason: they are the only offline record of what was there before. +- **The directory is created lazily and the manifest is written last**, so a directory carrying one + is a *complete* backup. Listing and pruning consider only those: a run interrupted mid-copy must + neither be mistaken for a backup nor be able to evict a good one by being newer than it. It is + left on disk for a human to look at rather than silently deleted. - **Restore is printed, not done.** Consistent with the uninstall report, and for the identical reason: the installer cannot know what has changed since, and a clever automatic restore over a newer overlay eats work rather than saving it. `doctor` names the most recent backup and its