fix(git-tools): refuse no-ci assertion without an attributable identity
ci/woodpecker/pr/ci Pipeline was successful

The --no-ci-expected admin-success path accepted an asserted-by=unknown
pass when MOSAIC_GIT_IDENTITY was unset or empty, so the queue-clear
assertion and its NO_CI_ASSERTED audit record named no one. Refuse such
callers with a distinct ASSERTION_UNATTRIBUTABLE outcome (exit 78, audit
recorded) before queue-clear and before the permission lookup, so an
unattributable caller never triggers that network call. Document exit 78
in the usage text and the tools reference; pin the path with a
regression case (admin stub + env -u MOSAIC_GIT_IDENTITY).
This commit is contained in:
2026-08-23 12:52:44 -05:00
parent 28f4002a70
commit 187d70be12
3 changed files with 57 additions and 3 deletions
@@ -28,7 +28,7 @@ Options:
-i, --interval SECONDS Poll interval in seconds (default: 15)
--purpose VALUE Log context: push|merge (default: merge)
--require-status Fail if no CI status contexts are present
--no-ci-expected Assert this repository has no CI configured: a merge guard on a zero-context head becomes queue-clear (requires the acting token to hold repository admin)
--no-ci-expected Assert this repository has no CI configured: a merge guard on a zero-context head becomes queue-clear (requires the acting token to hold repository admin); refused with exit 78 when MOSAIC_GIT_IDENTITY is unset or empty
-h, --help Show this help
Examples:
@@ -597,7 +597,18 @@ while true; do
# the ONLY state the flag reclassifies: a pending or failed
# context still holds or fails exactly as without it, and a
# non-admin token is refused rather than trusted.
ASSERTED_BY="${MOSAIC_GIT_IDENTITY:-unknown}"
# The assertion must name an asserting identity: "unknown"
# attributes nothing, so a caller with MOSAIC_GIT_IDENTITY
# unset or empty is refused (exit 78) BEFORE the permission
# lookup -- an unattributable caller never triggers that
# network call.
if [[ -z "${MOSAIC_GIT_IDENTITY:-}" ]]; then
record_assertion_event "ASSERTION_UNATTRIBUTABLE" "actor-unattributable" "unknown" \
|| echo "Warning: could not write the ASSERTION_UNATTRIBUTABLE audit record; the refusal itself stands." >&2
echo "Error: ASSERTION_UNATTRIBUTABLE state=no-status purpose=merge asserted-by=unknown reason=no-ci-expected branch=${BRANCH}; --no-ci-expected requires MOSAIC_GIT_IDENTITY to name the asserting identity and it is unset or empty (exit 78)." >&2
exit 78
fi
ASSERTED_BY="${MOSAIC_GIT_IDENTITY}"
ADMIN_STATE=2
if [[ "$PLATFORM" == "github" ]]; then
if github_repo_admin_state "$OWNER" "$REPO"; then ADMIN_STATE=0; else ADMIN_STATE=$?; fi