From e10a33e80d7b3d1e04575acd6fa571632ded1bee Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Wed, 4 Nov 2026 20:13:34 +0000 Subject: [PATCH] fix(ci): admit exact panic-attack subjects to lock recovery Add panic-attack as the fifth explicit repository in both the dispatch and generator admission boundaries. Keep the fixed Hypatia push subject, read-only token, canonical tool/source pins and candidate-only behavior. Extend wrong-owner, suffix, legacy-alias and malformed-revision controls; all 29 local boundary groups and workflow actionlint pass. --- .github/workflows/actions-lock-recovery.yml | 3 ++- docs/ACTIONS-LOCK-RECOVERY.adoc | 9 +++++---- scripts/generate-lock-recovery-candidate.sh | 2 +- tests/actions-lock-recovery.sh | 16 ++++++++-------- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/.github/workflows/actions-lock-recovery.yml b/.github/workflows/actions-lock-recovery.yml index ccb057c..0e099f4 100644 --- a/.github/workflows/actions-lock-recovery.yml +++ b/.github/workflows/actions-lock-recovery.yml @@ -16,6 +16,7 @@ on: - hyperpolymath/boj-server-cartridges - hyperpolymath/echidna - hyperpolymath/cicd-squabbler + - hyperpolymath/panic-attack sha: description: Exact 40-hex subject commit; never a branch or tag type: string @@ -49,7 +50,7 @@ jobs: REQUESTED_SHA=936196794e0266715e7b1902893cdcbca64ef73a fi case "$REQUESTED_REPO" in - hyperpolymath/hypatia|hyperpolymath/boj-server-cartridges|hyperpolymath/echidna|hyperpolymath/cicd-squabbler) ;; + hyperpolymath/hypatia|hyperpolymath/boj-server-cartridges|hyperpolymath/echidna|hyperpolymath/cicd-squabbler|hyperpolymath/panic-attack) ;; *) echo 'Repository is outside this recovery scope'; exit 2 ;; esac [[ "$REQUESTED_SHA" =~ ^[0-9a-f]{40}$ ]] || { echo 'An exact subject SHA is required'; exit 2; } diff --git a/docs/ACTIONS-LOCK-RECOVERY.adoc b/docs/ACTIONS-LOCK-RECOVERY.adoc index 812530d..7580618 100644 --- a/docs/ACTIONS-LOCK-RECOVERY.adoc +++ b/docs/ACTIONS-LOCK-RECOVERY.adoc @@ -2,14 +2,15 @@ = Actions lock recovery candidate runner This is a narrowly scoped maintenance runner, not a replacement governance -gate. It creates a reviewable lock candidate for the four explicitly admitted +gate. It creates a reviewable lock candidate for the five explicitly admitted repositories: `hyperpolymath/hypatia`, `hyperpolymath/boj-server-cartridges`, -`hyperpolymath/echidna` and `hyperpolymath/cicd-squabbler`. +`hyperpolymath/echidna`, `hyperpolymath/cicd-squabbler` and +`hyperpolymath/panic-attack`. The initial Hypatia use addresses an unreadable lock that prevents its own workflows from starting. BoJ uses the same canonical generation chain to reconcile its reviewed wrapper changes and existing dependency drift. -Echidna and CI/CD Squabbler use the same chain for their reviewed +Echidna, CI/CD Squabbler and panic-attack use the same chain for their reviewed reusable-workflow pin changes. Candidate generation runs outside the target so a lock-dependent startup failure cannot prevent inspection. @@ -20,7 +21,7 @@ required check or alters a repository security setting. The first execution is limited to pushes on `repair/actions-lock-recovery` and subject commit `936196794e0266715e7b1902893cdcbca64ef73a`. Manual dispatch -requires one of those four repository choices and a full 40-hex commit. +requires one of those five repository choices and a full 40-hex commit. The push subject and default choice remain Hypatia; branches, tags, other repositories and similarly named slugs are refused by both the workflow and the generator. Subject code is checked out for inspection and is never executed. diff --git a/scripts/generate-lock-recovery-candidate.sh b/scripts/generate-lock-recovery-candidate.sh index 7620730..35bb796 100644 --- a/scripts/generate-lock-recovery-candidate.sh +++ b/scripts/generate-lock-recovery-candidate.sh @@ -10,7 +10,7 @@ output=${RECOVERY_OUTPUT:?} authority_sha=d3e4b485a2af90c92a8e18af0888cd19cb132cd9 root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) case "$repository" in - hyperpolymath/hypatia|hyperpolymath/boj-server-cartridges|hyperpolymath/echidna|hyperpolymath/cicd-squabbler) ;; + hyperpolymath/hypatia|hyperpolymath/boj-server-cartridges|hyperpolymath/echidna|hyperpolymath/cicd-squabbler|hyperpolymath/panic-attack) ;; *) echo 'Recovery subject is outside the admitted repository scope'; exit 2 ;; esac [[ "$revision" =~ ^[0-9a-f]{40}$ ]] \ diff --git a/tests/actions-lock-recovery.sh b/tests/actions-lock-recovery.sh index 7da54dd..020248b 100644 --- a/tests/actions-lock-recovery.sh +++ b/tests/actions-lock-recovery.sh @@ -69,7 +69,7 @@ rc=0 [[ "$rc" -eq 2 && ! -s "$CALL_LOG" ]] echo 'ok: wrong original digest is refused before invoking the tool' -for repo in '' untrusted/hypatia hyperpolymath/other hyperpolymath/boj-server hyperpolymath/boj-server-cartridges-extra untrusted/echidna hyperpolymath/echidna-extra untrusted/cicd-squabbler hyperpolymath/cicd-squabbler-extra hyperpolymath/squabbler; do +for repo in '' untrusted/hypatia hyperpolymath/other hyperpolymath/boj-server hyperpolymath/boj-server-cartridges-extra untrusted/echidna hyperpolymath/echidna-extra untrusted/cicd-squabbler hyperpolymath/cicd-squabbler-extra hyperpolymath/squabbler untrusted/panic-attack hyperpolymath/panic-attack-extra hyperpolymath/panic-attacker; do rc=0 SUBJECT_REPOSITORY=$repo SUBJECT_SHA=0123456789abcdef0123456789abcdef01234567 \ SUBJECT_DIR="$tmp/fixture" AUTHORITY_DIR="$tmp/authority" RECOVERY_OUTPUT="$tmp/output" RUNNER_TEMP=$tmp \ @@ -79,7 +79,7 @@ for repo in '' untrusted/hypatia hyperpolymath/other hyperpolymath/boj-server hy done echo 'ok: candidate generator refuses other repositories' -for repo in hyperpolymath/hypatia hyperpolymath/boj-server-cartridges hyperpolymath/echidna hyperpolymath/cicd-squabbler; do +for repo in hyperpolymath/hypatia hyperpolymath/boj-server-cartridges hyperpolymath/echidna hyperpolymath/cicd-squabbler hyperpolymath/panic-attack; do rc=0 SUBJECT_REPOSITORY=$repo SUBJECT_SHA=0123456789abcdef0123456789abcdef01234567 \ SUBJECT_DIR="$tmp/fixture" AUTHORITY_DIR="$tmp/authority" RECOVERY_OUTPUT="$tmp/outside" RUNNER_TEMP="$tmp/runner" \ @@ -96,7 +96,7 @@ for repo in hyperpolymath/hypatia hyperpolymath/boj-server-cartridges hyperpolym grep -Fxq 'Recovery subject is outside the admitted repository/revision scope' "$tmp/log" done done -echo 'ok: candidate generator refuses floating, partial and malformed revisions for all four repositories' +echo 'ok: candidate generator refuses floating, partial and malformed revisions for all five repositories' # Execute the workflow's actual data-transfer blocks against local Git # fixtures. Source scripts and Git hooks are data, never commands to run. @@ -104,12 +104,12 @@ command -v yq >/dev/null || { echo 'yq unavailable for transfer controls'; exit workflow="$root/.github/workflows/actions-lock-recovery.yml" yq -o=json '.on.workflow_dispatch.inputs.repo' "$workflow" | jq -e ' .type == "choice" and .required == true and .default == "hyperpolymath/hypatia" and - .options == ["hyperpolymath/hypatia", "hyperpolymath/boj-server-cartridges", "hyperpolymath/echidna", "hyperpolymath/cicd-squabbler"]' >/dev/null + .options == ["hyperpolymath/hypatia", "hyperpolymath/boj-server-cartridges", "hyperpolymath/echidna", "hyperpolymath/cicd-squabbler", "hyperpolymath/panic-attack"]' >/dev/null yq -r '.jobs."acquire-subject".steps[] | select(.id == "subject") | .run' "$workflow" > "$tmp/admit.sh" [[ -s "$tmp/admit.sh" ]] || exit 2 export GITHUB_OUTPUT="$tmp/subject-outputs" valid_sha=0123456789abcdef0123456789abcdef01234567 -for repo in hyperpolymath/hypatia hyperpolymath/boj-server-cartridges hyperpolymath/echidna hyperpolymath/cicd-squabbler; do +for repo in hyperpolymath/hypatia hyperpolymath/boj-server-cartridges hyperpolymath/echidna hyperpolymath/cicd-squabbler hyperpolymath/panic-attack; do : > "$GITHUB_OUTPUT" EVENT=workflow_dispatch REQUESTED_REPO=$repo REQUESTED_SHA=$valid_sha bash "$tmp/admit.sh" printf 'repository=%s\nsha=%s\n' "$repo" "$valid_sha" > "$tmp/expected-outputs" @@ -121,7 +121,7 @@ EVENT=push REQUESTED_REPO=untrusted/ignored REQUESTED_SHA=main bash "$tmp/admit. printf 'repository=hyperpolymath/hypatia\nsha=936196794e0266715e7b1902893cdcbca64ef73a\n' > "$tmp/expected-outputs" cmp "$tmp/expected-outputs" "$GITHUB_OUTPUT" echo 'ok: the push subject remains the fixed Hypatia revision' -for repo in '' untrusted/hypatia hyperpolymath/boj-server hyperpolymath/boj-server-cartridges-extra untrusted/echidna hyperpolymath/echidna-extra untrusted/cicd-squabbler hyperpolymath/cicd-squabbler-extra hyperpolymath/squabbler; do +for repo in '' untrusted/hypatia hyperpolymath/boj-server hyperpolymath/boj-server-cartridges-extra untrusted/echidna hyperpolymath/echidna-extra untrusted/cicd-squabbler hyperpolymath/cicd-squabbler-extra hyperpolymath/squabbler untrusted/panic-attack hyperpolymath/panic-attack-extra hyperpolymath/panic-attacker; do : > "$GITHUB_OUTPUT" rc=0 EVENT=workflow_dispatch REQUESTED_REPO=$repo REQUESTED_SHA=$valid_sha bash "$tmp/admit.sh" > "$tmp/log" 2>&1 || rc=$? @@ -129,7 +129,7 @@ for repo in '' untrusted/hypatia hyperpolymath/boj-server hyperpolymath/boj-serv grep -Fxq 'Repository is outside this recovery scope' "$tmp/log" done echo 'ok: workflow admission refuses absent, other-owner and similarly named repositories' -for repo in hyperpolymath/hypatia hyperpolymath/boj-server-cartridges hyperpolymath/echidna hyperpolymath/cicd-squabbler; do +for repo in hyperpolymath/hypatia hyperpolymath/boj-server-cartridges hyperpolymath/echidna hyperpolymath/cicd-squabbler hyperpolymath/panic-attack; do for bad_sha in '' main v0.2.0 0123456789abcdef ABCDEF0123456789ABCDEF0123456789ABCDEF0123 0123456789abcdef0123456789abcdef01234567extra; do : > "$GITHUB_OUTPUT" rc=0 @@ -138,7 +138,7 @@ for repo in hyperpolymath/hypatia hyperpolymath/boj-server-cartridges hyperpolym grep -Fxq 'An exact subject SHA is required' "$tmp/log" done done -echo 'ok: workflow admission refuses missing, floating, partial and malformed revisions for all four repositories' +echo 'ok: workflow admission refuses missing, floating, partial and malformed revisions for all five repositories' yq -r '.jobs."acquire-subject".steps[] | select(.id == "archive") | .run' "$workflow" > "$tmp/package.sh" yq -r '.jobs.candidate.steps[] | select(.name == "Verify and unpack the subject data") | .run' "$workflow" > "$tmp/unpack.sh" [[ -s "$tmp/package.sh" && -s "$tmp/unpack.sh" ]] || exit 2