OverviewFilesCommitsIssuesDocsReleasesPeers

P2P-Hiverelay commits / cd3ef3e

fix(docs): correct the utah-0.5gb diagnosis — not a Node-version issue
I attributed utah-0.5gb's crash loop to Node v22.22.2 vs v22.22.0. A fleet-wide survey falsifies that: sing-1, sing-2 and dubai all run the identical v22.22.2 and pass the runtime check, and the fleet spans v18.19.1 through v22.23.1 with 11 of 12 reachable boxes passing. The actual cause is a memory-starved `npm ci` on a 458MB box with swap exhausted, which exited 0 while leaving node_modules partially written. Corroborating evidence: the follow-up `npm rebuild` failed inside patch-package's OWN dependency tree, and the box has no compiler at all (only python3), so it depends entirely on prebuilt binaries that the partial install never finished placing. This strengthens rather than weakens the gate that shipped. A version pin — which the plan proposed as 1.2 — would have caught nothing here. Executing the runtime catches it regardless of origin, which is why the preflight is a require and not a version comparison. Phase 1.2 is struck accordingly and replaced with the real follow-up: guard low-memory boxes against a partial dependency install. Corrects the comment in updater.sh, the rationale in the fleet safety test, and two passages in the plan. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
cd3ef3e81241452863ebeb84c7cbf6e46810535c
by bigdestiny2 <33146784+bigdestiny2@users.noreply.github.com> · 2026-07-28T15:12:02.000Z

Changed files (3) +25 -13

docs/FLEET-PLAN-2026-07-28.md +9 -4
……@@ -55,9 +55,14 @@ Error: Cannot find module '/prebuilds/linux-x64/sodium-native.node'
5555The path is **root-relative**: `require-addon` resolved the package root to `/`. The binary is
5656present and intact at
5757`node_modules/dht-rpc/node_modules/sodium-native/prebuilds/linux-x64/sodium-native.node` (919 KB).
58utah runs **Node v22.22.0** and works; utah-0.5gb runs **v22.22.2** and does not. This is
59environmental, not a HiveRelay code defect — but it is a fleet-wide risk, because any box on
60v22.22.2 that reinstalls dependencies will hit it.
58**Corrected after a fleet-wide survey:** this is *not* a Node-version issue. `sing-1`, `sing-2`
59and `dubai` all run the identical v22.22.2 and pass; the fleet spans v18.19.1 through v22.23.1
60with 11 of 12 reachable boxes passing the runtime check. The cause is a **memory-starved
61`npm ci`** on a 458 MB box with swap exhausted, which exited 0 while leaving `node_modules`
62partially written — corroborated by a follow-up `npm rebuild` failing inside patch-package's own
63dependency tree, and by the box having no compiler (only `python3`), so it depends entirely on
64prebuilt binaries. The risk is therefore specific to memory-constrained boxes during dependency
65reinstall, not to any Node version.
6166
6267**`dashboard-admin-operator` is an unauthenticated fleet-root control plane.** Verified live on the
6368workstation: `node PID 51423 … TCP *:3458 (LISTEN)`. Zero auth references in `server.cjs`,
……@@ -118,7 +123,7 @@ exists, every enablement is a manual, unrepeatable, undocumented act.
118123| # | Action |
119124|---|---|
120125| 1.1 | **Canary-of-one throwaway host.** Provision a disposable VPS matching the fleet's OS and Node. Every promotion runs there first: fresh clone at the tag → `npm ci --omit=dev` → start → `/health` green → only then bump the channel |
121| 1.2 | **Pin the Node version.** utah v22.22.0 works, utah-0.5gb v22.22.2 does not. Add `engines` + an updater pre-flight assertion, or ship a known-good Node with the appliance |
126| 1.2 | **~~Pin the Node version~~ — falsified, superseded by a runtime preflight.** The fleet spans v18.19.1–v22.23.1 and 11 of 12 pass; three boxes share utah-0.5gb's exact v22.22.2 and are fine. A version pin would have caught nothing. The gate that works is executing the runtime (`node -e 'require("hyperswarm")'`) after the deps install and before the restart — shipped in `updater.sh`. Separately: guard low-memory boxes against a partial `npm ci`, which is the actual cause |
122127| 1.3 | **Make the updater self-update.** It never reinstalls `/usr/local/bin/hiverelay-updater`, so the `--force` rollback fix in rc.6 is on *no* box. A fix to the update agent currently cannot reach the fleet except by hand |
123128| 1.4 | **Surface `storageAdmission.failClosed()`** on `/health` (R-8). Today it is invisible to every health surface *and* makes gateway reads 404 with "still replicating" — actively misleading |
124129| 1.5 | **Whitelist the disk-drain 503** in `health-watchdog.sh` (R-4). As written, `diskHealthGate` + watchdog is a 4-minute SIGKILL loop that frees no disk. Latent only because the gate defaults off — it arms the moment an operator follows `PRODUCTION.md` |
fleet/updater.sh +11 -6
……@@ -252,12 +252,17 @@ deps_if_changed() { # $1=from-ref $2=to-ref
252252
253253# Prove the runtime can actually boot BEFORE restarting the live service.
254254#
255# `npm ci` succeeding does not mean the relay can start. On 2026-07-28
256# utah-0.5gb installed cleanly and then crash-looped, because require-addon
257# resolved the package root to "/" and looked for
258# /prebuilds/linux-x64/sodium-native.node — the binary was present and correct
259# inside node_modules. Same tag, same install; the difference was Node
260# v22.22.2 vs v22.22.0 on the box that worked. `engines: >=20.0.0` admits both.
255# `npm ci` REPORTING success does not mean the relay can start. On 2026-07-28
256# utah-0.5gb's install exited 0 and the relay then crash-looped 188 times:
257# require-addon resolved the package root to "/" and looked for
258# /prebuilds/linux-x64/sodium-native.node, while the binary sat present and
259# correct inside node_modules.
260#
261# The cause was a memory-starved install — 458MB RAM with swap exhausted — that
262# left node_modules partially written. NOT a Node incompatibility: three other
263# relays run the identical v22.22.2 and pass, and the fleet spans v18.19.1
264# through v22.23.1 with 11 of 12 passing. A version pin would have caught
265# nothing; only executing the runtime does.
261266#
262267# Loading hyperswarm walks the exact chain that failed
263268# (hyperswarm -> hyperdht -> dht-rpc -> udx-native -> require-addon ->
test/unit/fleet-shell-safety.test.js +5 -3
……@@ -140,9 +140,11 @@ test('fleet updater proves the runtime boots before restarting the live service'
140140 // npm ci succeeding does not mean the relay can start. utah-0.5gb installed
141141 // cleanly on 2026-07-28 and then crash-looped: require-addon resolved the
142142 // package root to "/" and looked for /prebuilds/linux-x64/sodium-native.node
143 // while the binary sat correct inside node_modules. Same tag, same install —
144 // the difference was Node v22.22.2 vs v22.22.0, and `engines: >=20.0.0`
145 // admits both, so a version pin would not have caught it either.
143 // while the binary sat correct inside node_modules. The cause was a
144 // memory-starved install on a 458MB box leaving node_modules partial — not a
145 // Node incompatibility: three other relays run the identical v22.22.2 and
146 // pass. A version pin would have caught nothing; only executing the runtime
147 // does, which is why the gate is a require rather than a version comparison.
146148 t.ok(updater.includes('preflight_runtime'), 'preflight helper exists')
147149 t.ok(updater.includes('require("hyperswarm")'),
148150 'loads the chain that actually broke: hyperswarm -> hyperdht -> dht-rpc -> udx-native -> require-addon -> sodium-native')