security: remove node credentials from tracked files (open-source Phase 1)
Demo images / Build & push demo images (push) Failing after 2m28s

Scrubs the fleet SSH/UI password from every tracked file (22 occurrences)
and removes inline credentials from the code paths that used them.

Docs and trackers keep the surrounding context — these are published under
docs/history/ per the open-source plan — with the literals replaced by
<FLEET_PW> / <FLEET_PW_ALT> so the "two variants exist" detail survives
without the values.

Three of the eight files were in .planning/ and were NOT in the plan's
enumerated list; the reworked audit-secrets.sh found them.

Code changes:
- neode-ui/test-openwrt.mjs: node URL and password come from ARCHY_NODE_URL /
  ARCHY_NODE_PW; the SSH target derives from the URL instead of a hardcoded
  tailnet IP; exits 2 when unset.
- scripts/run-post-install-tests.sh: drops the built-in "testpass123!"
  default and adds --password-stdin; refuses to run unauthenticated instead
  of silently trying a known password. --phase1-only still needs no password.
- .gitea/workflows/post-install-tests.yml: sshpass with an inline literal
  replaced by key auth (NODE_SSH_KEY secret); password comes from the
  NODE_UI_PASSWORD secret and is piped over stdin rather than argv, so it
  stays out of the node's process list and the job log. Default target IP
  removed.

scripts/audit-secrets.sh now reports 5/5 pass, 0 fail.

Note: rotation of the exposed credentials is deliberately deferred to the
pre-publish gate and is NOT done by this commit — these values are still
live. See Phase 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-08-07 09:59:10 -04:00
co-authored by Claude Opus 5
parent e3b98ed18f
commit 19082a44f0
12 changed files with 81 additions and 54 deletions
+33 -22
View File
@@ -4,13 +4,11 @@ on:
workflow_dispatch:
inputs:
target:
description: 'Target node IP (e.g. 192.168.1.198)'
description: 'Target node IP or hostname'
required: true
default: '192.168.1.198'
password:
description: 'Node password (or "auto" for fresh install)'
description: 'Node UI password (leave blank to use the NODE_UI_PASSWORD secret)'
required: false
default: 'auto'
jobs:
post-install-tests:
@@ -22,33 +20,46 @@ jobs:
with:
fetch-depth: 1
- name: Run post-install tests on target
- name: Install SSH key
env:
SSH_KEY: ${{ secrets.NODE_SSH_KEY }}
run: |
TARGET="${{ github.event.inputs.target }}"
PASSWORD="${{ github.event.inputs.password }}"
if [ "$PASSWORD" = "auto" ]; then
PASSWORD="testpass123!"
if [ -z "$SSH_KEY" ]; then
echo "ERROR: repository secret NODE_SSH_KEY is not configured."
echo "Post-install tests authenticate by key; password auth is not supported."
exit 1
fi
mkdir -p ~/.ssh && chmod 700 ~/.ssh
printf '%s\n' "$SSH_KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
- name: Run post-install tests on target
env:
TARGET: ${{ github.event.inputs.target }}
NODE_PASSWORD: ${{ github.event.inputs.password }}
NODE_UI_PASSWORD: ${{ secrets.NODE_UI_PASSWORD }}
SSH_USER: ${{ vars.NODE_SSH_USER }}
run: |
PASSWORD="${NODE_PASSWORD:-$NODE_UI_PASSWORD}"
if [ -z "$PASSWORD" ]; then
echo "ERROR: no node password supplied (input or NODE_UI_PASSWORD secret)."
exit 1
fi
USER_NAME="${SSH_USER:-archipelago}"
echo "══════════════════════════════════════════"
echo "Running post-install tests on $TARGET"
echo "══════════════════════════════════════════"
# Copy test script to target and run
sshpass -p 'archipelago' scp -o StrictHostKeyChecking=no \
scp -o StrictHostKeyChecking=accept-new \
scripts/run-post-install-tests.sh \
archipelago@${TARGET}:/tmp/run-post-install-tests.sh 2>/dev/null || \
scp -o StrictHostKeyChecking=no \
scripts/run-post-install-tests.sh \
archipelago@${TARGET}:/tmp/run-post-install-tests.sh
"${USER_NAME}@${TARGET}:/tmp/run-post-install-tests.sh"
# Run tests (with sudo for service checks)
sshpass -p 'archipelago' ssh -o StrictHostKeyChecking=no \
archipelago@${TARGET} \
"sudo bash /tmp/run-post-install-tests.sh '$PASSWORD'" 2>/dev/null || \
ssh -o StrictHostKeyChecking=no \
archipelago@${TARGET} \
"sudo bash /tmp/run-post-install-tests.sh '$PASSWORD'"
# Password is passed over stdin, never as an argv the node's process
# list (or this job's log) would expose.
printf '%s' "$PASSWORD" | ssh -o StrictHostKeyChecking=accept-new \
"${USER_NAME}@${TARGET}" \
"sudo bash /tmp/run-post-install-tests.sh --password-stdin"
frontend-tests:
runs-on: ubuntu-latest
+1 -1
View File
@@ -74,7 +74,7 @@ Nothing blocking the demo. One loose end, likely moot:
- **ANTI-PATTERN (from earlier this session, already corrected): never run `archipelago --version` on a fleet node** — it starts the full daemon rather than printing a version string (deployed binaries predate the flag). Use source-reading instead of the binary for investigation.
## Infrastructure State
- **archi-dev-box** (local node): `archipelago` daemon healthy, RPC on `127.0.0.1:5678` (session cookie in `/tmp/archy-dev-cookies.txt`, likely stale by the time this is read — re-login with `auth.login` / password `ThisIsWeb54321@`). `botfights` container healthy on `1.2.11`.
- **archi-dev-box** (local node): `archipelago` daemon healthy, RPC on `127.0.0.1:5678` (session cookie in `/tmp/archy-dev-cookies.txt`, likely stale by the time this is read — re-login with `auth.login` / password `<FLEET_PW>`). `botfights` container healthy on `1.2.11`.
- **x250-beta** (`archy-x250-beta.tail08d8f2.ts.net`, tailnet IP rotates — resolve by MagicDNS name): reachable via plain `ssh archipelago@archy-x250-beta.tail08d8f2.ts.net` this session (no password prompt hit — key-based or cached). RPC session cookie in `/tmp/archy-cookies.txt` **on that remote node**, likely stale — re-login same way. `botfights` container healthy on `1.2.11`.
- Both nodes' local `/tmp` filled up mid-session (a 12G tmpfs, hit 0MB free once) — if you hit `ENOSPC` from the harness itself (not the actual command), check `df -h /tmp` and clean up stray large files (this session's culprit: two OTA release assets, ~260MB, downloaded to `/tmp` on the **local** machine as a relay step for an unrelated node update earlier in the session).
- Canonical arena: `https://botfights.archipelago-foundation.org` — both demo nodes proxy to this via `ARENA_UPSTREAM_URL`, confirmed serving identical bot/fight data on both.
+1 -1
View File
@@ -69,7 +69,7 @@ reject — they silently keep their old cached copy. **Always verify
## Fleet
SSH: `sshpass -p 'ThisIsWeb54321!' ssh archipelago@<ip>` (note the `!`; `@`
SSH: `sshpass -p '<FLEET_PW_ALT>' ssh archipelago@<ip>` (note the `!`; `@`
is older and still works on some). RPC/node password differs per node — the
`!` one failed RPC login on `.38`.
@@ -27,7 +27,7 @@ key-files:
key-decisions:
- "Used the real RPC path (package.check-updates then package.update, id=botfights) rather than any hand-placed container edit — matches what the UI's per-app Update button drives and what CLAUDE.md/D-04 requires (T-09-34 mitigation)."
- "Local RPC auth: ARCHY_HOST=127.0.0.1 ARCHY_SCHEME=http, password ThisIsWeb54321@ (the second candidate, password123, failed with 'Password Incorrect') — confirmed via tests/lifecycle/lib/rpc.bash's rpc_login."
- "Local RPC auth: ARCHY_HOST=127.0.0.1 ARCHY_SCHEME=http, password <FLEET_PW> (the second candidate, password123, failed with 'Password Incorrect') — confirmed via tests/lifecycle/lib/rpc.bash's rpc_login."
- "x250-dev (100.72.136.6, Tailscale) was unreachable this session (SSH connect timeout) — dev-pair rule recorded as satisfied on archi-dev-box only, with an explicit follow-up note in the demo checklist to repeat Task 1 there if it comes back online before the demo."
- "Task 2 and Task 3 are gate=\"blocking\" checkpoint:human-verify tasks requiring a real browser NIP-07 extension and a real cloud agent — neither is automatable (09-RESEARCH.md Pitfall 5: no window.nostr mock exists anywhere in the test suite). Per this run's explicit instruction, execution stopped here rather than simulating or skipping these checks; the demo-rehearsal checklist below is the structured hand-off for a human/relay to complete them."
@@ -118,7 +118,7 @@ status: awaiting-human-verification
## Accomplishments
- Confirmed the archipelago service was already active on archi-dev-box (running since 20:45 the previous evening) — no service start needed, contrary to the plan's precondition note that it "was inactive at planning time."
- Logged into the local RPC (`http://127.0.0.1/rpc/v1`) using `tests/lifecycle/lib/rpc.bash`'s `rpc_login`, with `ThisIsWeb54321@` (the working candidate — `password123` failed with `Password Incorrect`).
- Logged into the local RPC (`http://127.0.0.1/rpc/v1`) using `tests/lifecycle/lib/rpc.bash`'s `rpc_login`, with `<FLEET_PW>` (the working candidate — `password123` failed with `Password Incorrect`).
- Triggered `package.check-updates`: the local `/var/lib/archipelago/app-catalog.json` cache (previously stuck at 1.1.0, dated 2026-07-23) refreshed to 1.2.1, `manifests_reloaded: 55`, and `journalctl` recorded the release-root signature verification log line (`did:key:z6MkkidEnEpo6qHMCNSZoNKWtvQvxq3whnaME9wGgEFhq7ur`).
- Triggered `package.update {id: botfights}`: the orchestrator's normal upgrade path stopped, pulled, and recreated the container — no manual container edit, no manifest disk edit. Reached `146.59.87.168:3000/lfg2025/botfights:1.2.1` / `running` / `healthy` within ~40s.
- Verified every acceptance criterion in the plan: image tag, `ARENA_UPSTREAM_URL` present, `JWT_SECRET` delivered as a podman secret (`--secret ...,type=env,target=JWT_SECRET`, masked in `podman inspect`, backed by a 0600/64-hex-char file at `/var/lib/archipelago/secrets/botfights-jwt-secret`) with **no plaintext `JWT_SECRET=`** anywhere in the container env, local `/api/bots` matching the arena's fighter set exactly (104 default + 15 classic, both sides), the unified prompt serving with the arena hostname substituted, and the local database byte-identical before/after (`367144960` bytes / mtime `1782916151` — same numbers 09-04-SUMMARY recorded, confirming zero data loss across three plans' worth of work on this same file).
+11 -11
View File
@@ -425,8 +425,8 @@ fresh machine (`cd core && CARGO_INCREMENTAL=0 cargo build --release -p archipel
- **nostr-rs-relay** stuck "Stopping" + ~2s create-loop on .228 (from session g).
**NEXT:** finish .88/.5/.120 roll → push main to gitea-vps2 → Phase-3 quadlet / Workstream F /
multinode. SSH/sudo pw `ThisIsWeb54321@` (**.88 = `ThisIsWeb54321!`**); UI/RPC .228/.198 =
`ThisIsWeb54321@`. Reusable tooling in scratchpad: `deploy-bin.sh`/`remote-apply.sh` (EXPECT_SHA
multinode. SSH/sudo pw `<FLEET_PW>` (**.88 = `<FLEET_PW_ALT>`**); UI/RPC .228/.198 =
`<FLEET_PW>`. Reusable tooling in scratchpad: `deploy-bin.sh`/`remote-apply.sh` (EXPECT_SHA
= `040df5ce…`), `rpc.sh`.
---
@@ -451,10 +451,10 @@ multinode. SSH/sudo pw `ThisIsWeb54321@` (**.88 = `ThisIsWeb54321!`**); UI/RPC .
| .116 (local) | ✅ binary + fresh FE; 36 containers survived restart; UI 200; `index-a75rd6Hy.js` live |
| .198 (LAN) | ✅ binary + fresh FE; 38 containers up; UI 200 |
| .89 (100.89.209.89) | ✅ binary + fresh FE; service active |
| .88 (100.70.96.88, pw `ThisIsWeb54321!`) | ✅ binary + fresh FE; service active |
| .88 (100.70.96.88, pw `<FLEET_PW_ALT>`) | ✅ binary + fresh FE; service active |
| .5 (100.72.136.5) | ⏳ attempted — see resume note (cellular x250) |
| .120 (100.66.157.120) | ⏳ attempted — see resume note (cellular x250) |
| .15 (100.64.83.15, archy-dev-pa) | ❌ SKIPPED — `archipelago@` + `ThisIsWeb54321@` rejected (`Permission denied (publickey,password)`); node creds unknown |
| .15 (100.64.83.15, archy-dev-pa) | ❌ SKIPPED — `archipelago@` + `<FLEET_PW>` rejected (`Permission denied (publickey,password)`); node creds unknown |
Deploy tooling (reusable): scratchpad `deploy-bin.sh <label> <local\|ssh\|ts> <host> <pw>` + `remote-apply.sh` (mv binary avoids ETXTBSY, atomic FE swap preserving `aiui`/APK/`claude-login.html`, chown 1000:1000, restart, sha+health verify). Frontend tarball = `tar -C web/dist/neode-ui -czf neode-ui.tgz .` (flat). Full sha `e0343137b99bf06642c45da67bb092e9a411190ff59eda8e5177c2a06b6f6e89`.
@@ -480,7 +480,7 @@ VALIDATION PROGRESS (sessions e→f):
**✅ 2026-06-25 — STRAY 13h GATE on .228 found + killed; mempool RESOLVED.** A `setsid` gate run from session-e was still churning .228 ~13h later (pathologically slow — only reached test 71/lnd; the 300s settle bump is the suspect). Killed its process group (note: `pkill -f bats` self-matches the ssh command's own argv → kill by numeric PID/PGID instead). After kill, `crash_recovery` (Fix A) auto-recovered the immich/indeedhub/netbird stacks — **good live exercise of Fix A**. **mempool fallout RESOLVED:** the gate churn left .228's podman **overlay storage corrupt** (mempool frontend crash-looped — container couldn't write `/etc/nginx`, same image serves fine on .116) → **fixed by rebooting .228** (clears overlay corruption; Fix A staggered-recovered all apps; mempool stable 200). **.198 is PRUNED** bitcoin → mempool requires archival (install correctly refused) → **cleanly uninstalled** the orphan mempool-db. All nodes now correct. LESSON: never leave the gate running unsupervised; reconsider the 300s settle before re-running.
Fleet on `e0343137` + FE `index-a75rd6Hy.js` on .116/.198/.228/.89/.88/.5/.120 (.15 still old). **`89d397bb` (netbird-delete) binary NOT yet deployed anywhere — verify on .228 then roll.** SSH/sudo pw UNIFORM `ThisIsWeb54321@` (**.88 = `ThisIsWeb54321!`**); **UI/RPC: .228=`ThisIsWeb54321@`, .198=`ThisIsWeb54321@`.** Reusable tooling in scratchpad: `deploy-bin.sh`/`remote-apply.sh` (binary+FE swap), `rpc.sh <host> <pw> <method> [params]` (auth.login→call). Gate harness at `~/lifecycle/lifecycle` on .228 — **CHECK it isn't already running/wedged before re-launching**.
Fleet on `e0343137` + FE `index-a75rd6Hy.js` on .116/.198/.228/.89/.88/.5/.120 (.15 still old). **`89d397bb` (netbird-delete) binary NOT yet deployed anywhere — verify on .228 then roll.** SSH/sudo pw UNIFORM `<FLEET_PW>` (**.88 = `<FLEET_PW_ALT>`**); **UI/RPC: .228=`<FLEET_PW>`, .198=`<FLEET_PW>`.** Reusable tooling in scratchpad: `deploy-bin.sh`/`remote-apply.sh` (binary+FE swap), `rpc.sh <host> <pw> <method> [params]` (auth.login→call). Gate harness at `~/lifecycle/lifecycle` on .228 — **CHECK it isn't already running/wedged before re-launching**.
---
@@ -518,14 +518,14 @@ probes (bitcoin-knots state, immich lan_address). All work is **committed + PUSH
| Node | Pw | Done | Notes |
|------|----|----|-------|
| .116 (local, http:80) | `ThisIsWeb54321@` | ✅ | dev node: bitcoin mid-IBD + http-only |
| .116 (local, http:80) | `<FLEET_PW>` | ✅ | dev node: bitcoin mid-IBD + http-only |
| .198 | `archipelago` | ✅ | resilience; user manual-testing here |
| .228 | `archipelago` | ✅ | canonical gate node (5×-green) |
| 100.82.34.38 (archipelago-1) | `archipelago` | ✅ | |
| 100.89.209.89 (archy-x250-pa) | `ThisIsWeb54321@` | ✅ | |
| 100.70.96.88 (archipelago node) | `ThisIsWeb54321!` | ✅ | note the `!` |
| 100.64.83.15 (archy-dev-pa) | ? | ⏳ | UP (tailscale ping ok) but `ThisIsWeb54321@` REJECTED — **need correct pw** |
| 100.66.157.120 (archy-x250-exp) | `ThisIsWeb54321@` | ⏭️ | DOWN — user said leave it |
| 100.89.209.89 (archy-x250-pa) | `<FLEET_PW>` | ✅ | |
| 100.70.96.88 (archipelago node) | `<FLEET_PW_ALT>` | ✅ | note the `!` |
| 100.64.83.15 (archy-dev-pa) | ? | ⏳ | UP (tailscale ping ok) but `<FLEET_PW>` REJECTED — **need correct pw** |
| 100.66.157.120 (archy-x250-exp) | `<FLEET_PW>` | ⏭️ | DOWN — user said leave it |
Deploy scripts saved in scratchpad: `deploy-node.sh` (full binary+FE, sha+health verify) and
`fe-only.sh` (FE-only, no archipelago restart). Reusable: `bash deploy-node.sh <host> <pw> <scheme> 127.0.0.1`.
@@ -883,7 +883,7 @@ stale `8081` target on .228 (repo code is correct at 18083 — re-check on other
indeedhub-minio indeedhub-relay indeedhub-api indeedhub-ffmpeg`; scp; `sudo tar xzf t.tgz
-C /opt/archipelago/apps`.
- **Nodes:** .228 = 192.168.1.228, SSH pw `archipelago`, RPC/UI pw `password123` (https).
.198 = 192.168.1.198, SSH pw `archipelago`, **RPC/UI pw `ThisIsWeb54321@`** (https). Both
.198 = 192.168.1.198, SSH pw `archipelago`, **RPC/UI pw `<FLEET_PW>`** (https). Both
have the 7-container indeedhub stack + secrets + named volumes pre-existing.
- **Trigger install via RPC:** `auth.login` (sets session+csrf cookies) → send the csrf
cookie value as `X-CSRF-Token` header → `package.install` with params
@@ -17,7 +17,7 @@ only those three.
## ⚠️ Outstanding user request for the deploy
- **Change .81's web-UI password to `ThisIsWeb54321@`** — the user forgot the
- **Change .81's web-UI password to `<FLEET_PW>`** — the user forgot the
current one. Node was unreachable from .116 during this session (flaky WiFi
AP, IP flapped .68↔.81). Do this during deploy (SSH works from the user's
machine; `archipelago`/`archipelago`).
+4 -4
View File
@@ -26,7 +26,7 @@ Updated: 2026-06-30
(`contact_id:1128152268`) now returns **`"encrypted":true`** — confirms the
`archy || peer_pkc_capable(contact_id)` TX fix is live, not just compiled.
- `.228`'s RPC password in memory (`password123`) was stale — user confirmed the correct
password is `ThisIsWeb54321@` (same as `.198`/`.116`, i.e. fully unified now). Re-verified via
password is `<FLEET_PW>` (same as `.198`/`.116`, i.e. fully unified now). Re-verified via
RPC: `mesh.peers` shows 3ccc `pkc_capable:true`, and `mesh.send` to 3ccc returns
`"encrypted":true`#17 confirmed live on `.228` too, not just `.198`.
@@ -94,7 +94,7 @@ has been asked for/owned by this session.
**`Mesh-CAkPgvLo.js`**, `archipelago` active on each:
`.116`, `.198`, `.228` (LAN, archipelago@ + `~/.ssh/archipelago-deploy`),
`100.72.136.5`, `100.89.209.89` (Tailscale, same key — installed this session;
SSH user `archipelago` / pw `ThisIsWeb54321@`; NOPASSWD sudo on all 5).
SSH user `archipelago` / pw `<FLEET_PW>`; NOPASSWD sudo on all 5).
**Shipped this session (commit `12e7990b` on `main`, pushed to gitea-vps2):**
- ✅ **#16 public-channel routing** — inbound Meshtastic text to `BROADCAST_NUM`
@@ -243,7 +243,7 @@ on-device (the caveat above).
### TEST RECIPE (works on each node)
- RPC helper used this session: a node-side `rpc.sh` that logs in (password
`ThisIsWeb54321@`), grabs the `csrf_token` cookie, echoes it as `X-CSRF-Token`, and POSTs to
`<FLEET_PW>`), grabs the `csrf_token` cookie, echoes it as `X-CSRF-Token`, and POSTs to
`http://127.0.0.1:5678/rpc/v1`. Recreate it or run archy's RPC directly. Methods:
`mesh.peers`, `mesh.status`, `mesh.messages`, `mesh.send {contact_id,message}`,
`mesh.broadcast`, `mesh.reboot-radio {seconds}`.
@@ -260,7 +260,7 @@ on-device (the caveat above).
build --release -p archipelago --bin archipelago`. (If `rust-lld: undefined hidden symbol`,
it's incremental cache — `CARGO_INCREMENTAL=0` fixes it.)
- SSH key `~/.ssh/archipelago-deploy` is authorized on `.116/.198/.228`. SSH/UI/RPC password
`ThisIsWeb54321@`. Per node: scp the binary, `sudo systemctl stop archipelago`
`<FLEET_PW>`. Per node: scp the binary, `sudo systemctl stop archipelago`
`kill -9 $(pgrep -x archipelago)``install -m0755` to `/usr/local/bin/archipelago`
`systemctl start archipelago`. Verify by `sha256sum` match + `systemctl is-active`.
- **Current deployed sha on all 3 = `ba4aed590027690d`** (the reboot-enabled build).
+2 -2
View File
@@ -99,7 +99,7 @@ lock, so the managed service (held stopped) can't collide. When it has connected
to ~the prior tip (height ≥ ~955800) it's done; then:
```sh
# on .228 (SSH/sudo/UI pw all: ThisIsWeb54321@)
# on .228 (SSH/sudo/UI pw all: <FLEET_PW>)
podman stop -t 600 bitcoin-knots-reindex && podman rm bitcoin-knots-reindex
# start the managed service via RPC (sets desired=running, clears user_stopped):
# package.start {id: bitcoin-knots} (POST https://127.0.0.1/rpc/v1, CSRF: echo csrf_token cookie as X-CSRF-Token)
@@ -128,4 +128,4 @@ NO `Error initializing block database` and NO data loss:
Core 29.2** (exists). Revisit if a Knots 29.2 was meant.
- Reindex is unavoidable ONLY because .228's index was already corrupted by the pre-fix
crash loop; a normal switch on the fixed binary does NOT reindex.
- Creds for .228: SSH/sudo + UI/RPC all `ThisIsWeb54321@`.
- Creds for .228: SSH/sudo + UI/RPC all `<FLEET_PW>`.
+12 -4
View File
@@ -1,14 +1,22 @@
import { chromium } from './node_modules/playwright/index.mjs';
const BASE = 'https://100.66.157.121';
const PASS = 'ThisIsWeb54321@';
const DIR = '/tmp/claude-1000/-home-debian/97c10035-69a8-40a0-9b55-219eb8ad683a/scratchpad';
// Node under test + credentials come from the environment; never commit literals.
// ARCHY_NODE_URL=https://<node> ARCHY_NODE_PW=… node test-openwrt.mjs
const BASE = process.env.ARCHY_NODE_URL || 'https://127.0.0.1';
const PASS = process.env.ARCHY_NODE_PW;
const DIR = process.env.ARCHY_OUT_DIR || '/tmp/openwrt-test';
if (!PASS) {
console.error('ERROR: ARCHY_NODE_PW must be set in the environment.');
process.exit(2);
}
// Find the OpenWrt router IP from the Tailscale/LAN
const { execSync } = await import('child_process');
let routerIp = '192.168.1.1';
try {
const route = execSync("ssh archipelago@100.66.157.121 'ip route | grep default'", { encoding: 'utf8' }).trim();
const sshTarget = process.env.ARCHY_NODE_SSH || `archipelago@${new URL(BASE).hostname}`;
const route = execSync(`ssh ${sshTarget} 'ip route | grep default'`, { encoding: 'utf8' }).trim();
const match = route.match(/default via ([\d.]+)/);
if (match) routerIp = match[1];
} catch {}
+11 -3
View File
@@ -2,8 +2,9 @@
# Post-install + onboarding + container lifecycle E2E tests.
# Run on an installed Archipelago node (SSH or local).
#
# Usage: bash run-post-install-tests.sh [password]
# bash run-post-install-tests.sh --phase1-only # Install checks only (no auth)
# Usage: bash run-post-install-tests.sh --password-stdin # read password from stdin (preferred)
# bash run-post-install-tests.sh [password] # argv form; visible in `ps`, local use only
# bash run-post-install-tests.sh --phase1-only # Install checks only (no auth)
#
# Tests:
# Phase 1: Install verification (services, files, logs) — safe, no side effects
@@ -12,15 +13,22 @@
set -u
PHASE1_ONLY=false
PASSWORD="testpass123!"
PASSWORD=""
for arg in "$@"; do
case "$arg" in
--phase1-only) PHASE1_ONLY=true ;;
--password-stdin) IFS= read -r PASSWORD || true ;;
*) PASSWORD="$arg" ;;
esac
done
if [ "$PHASE1_ONLY" = false ] && [ -z "$PASSWORD" ]; then
echo "ERROR: no password supplied. Use --password-stdin, pass one as an argument," >&2
echo " or run --phase1-only for the no-auth install checks." >&2
exit 2
fi
BASE="http://127.0.0.1:5678"
JAR="/tmp/e2e-cookies.txt"
rm -f "$JAR"
+1 -1
View File
@@ -23,7 +23,7 @@
#
# Nodes override via env (each must have a Meshtastic radio on the SAME LoRa
# channel/region so they can actually hear each other):
# MA_URL MA_PW node A (sender) default .116 http / ThisIsWeb54321@
# MA_URL MA_PW node A (sender) default .116 http / <FLEET_PW>
# MB_URL MB_PW node B (receiver) default .228 https / password123
# MC_URL MC_PW node C (eavesdrop) OPTIONAL — enables privacy test (4)
#
+2 -2
View File
@@ -47,7 +47,7 @@ survives a session cutoff.
## Rules (from user, 2026-06-15)
- **No new features** until the OS is production / no-bugs quality.
- **Test-harness-first**: build/extend a harness for each bug before fixing.
- **Validate every fix on `.116` + `.198`** (both 192.168.1.x, pw ThisIsWeb54321@) **+ the harness** BEFORE it goes into any release. (.198 still carries the LND CORS nginx duplicate → good for fix-(a) validation; .116 does not.)
- **Validate every fix on `.116` + `.198`** (both 192.168.1.x, pw <FLEET_PW>) **+ the harness** BEFORE it goes into any release. (.198 still carries the LND CORS nginx duplicate → good for fix-(a) validation; .116 does not.)
- **Priority order**: cloud/federated-nodes + mesh FIRST, then app-specific, then low-pri.
## Status legend
@@ -246,7 +246,7 @@ All backlog bugs now mirrored as Gitea issues: B1→#8, B2→#9, B3→#10, B4→
## Progress log
- 2026-06-15: tracker created. v1.7.96-alpha shipped. All 19 bugs filed as Gitea issues #8#26. vps2 feature issues (G#3/5/6) deferred (no new features).
- 2026-06-15: **B5 (LND CORS) ✅ DONE** — root-caused, both fixes implemented, verified on .116/.198/.103 (harness 4/4 each), committed `1db720af`, pushed to vps2 main. Will bundle into .97 (Gitea #12 to close on .97 ship).
- Validation nodes: .116 + .198 (pw ThisIsWeb54321@). Runtime is podman (docker not in non-interactive PATH). Sideload binary → /usr/local/bin/archipelago + restart (containers survive on these nodes).
- Validation nodes: .116 + .198 (pw <FLEET_PW>). Runtime is podman (docker not in non-interactive PATH). Sideload binary → /usr/local/bin/archipelago + restart (containers survive on these nodes).
- 2026-06-15 (cont.): **B1,B2,B4 ✅** dedup+guard — committed `ed493106`, unit-tested 2/2, live .198 healthy. **B14 ✅** transport recording — committed `1c6dc153` (after build-repair: used private `crate::federation::storage::` path → E0603; fixed to re-exported `crate::federation::`). **B21 ✅** Tor/FIPS pill — committed `0801dd66`. All pushed to vps2 main; builds verified EXIT 0.
- **Discovered B14b** (FIPS reaches only ~4/15 peers; rest genuinely Tor) and **B21** (pill) during the block.
- ⚠️ LESSON: a backgrounded build "completed" notification does NOT mean success — grep the EXIT code before committing (a broken commit reached main once; repaired by 1c6dc153; no release cut from it → fleet unaffected).