Skip to content

Commit 9d7e5f7

Browse files
ralyodioclaude
andcommitted
alert: cache the vault key so a logicsrc outage does not silence alerts
On 2026-10-28 app.logicsrc.com crash-looped 16:10-16:16Z; every alert in that window failed with "no API key (vault smshub--prod SMSHUB_ALERT_API_KEY)" and fell back to email, including the qrypt.chat sweep alert. The key was in the vault the whole time. Now the last key the vault returned is kept in ~/.local/state/alert/smshub-key (0600) and used when the vault cannot answer. A key smshub rejects is still reported loudly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 3c33cc8 commit 9d7e5f7

2 files changed

Lines changed: 29 additions & 0 deletions

File tree

‎bin/alert‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
# about the key without alerting anyone and sends that same email when it is
2121
# rejected, so a revoked key is found by cron, not by the next real outage.
2222
#
23+
# The vault key is cached in ~/.local/state/alert/smshub-key (0600) and used
24+
# when the vault cannot be read, so a logicsrc outage does not silence alerts.
25+
#
2326
# Exit 0 when sent or deliberately skipped, 1 when nothing went out.
2427
# Log: ~/.local/state/alert/alert.log
2528
set -uo pipefail
@@ -75,6 +78,17 @@ for r in csv.DictReader(open(sys.argv[1])):
7578
if r["key"]=="SMSHUB_ALERT_API_KEY": print(r["value"])' "$tmp/v.csv")
7679
fi
7780
rm -rf "$tmp"
81+
# The vault (app.logicsrc.com) lives on the same box this script watches, so it
82+
# is down exactly when alerts matter most. Keep the last key it gave us (0600)
83+
# and use that when it cannot answer; a key smshub rejects is still caught below.
84+
cache="$STATE/smshub-key"
85+
if [ -n "$apikey" ]; then
86+
[ "$(cat "$cache" 2>/dev/null)" = "$apikey" ] || (umask 077; printf '%s\n' "$apikey" >"$cache.tmp" && mv "$cache.tmp" "$cache")
87+
elif [ -s "$cache" ]; then
88+
apikey=$(cat "$cache")
89+
keysrc="the cached copy $cache (vault smshub--prod did not answer)"
90+
log "vault unreachable or key missing: using cached smshub key"
91+
fi
7892
fi
7993

8094
email() { # subject body

‎test/alert.sh‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,19 @@ run bad --check; rc=$?
5656
run bad --check; [ ! -s "$tmp/home/mail.out" ] && ok "--check: one key email per 6h" || bad "--check repeated email"
5757
run good --check && [ ! -f "$tmp/home/.local/state/alert/smshub-key-broken.last" ] && ok "--check on good key: exit 0, clears" || bad "--check good"
5858

59+
60+
# Vault outage: the last key the vault gave is cached and used. No logicsrc in
61+
# this HOME means "vault did not answer"; a fake logicsrc stands in for the vault.
62+
: >"$tmp/home/mail.out"; rm -f "$tmp/home/.local/state/alert/"*.last
63+
cat >"$tmp/home/.local/bin/logicsrc" <<'L'
64+
#!/usr/bin/env bash
65+
while [ $# -gt 0 ]; do [ "$1" = -o ] && { printf 'team,project,env,category,key,value,updated_at\np,smshub,prod,,SMSHUB_ALERT_API_KEY,good,\n' >"$2"; }; shift; done
66+
L
67+
chmod +x "$tmp/home/.local/bin/logicsrc"
68+
vrun() { HOME="$tmp/home" PATH="$tmp/home/.local/bin:$PATH" "$root/bin/alert" "$@" >/dev/null 2>&1; }
69+
vrun --key v1 "vault up" && [ "$(stat -c %a "$tmp/home/.local/state/alert/smshub-key")" = 600 ] && ok "vault key used and cached 0600" || bad "vault key cache"
70+
rm "$tmp/home/.local/bin/logicsrc"
71+
vrun --key v2 "vault down" && [ ! -s "$tmp/home/mail.out" ] && grep -q 'using cached smshub key' "$tmp/home/.local/state/alert/alert.log" \
72+
&& ok "vault down: cached key still calls, no email" || bad "vault down: $(mailed)"
73+
5974
exit $fails

0 commit comments

Comments
 (0)