aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/signal-receive.sh6
-rw-r--r--scripts/tests/agent-text.bats101
2 files changed, 96 insertions, 11 deletions
diff --git a/scripts/signal-receive.sh b/scripts/signal-receive.sh
index 8c3ef01..ffe292c 100755
--- a/scripts/signal-receive.sh
+++ b/scripts/signal-receive.sh
@@ -1,8 +1,10 @@
#!/usr/bin/env bash
# signal-receive.sh — drain the Signal pager account's inbound queue.
#
-# The pager identity (+15045173983) lives on velox (primary) and any linked
-# device (ratio). The Signal protocol expects a registered account to receive
+# The pager identity (+15045173983) lives on whichever machines hold it in their
+# local signal-cli — check with `signal-cli listAccounts` rather than assuming;
+# velox's 2026-08-13 reinstall wiped its registration and the old comment here
+# named it as primary. The Signal protocol expects a registered account to receive
# regularly; when it goes quiet, signal-cli prints a staleness warning
# ("Messages have been last received N days ago") and the account drifts toward
# an unhealthy state. This script pulls anything queued and exits, keeping the
diff --git a/scripts/tests/agent-text.bats b/scripts/tests/agent-text.bats
index e5d80fc..d4c5f9b 100644
--- a/scripts/tests/agent-text.bats
+++ b/scripts/tests/agent-text.bats
@@ -1,11 +1,14 @@
#!/usr/bin/env bats
# agent-text — the runtime-neutral Signal phone messenger ("text me"). Reaches
# Craig over Signal from any machine on the tailnet: sends directly wherever the
-# account is registered locally (velox, or any linked device), and ssh-relays to
-# velox from a machine that doesn't hold the account. These tests stub
-# ssh/signal-cli on PATH to verify command construction without a network or a
-# phone. The signal-cli stub answers `listAccounts` to control which branch the
-# dispatch takes. The final test covers the deprecated agent-page shim.
+# account is registered locally (any machine holding it, as primary or as a
+# linked device), and otherwise ssh-relays to the first relay host that holds
+# it. These tests stub ssh/signal-cli/uname on PATH to verify command
+# construction without a network or a phone. The signal-cli stub answers
+# `listAccounts` to control which branch the dispatch takes; the uname stub
+# fixes the machine identity, so the self-relay skip is exercised deterministically
+# rather than depending on which machine runs the suite. The final test covers
+# the deprecated agent-page shim.
setup() {
REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../.." && pwd)"
@@ -29,7 +32,14 @@ fi
echo "signal-cli \$*" >> "$LOG"
exit 0
EOF
- chmod +x "$STUBS/ssh" "$STUBS/signal-cli"
+ # SELF_HOST fixes what the script sees as this machine. Defaults to a name
+ # in neither relay list, so the plain relay tests reach the first host.
+ cat > "$STUBS/uname" <<EOF
+#!/bin/bash
+[ "\$1" = "-n" ] && { echo "\${SELF_HOST:-somewhere-else}"; exit 0; }
+exec /usr/bin/uname "\$@"
+EOF
+ chmod +x "$STUBS/ssh" "$STUBS/signal-cli" "$STUBS/uname"
}
teardown() {
@@ -42,14 +52,59 @@ teardown() {
[[ "$output" == *"usage"* ]]
}
-@test "relays through ssh to velox when the account is not local" {
+@test "relays to the first relay host when the account is not local" {
HAS_ACCOUNT=0 PATH="$STUBS:$PATH" run bash "$PAGE" build finished
[ "$status" -eq 0 ]
- grep -q "^ssh .*velox" "$LOG"
+ grep -q "^ssh .*ratio" "$LOG"
grep -q "15045173983" "$LOG"
grep -q "b1b5601e-6126-47f8-afaa-0a59f5188fde" "$LOG"
# printf %q escapes the space, so the relayed message reads build\ finished.
grep -qF 'build\ finished' "$LOG"
+ # First host answered, so the second is never tried.
+ ! grep -q "^ssh .*velox" "$LOG"
+}
+
+@test "never relays to this machine — the self host is skipped" {
+ # On ratio, relaying to ratio cannot work: reaching this branch means the
+ # account is not local, so the round trip lands on the same empty store.
+ SELF_HOST=ratio HAS_ACCOUNT=0 PATH="$STUBS:$PATH" run bash "$PAGE" hello
+ [ "$status" -eq 0 ]
+ ! grep -q "^ssh .*ratio" "$LOG"
+ grep -q "^ssh .*velox" "$LOG"
+}
+
+@test "the self skip survives an FQDN nodename on either side" {
+ # uname -n returns whatever /etc/hostname holds, which may be fully
+ # qualified. Both sides are stripped, so the guard must still fire -- if it
+ # compares a stripped candidate against an unqualified self, an FQDN
+ # nodename silently restores the self-relay bug on the away channel.
+ SELF_HOST=ratio.tailf3bb8c.ts.net HAS_ACCOUNT=0 PATH="$STUBS:$PATH" \
+ run bash "$PAGE" hi
+ [ "$status" -eq 0 ]
+ ! grep -q "^ssh .*ratio" "$LOG"
+ grep -q "^ssh .*velox" "$LOG"
+}
+
+@test "falls through to the next host when the first relay fails" {
+ cat > "$STUBS/ssh" <<EOF
+#!/bin/bash
+echo "ssh \$*" >> "$LOG"
+case "\$*" in *ratio*) exit 255 ;; esac
+exit 0
+EOF
+ chmod +x "$STUBS/ssh"
+ HAS_ACCOUNT=0 PATH="$STUBS:$PATH" run bash "$PAGE" retry me
+ [ "$status" -eq 0 ]
+ grep -q "^ssh .*ratio" "$LOG"
+ grep -q "^ssh .*velox" "$LOG"
+}
+
+@test "AGENT_TEXT_RELAYS overrides the default relay list" {
+ AGENT_TEXT_RELAYS="spare.example.net" HAS_ACCOUNT=0 PATH="$STUBS:$PATH" \
+ run bash "$PAGE" custom
+ [ "$status" -eq 0 ]
+ grep -q "^ssh .*spare.example.net" "$LOG"
+ ! grep -q "^ssh .*ratio" "$LOG"
}
@test "sends directly (no ssh) when the pager account is registered locally" {
@@ -59,7 +114,7 @@ teardown() {
! grep -q "^ssh " "$LOG"
}
-@test "a failed relay reports the desktop fallback and propagates failure" {
+@test "every relay failing reports the desktop fallback and propagates failure" {
cat > "$STUBS/ssh" <<'EOF'
#!/bin/bash
exit 255
@@ -70,6 +125,34 @@ EOF
[[ "$output" == *"notify"* ]]
}
+@test "no reachable relay at all still fails rather than reporting success" {
+ # Every candidate is this machine, so the loop body never runs. rc must stay
+ # at its non-zero seed: a skipped loop is not a delivered message.
+ AGENT_TEXT_RELAYS="ratio.tailf3bb8c.ts.net" SELF_HOST=ratio HAS_ACCOUNT=0 \
+ PATH="$STUBS:$PATH" run bash "$PAGE" nowhere to go
+ [ "$status" -ne 0 ]
+ [[ "$output" == *"notify"* ]]
+ ! grep -q "^ssh " "$LOG"
+}
+
+@test "a local send failure blames the local send, not the relay list" {
+ # On the machine that holds the account, no relay is ever consulted. A
+ # message naming the relay list sends whoever is debugging it off chasing
+ # the tailnet while the fault is on the box in front of them.
+ cat > "$STUBS/signal-cli" <<EOF
+#!/bin/bash
+if [ "\$1" = "listAccounts" ]; then echo "Number: +15045173983"; exit 0; fi
+exit 1
+EOF
+ chmod +x "$STUBS/signal-cli"
+ # This stub reports the account unconditionally, so it drives the direct
+ # branch on its own -- HAS_ACCOUNT would be decorative here.
+ PATH="$STUBS:$PATH" run bash "$PAGE" boom
+ [ "$status" -ne 0 ]
+ [[ "$output" == *"local signal-cli send failed"* ]]
+ [[ "$output" != *"no relay reachable"* ]]
+}
+
@test "the deprecated agent-page shim delegates to agent-text" {
HAS_ACCOUNT=1 PATH="$STUBS:$PATH" run bash "$SHIM" via shim
[ "$status" -eq 0 ]