fix(deploy): consume signed approval evidence exactly once
ChatGPT validation / quality (push) Failing after 0s

This commit is contained in:
2026-08-26 23:55:49 +02:00
parent c5cf384f9a
commit e377889263
+12 -1
View File
@@ -6,10 +6,12 @@ umask 027
# the Gitea runner. Targets are read from the root-owned data file below. # the Gitea runner. Targets are read from the root-owned data file below.
# Approved machine deployments additionally verify an AppOps Ed25519 signature # Approved machine deployments additionally verify an AppOps Ed25519 signature
# using the root-controlled public key; the Actions runner never receives that # using the root-controlled public key; the Actions runner never receives that
# trust anchor's private key. # trust anchor's private key. Every verified approval id is consumed exactly
# once in a root-owned replay journal before target lookup or mutation.
readonly CONFIG_FILE="/etc/forgeflow/targets.conf" readonly CONFIG_FILE="/etc/forgeflow/targets.conf"
readonly EVIDENCE_PUBLIC_KEY_FILE="/etc/forgeflow/evidence.pub" readonly EVIDENCE_PUBLIC_KEY_FILE="/etc/forgeflow/evidence.pub"
readonly EVIDENCE_REPLAY_DIR="/var/lib/forgeflow-status/approved-requests"
readonly REPOSITORY="${1:-}" readonly REPOSITORY="${1:-}"
readonly ENVIRONMENT="${2:-}" readonly ENVIRONMENT="${2:-}"
readonly SHA="${3:-}" readonly SHA="${3:-}"
@@ -81,6 +83,15 @@ if (( $# == 8 )); then
echo "Deployment evidence signature verification failed" >&2 echo "Deployment evidence signature verification failed" >&2
exit 65 exit 65
} }
# Consume the verified approval before any target lookup. mkdir is atomic,
# making this a cross-process replay fence. A failed first deployment still
# requires a fresh human approval, matching AppOps' terminal execution model.
install -d -o root -g root -m 0700 "$EVIDENCE_REPLAY_DIR"
if ! mkdir -m 0700 "$EVIDENCE_REPLAY_DIR/$APPROVAL_ID" 2>/dev/null; then
echo "Approved deployment evidence was already consumed" >&2
exit 65
fi
EVIDENCE_VERIFIED=true EVIDENCE_VERIFIED=true
fi fi