fix(ops-log): a sub-tool must not drop the claim wrapping its caller

deploy-stack.sh claims and releases around its own work. When the agent
already held a longer claim for a multi-step operation, the deploy refreshed
it, then released it on exit -- silently dropping the protection partway
through the very operation it was guarding.

Caught live: a 45-minute claim on nh3-docker/althing-post-office, taken to
cover a build-push-deploy-verify rollout, was gone by the time the rollout
finished. Nothing refused anything, and nothing said so.

`ops-log claim` now exits 10 when the claim was already the caller's, and
leaves the holder file untouched. deploy-stack.sh treats 10 as "not mine to
release". Untouched matters as much as the exit code: a refresh would
overwrite the reason and TTL the original claimant chose, so a deliberate
45-minute "3.7.0 rollout in progress" would degrade into "deploy-stack.sh
<host> <stack>" and whoever got refused would read the wrong story.

Verified in three states: no pre-existing claim -> deploy claims and releases;
caller's own wider claim -> deploy refreshes nothing and leaves it standing
with its original reason; another agent's claim -> still refused with exit 3.
This commit is contained in:
vh
2026-09-19 06:50:17 -07:00
parent 920f37c6c2
commit 3e7d3a3e3d
2 changed files with 26 additions and 1 deletions
+7 -1
View File
@@ -131,7 +131,13 @@ if [ -x "$OPS_LOG" ] && [ "${DEPLOY_NO_CLAIM:-0}" != 1 ]; then
"$OPS_LOG" claim "$HOST" "$STACK" --ttl "${DEPLOY_CLAIM_TTL:-30m}" \
--why "deploy-stack.sh $HOST $STACK" -q || claim_rc=$?
case "$claim_rc" in
0) CLAIMED=1 ;;
0) CLAIMED=1 ;;
10) # We only refreshed a claim this agent already held for a wider
# operation. Do NOT release it on the way out — dropping someone's
# multi-step claim mid-operation is exactly the exposure the claim
# exists to prevent.
CLAIMED=0
echo "note: $HOST/$STACK was already claimed by you — leaving that claim in place." ;;
3) echo "error: refused — see the claim above. Wait for the holder, coordinate" >&2
echo " on althing, or override with DEPLOY_NO_CLAIM=1 if it is dead." >&2
exit 3 ;;