Stop verify.sh reporting two things it cannot see

Both found running it on lin001 straight after the Caddy blocks went in.

The public-endpoint check called lf, cube and api unreachable. They are not:
the host resolves yokogawa.tech through the DC, which holds pinpoint records
only, and those three have none. Nothing is wrong with them and the check
cannot tell from here - so it now says so, and says to check from outside the
VNet, instead of printing a failure that means nothing.

403 now has its own message. It is what Caddy plus Authelia return for a
hostname with a site block and no access_control rule, which is the state
between applying the Caddy blocks and applying the Authelia rule - the one
case an operator is most likely to hit and least likely to recognise.

And the log check ran after the agent_ro test, which deliberately attempts a
forbidden INSERT that pg-ai logs. verify.sh was flagging an error line it had
just written itself.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Claude 2026-08-27 15:03:21 +10:00
parent 1ce0bab98c
commit eb8cfaa787

View file

@ -53,12 +53,23 @@ else
fi
head_ "Public endpoints - expect 302 to the auth portal"
# Run this from OUTSIDE the VNet as well. lin001 resolves yokogawa.tech through
# the DC, which holds pinpoint records only - ai and influx have one, lf, api
# and cube do not. So on this host those three do not resolve at all, and that
# says nothing about whether they work from a browser. The check reports the
# two cases separately rather than calling both a failure.
for host in lf.yokogawa.tech cube.yokogawa.tech api.yokogawa.tech ai.yokogawa.tech; do
if ! getent hosts "$host" >/dev/null 2>&1; then
printf ' ?? %s does not resolve FROM THIS HOST (no DC pinpoint record) - check it from outside the VNet
' "$host"
continue
fi
code=$(curl -s -o /dev/null -w '%{http_code}' -I "https://$host" --max-time 10 || echo "000")
case "$code" in
302|303) ok "$host -> $code (auth portal)" ;;
200) bad "$host -> 200 WITHOUT AUTH - check 'import authelia' in ~/Caddyfile" ;;
000) bad "$host unreachable - DNS A record missing, or Caddy has no certificate" ;;
403) bad "$host -> 403 - Caddy is serving it but Authelia has no access_control rule, so default_policy: deny applies. Add the hostname (authelia/access-rules.md)" ;;
000) bad "$host unreachable - Caddy has no certificate, or nothing is listening" ;;
*) bad "$host -> $code" ;;
esac
done
@ -71,6 +82,7 @@ head_ "The operator page and the API share an origin"
code=$(curl -s -o /dev/null -w '%{http_code}' -X POST "https://ai.yokogawa.tech/ask" -H 'Content-Type: application/json' -d '{}' --max-time 10 || echo "000")
case "$code" in
302|303) ok "ai.yokogawa.tech/ask -> $code (routed to ai-api, gated)" ;;
403) bad "ai.yokogawa.tech/ask -> 403 - Authelia has no rule for this hostname yet; the route cannot be proved until it does" ;;
404) bad "ai.yokogawa.tech/ask -> 404 - the /ask route is missing from the Caddy block; ai-web is answering" ;;
000) bad "ai.yokogawa.tech/ask unreachable" ;;
*) bad "ai.yokogawa.tech/ask -> $code" ;;
@ -84,6 +96,17 @@ else
ok "ai-web bundle carries no cross-origin API hostname"
fi
# Runs BEFORE the agent_ro test on purpose. That test deliberately attempts an
# INSERT it is not allowed to make, which pg-ai logs as "permission denied for
# table equipment" - in the other order verify.sh flags, every single run, an
# error line it created itself.
head_ "Recent errors in the logs"
for name in pg-ai cube ai-api ai-web; do
errors=$(docker logs --tail 200 "$name" 2>&1 | grep -icE 'error|fatal|panic' || true)
[ "${errors:-0}" -eq 0 ] && ok "$name logs clean (last 200 lines)" \
|| bad "$name has $errors error lines - docker logs --tail 200 $name"
done
head_ "agent_ro is read-only"
if docker exec pg-ai psql -U agent_ro -d plant -tAc 'SELECT count(*) FROM equipment' >/dev/null 2>&1; then
ok "agent_ro can SELECT"
@ -125,12 +148,5 @@ fi
head_ "Disk"
df -h / /datadisk | sed 's/^/ /'
head_ "Recent errors in the logs"
for name in pg-ai cube ai-api ai-web; do
errors=$(docker logs --tail 200 "$name" 2>&1 | grep -icE 'error|fatal|panic' || true)
[ "${errors:-0}" -eq 0 ] && ok "$name logs clean (last 200 lines)" \
|| bad "$name has $errors error lines - docker logs --tail 200 $name"
done
printf '\n%s passed, %s failed\n' "$PASS" "$FAIL"
exit "$FAIL"