#!/bin/sh
# fleet commit-message gates  --  DOS reasons: PUBLIC_LEAK, HARDWARE_TELL, COMMIT_MSG
#
# Three gates over the commit MESSAGE itself, at the same boundary git checks it:
#
#   PUBLIC_LEAK (block) -- a leaked hostname/credential/needle in the SUBJECT or
#     BODY sails past the pre-commit content gate (which scans staged FILES, not
#     the message). This closes that gap with the SAME AUDIT_NEEDLES list
#     (tools/scrub_public_copy.py --audit-message), so a secret cannot ride into
#     history via the message. Mode FLEET_SCRUB_GUARD; escape FLEET_ALLOW_LEAK=1.
#
#   HARDWARE_TELL (block) -- a private lab node label (DGX/dgx3/A100/SXM4) in the
#     SUBJECT or BODY rides into immutable history the same way (the secret-needle
#     gate above never checked hardware names). Closes that gap with the SAME tells
#     the doc scrubber uses (tools/scrub_hardware_names.py --audit-message), so a
#     "docs: add the dgx3 decode" subject is blocked, not committed. A competitor
#     citation (1xA100) is NOT flagged. Mode FLEET_HW_GUARD; escape FLEET_ALLOW_HW=1.
#
#   COMMIT_MSG (warn) -- nudges the subject toward `type(scope): <verb> <what>`
#     so the DOS commit-audit witness can grade the commit (a noun-led subject
#     ABSTAINs, and an ABSTAIN on a landed commit is immutable).
#     Mode FLEET_MSG_GUARD; escape FLEET_ALLOW_MSG=1. Logic: check_commit_msg.py.
#
# Every gate FAILS OPEN if its checker cannot run (a broken check must never
# wedge every commit in the clone).

msgfile="$1"                       # save BEFORE `set --` clobbers the positionals
root="$(git rev-parse --show-toplevel 2>/dev/null)" || exit 0

# FAST PATH: `fak hooks commit-msg` runs the PUBLIC_LEAK (block), HARDWARE_TELL (block),
# and COMMIT_MSG (warn) gates in one process, honoring the SAME FLEET_* guard env vars.
# Exit 0 -> done; 1 -> a block gate fired; 2 -> could-not-run, fall through to the Python
# path below (fail-open).
if command -v fak >/dev/null 2>&1; then
	fak hooks commit-msg --root "$root" "$msgfile"
	_fak_st=$?
	[ "$_fak_st" -eq 0 ] && exit 0
	[ "$_fak_st" -eq 1 ] && exit 1
fi

# Resolve a python interpreter once (PY_A binary, PY_B optional `-3` for the
# Windows `py` launcher). Empty PY_A -> skip every gate (fail open).
if [ -n "${PYTHON:-}" ]; then PY_A="$PYTHON"; PY_B=""
elif command -v python3 >/dev/null 2>&1; then PY_A=python3; PY_B=""
elif command -v python  >/dev/null 2>&1; then PY_A=python;  PY_B=""
elif command -v py >/dev/null 2>&1; then PY_A=py; PY_B="-3"
else PY_A=""; PY_B=""; fi
[ -n "$PY_A" ] || exit 0

# ---- PUBLIC_LEAK: scan the message for redact needles (block by default) ----
leak_mode="${FLEET_SCRUB_GUARD:-block}"
scrub="$root/tools/scrub_public_copy.py"
if [ "$leak_mode" != "off" ] && [ "${FLEET_ALLOW_LEAK:-0}" != "1" ] && [ -f "$scrub" ]; then
	lout="$("$PY_A" $PY_B "$scrub" --audit-message "$msgfile" --root "$root" 2>&1)"; lst=$?
	if [ "$lst" -eq 1 ]; then
		if [ "$leak_mode" = "block" ]; then
			echo "$lout" >&2
			echo "PUBLIC_LEAK: the commit MESSAGE carries a redact needle (above)." >&2
			echo "  scrub the subject/body, or FLEET_ALLOW_LEAK=1 to override once (=warn/off softens)." >&2
			exit 1
		fi
		echo "PUBLIC_LEAK (advisory): redact needle in the commit message:" >&2
		echo "$lout" >&2
	fi
	# lst 0 (clean) or 2 (could-not-read) -> fall through; never wedge on a broken check.
fi

# ---- HARDWARE_TELL: scan the message for a private lab node name (block by default) ----
# The hardware scrubber's --audit-message owns the FLEET_HW_GUARD / FLEET_ALLOW_HW logic
# (off/warn/escape), so the wrapper just runs it and blocks on exit 1. Same fail-open contract.
hw="$root/tools/scrub_hardware_names.py"
if [ -f "$hw" ]; then
	hout="$("$PY_A" $PY_B "$hw" --audit-message "$msgfile" 2>&1)"; hst=$?
	if [ "$hst" -eq 1 ]; then
		echo "$hout" >&2
		exit 1
	fi
	# hst 0 (clean / warned / escaped) or 2 (could-not-read) -> fall through (fail open).
fi

# ---- COMMIT_MSG: subject-shape advisory (warn by default) ----
mode="${FLEET_MSG_GUARD:-warn}"
[ "$mode" = "off" ] && exit 0
[ "${FLEET_ALLOW_MSG:-0}" = "1" ] && exit 0

chk="$root/tools/check_commit_msg.py"
[ -f "$chk" ] || exit 0

set -- "$PY_A" $PY_B

out="$("$@" "$chk" --file "$msgfile" 2>&1)"; status=$?
[ "$status" -eq 0 ] && exit 0
# status 2 (could-not-read) -> fail open, never wedge a commit over a style check
[ "$status" -ne 1 ] && exit 0

if [ "$mode" = "block" ]; then
	echo "$out" >&2
	echo "  (FLEET_MSG_GUARD=warn softens; =off disables; FLEET_ALLOW_MSG=1 overrides once)" >&2
	exit 1
fi
echo "COMMIT_MSG (advisory):" >&2
echo "$out" >&2
echo "  hard-enforce with FLEET_MSG_GUARD=block." >&2
exit 0
