igneum/relay/clients/make-clients.sh
igneum-labs 1065b81d05 relay: three auth tiers, signed run tasks, machine secrets, retention; clients on headers; TZ=UTC and curl -K checks (X23 X24 X25 X26 X27 X28 X29 G13 G14)
Relay (X23, X27): the intake key is its own tier (upload and file drops only, RELAY_INTAKE_COMPAT=0 closes it);
a run task needs an Ed25519 signature by the Mac run key over {to, nonce, body sha256, flags} (RELAY_RUN_PUB,
401 without) and an HMAC tag with the target's machine secret that the agent verifies before anything runs;
results and registration are bound to the machine the secret proves (403 on a forged from).
X24: every client and Mac tool sends x-relay-token as a header to /api/relay?fn=; the path token stays for the
phone page only. X25: the agent arms the logon task only for a restart a task asked for and disarms on start
and exit. X26: 30-day retention with blob deletion, feed capped at 100, the dl base as RELAY_DL_BASE held by the
agent, never in a body. X28: GET inbox never acks (POST inbox does), RELAY-REBOOT on its own line and only with a
reboot flag, 120/min and 10 failed auths/min per IP, no username or folder on register, WSL sudo scoped to
apt-get and dpkg with SETENV, no password on a command line. X29: the intake key reaches curl through -K in
upload.sh and both upload-log.bat; tools/ci/curl-header-check.sh fails the class. G14: TZ=UTC in ship-app.mjs
and publish-jobs.sh; tools/ci/commit-tz-check.sh fails the class; history-rewrite.md names the .old-2026-10-05
files as the values in the history. The handler moved to relay/lib/handler.mjs with injected sql and blobs
(relay/lib/blob.mjs holds @vercel/blob) so relay/test/handler.test.mjs drives it without a database:
47 tests across 6 suites, all green.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-05 18:46:13 +00:00

49 lines
3.1 KiB
Bash
Executable file

#!/usr/bin/env bash
# Bakes the relay URL, key, token and downloads base into copies of the clients and zips them. The files in the repo keep
# their placeholders; the zip is the secret-bearing artefact and goes to the PC by hand (USB stick, AirDrop), NEVER
# through the downloads host (review round 4, X23: the hosted zip put both relay secrets one dl token away).
#
# make-clients.sh [--machine NAME] [outdir-for-zip]
#
# --machine NAME also puts that machine's secret (~/.config/igneum/relay-machines/NAME, from `node tools/relay.mjs
# secret NAME`) into the zip as machine-secret.txt, which is what lets the agent there run signed tasks and lets its
# results carry its name (X23, X27). Without --machine the zip can read, post notes and files, and nothing runs.
# Reads ~/.config/igneum/relay-url (optional), relay-key, relay-token, dl-token (for RELAY_DL_BASE; X26: the base is a
# value the agent holds, never text in a task body).
set -euo pipefail
HERE="$(cd "$(dirname "$0")" && pwd)"
CFG="$HOME/.config/igneum"
MACHINE=""; OUT="$HOME/Desktop"
while [ $# -gt 0 ]; do
case "$1" in --machine) MACHINE="$2"; shift 2 ;; --*) echo "unknown flag $1" >&2; exit 2 ;; *) OUT="$1"; shift ;; esac
done
URL="$(cat "$CFG/relay-url" 2>/dev/null | tr -d '\n' || true)"; URL="${URL:-https://relay.igneum.network}"
KEY="$(tr -d '\n' < "$CFG/relay-key")"; TOKEN="$(tr -d '\n' < "$CFG/relay-token")"
DL="$(tr -d '[:space:]' < "$CFG/dl-token" 2>/dev/null || true)"
DL_BASE="https://dl.igneum.network/dl/${DL:-MISSING-DL-TOKEN}"
SECRET=""
if [ -n "$MACHINE" ]; then
SF="$CFG/relay-machines/$MACHINE"
[ -f "$SF" ] || { echo "no $SF: node tools/relay.mjs secret $MACHINE first" >&2; exit 1; }
SECRET="$(tr -d '[:space:]' < "$SF")"
[ ${#SECRET} = 64 ] || { echo "$SF is not a 64-hex secret" >&2; exit 1; }
fi
mkdir -p "$OUT"
NAME="igneum-relay-clients${MACHINE:+-$MACHINE}"
STAGE="$(mktemp -d)/$NAME"; mkdir -p "$STAGE"; umask 077
for f in send.bat send.ps1 send.sh igneum-agent.bat igneum-agent.ps1 agent.sh CLAUDE-PC.md; do
sed -e "s#__RELAY_URL__#$URL#g" -e "s#__RELAY_KEY__#$KEY#g" -e "s#__RELAY_TOKEN__#$TOKEN#g" -e "s#__DL_BASE__#$DL_BASE#g" "$HERE/$f" > "$STAGE/$f"
done
[ -n "$SECRET" ] && printf '%s\n' "$SECRET" > "$STAGE/machine-secret.txt"
# Windows reads CRLF batch files most reliably; PowerShell is fine either way
for f in send.bat igneum-agent.bat; do perl -pi -e 's/\r?\n/\r\n/' "$STAGE/$f"; done
chmod +x "$STAGE/send.sh" "$STAGE/agent.sh"
cat > "$STAGE/README.txt" <<TXT
Igneum relay clients${MACHINE:+ for $MACHINE}. Unzip anywhere. send.bat "<text>" | send.bat <file> | send.bat inbox | send.bat result "<text>" | send.bat get <id>
igneum-agent.bat: double-click once, leave open. CLAUDE-PC.md: paste into the Claude Code session on this PC.
These files contain the relay secret${MACHINE:+ and this machine's own secret (machine-secret.txt)}. Keep them off shared drives and off the downloads host.
TXT
rm -f "$OUT/$NAME.zip"
(cd "$(dirname "$STAGE")" && zip -qr "$OUT/$NAME.zip" "$NAME")
echo "staged: $STAGE"
echo "zip: $OUT/$NAME.zip ($(du -h "$OUT/$NAME.zip" | cut -f1)); carry it to the PC by hand, never through the downloads host"