From 55f1208eb89bcbb1ff501c998d4a3927779c0313 Mon Sep 17 00:00:00 2001 From: abiba-bot Date: Fri, 11 Sep 2026 17:30:33 +0000 Subject: [PATCH] no-mistakes(review): scope dsh token to invocation; log nginx diagnostics --- scripts/capture-dsh-token.sh | 41 +++++++++++++++++++++++------------- zulip-health.prose.md | 15 +++++++------ 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/scripts/capture-dsh-token.sh b/scripts/capture-dsh-token.sh index bcce34f..342275a 100755 --- a/scripts/capture-dsh-token.sh +++ b/scripts/capture-dsh-token.sh @@ -14,8 +14,8 @@ # reference the token of the RUNNING process. # # This script: -# 1. selects the launch token the RUNNING service actually accepts — it NEVER -# stops or starts dsh-web, +# 1. selects the launch token the RUNNING service actually accepts from the +# current systemd invocation — it NEVER stops or starts dsh-web, # 2. records it in /etc/dsh-web/launch-token, # 3. regenerates the nginx include /etc/dsh-web/nginx-login.conf (the # `proxy_pass ...?token=` line consumed by /dsh-web-login), @@ -78,8 +78,8 @@ if [ -e "$LEGACY_8081" ] || [ -L "$LEGACY_8081" ]; then mv "$LEGACY_8081" "$STASHED" chmod 600 "$STASHED" 2>/dev/null || true touch "$PENDING_FILE" - if ! nginx -t >/dev/null 2>&1; then - die "nginx config test failed after disabling $LEGACY_8081 (kept disabled at $STASHED); a pending reload is recorded so running nginx is reloaded once the config is fixed. The legacy :8081 endpoint will NOT be restored." + if ! NGINX_TEST_OUT="$(nginx -t 2>&1)"; then + die "nginx config test failed after disabling $LEGACY_8081 (kept disabled at $STASHED): $NGINX_TEST_OUT; a pending reload is recorded so running nginx is reloaded once the config is fixed. The legacy :8081 endpoint will NOT be restored." fi if ! nginx -s reload; then die "nginx reload failed after disabling $LEGACY_8081 (kept disabled at $STASHED); a pending reload is recorded so running nginx is reloaded on the next run. The legacy :8081 endpoint will NOT be restored." @@ -93,8 +93,8 @@ fi # never remain loaded in the running nginx while dsh-web is down or not yet # answering. Reconcile it before the token wait. if [ -e "$PENDING_FILE" ]; then - if ! nginx -t >/dev/null 2>&1; then - log "WARNING: pending nginx reload recorded but 'nginx -t' fails; continuing so the include can be regenerated; will retry next run" + if ! NGINX_TEST_OUT="$(nginx -t 2>&1)"; then + log "WARNING: pending nginx reload recorded but 'nginx -t' fails: $NGINX_TEST_OUT; continuing so the include can be regenerated; will retry next run" elif ! nginx -s reload; then log "WARNING: pending nginx reload recorded but 'nginx -s reload' failed; will retry next run" else @@ -104,14 +104,25 @@ if [ -e "$PENDING_FILE" ]; then fi # ── 2. Select the token the RUNNING service actually accepts ──────────────── -# Functionally verify each journal candidate against the local dsh-web using the -# public authority, exactly as the /dsh-web-login proxy does. A token from a -# previous invocation is rejected (never 303) and can never be selected, so no -# systemd invocation scoping or newest-overall fallback is needed. Candidates -# are tried newest-first and re-read from the journal each pass until one is +# Read candidates ONLY from the service's current systemd invocation so a +# restarted process's stale token is never considered while its new startup +# banner is still pending; there is no whole-journal or cross-invocation +# fallback. Each candidate is then functionally verified against the local +# dsh-web using the public authority, exactly as the /dsh-web-login proxy does, +# and the first that answers 303 is the live token. Candidates are re-probed +# newest-first on each pass (connection failures stay eligible) until one is # accepted or the wait elapses. +INVOCATION="$(systemctl show -p InvocationID --value "$JOURNAL_UNIT" 2>/dev/null || true)" +JOURNAL_ARGS=(-u "$JOURNAL_UNIT") +if [ -n "$INVOCATION" ] && [ "$INVOCATION" != "n/a" ]; then + JOURNAL_ARGS+=("_SYSTEMD_INVOCATION_ID=$INVOCATION") +else + log "WARNING: no invocation id for $JOURNAL_UNIT; no token can be selected this run" +fi + collect_tokens() { - journalctl -u "$JOURNAL_UNIT" --no-pager -o cat 2>/dev/null \ + [ "${#JOURNAL_ARGS[@]}" -ge 3 ] || return 0 + journalctl "${JOURNAL_ARGS[@]}" --no-pager -o cat 2>/dev/null \ | grep -oE 'dsh web: https?://[^[:space:]]+[?&]token=[^[:space:]]+' \ | sed -E 's/.*[?&]token=//' \ | grep -E '^[A-Za-z0-9._~+/=:@-]+$' \ @@ -134,7 +145,7 @@ while [ -z "$TOKEN" ] && [ "$SECONDS" -lt "$DEADLINE" ]; do done if [ -z "$TOKEN" ]; then - log "no dsh-web launch token accepted within ${TOKEN_WAIT}s; leaving the include untouched for the next run" + log "no accepted launch token in the current invocation within ${TOKEN_WAIT}s; leaving the include untouched for the next run" [ -e "$PENDING_FILE" ] && die "pending nginx reload could not be completed; will retry next run" exit 0 fi @@ -182,13 +193,13 @@ fi mv "$NEW_INCLUDE" "$INCLUDE_FILE" chmod 600 "$INCLUDE_FILE" -if ! nginx -t >/dev/null 2>&1; then +if ! NGINX_TEST_OUT="$(nginx -t 2>&1)"; then if [ -n "$RESTORE" ]; then mv "$RESTORE" "$INCLUDE_FILE" else rm -f "$INCLUDE_FILE" fi - die "nginx config test failed; previous include restored" + die "nginx config test failed: $NGINX_TEST_OUT; previous include restored" fi if ! nginx -s reload; then diff --git a/zulip-health.prose.md b/zulip-health.prose.md index 14a3666..7b8e0e6 100644 --- a/zulip-health.prose.md +++ b/zulip-health.prose.md @@ -292,12 +292,15 @@ proxy_pass http://127.0.0.1:3080/?token=; **Token refresh (non-disruptive):** `/opt/deepseek-harness/capture-dsh-token.sh` (source: -`scripts/capture-dsh-token.sh`) selects the live launch token by functionally -verifying journal candidates against dsh-web with `Host: tankodhs.sysloggh.net` -and using the first one the running process accepts with `303`; a stale token -from a previous invocation is rejected and can never be selected. It waits up to -120s for a restarted process to accept a token; every distinct candidate is -re-probed on each pass, so a token that briefly returns `000` while the service +`scripts/capture-dsh-token.sh`) reads candidate launch tokens from the journal +**scoped to the service's current systemd invocation** +(`systemctl show -p InvocationID` + `_SYSTEMD_INVOCATION_ID=`), so a restarted +process's stale token is never considered while its new startup banner is still +pending; there is no whole-journal or cross-invocation fallback. Each candidate +is then functionally verified against dsh-web with `Host: tankodhs.sysloggh.net`, +using the first the running process accepts with `303`. It waits up to 120s for +a restarted process to accept a token and re-probes every current-invocation +candidate on each pass, so a token that briefly returns `000` while the service is still starting is not disqualified. If none is accepted it leaves the include untouched and exits so the timer retries (exiting non-zero when a pending reload is still outstanding). It writes