nigig-org/tools/check-no-pin-capture.sh
andodeki 5f999b7e9f
Some checks failed
email.yml / fix(tools): make test scripts executable for CI runners (push) Failing after 0s
repo hygiene / hygiene (push) Has been cancelled
Payment domain, storage, platform and UI / isolated-payment-tests (push) Failing after 2m57s
Payment domain, storage, platform and UI / payment-ui-tests (push) Failing after 4m10s
fix(tools): make test scripts executable for CI runners
2026-08-17 09:57:13 +00:00

101 lines
3.9 KiB
Bash
Executable file

#!/usr/bin/env bash
# Assert that a default build contains no custom M-Pesa PIN capture.
#
# Review item 0.3 requires removing custom PIN capture from the app flow.
# Hiding the widget is not enough: a hot reload or a re-instantiated sheet
# re-applies the UI definition, and a hidden `TextInput` still exists in the
# widget tree. The guarantee has to be that the field is not compiled at all.
#
# The check is a compile probe rather than a grep. A reference to `form_pin`
# is inserted outside any `cfg` block; a packaging build
# (`--no-default-features`) must reject it with "no field `form_pin`", and
# the default build must accept it. Grepping for the identifier would pass
# just as happily against a field that still exists behind a runtime `if`.
#
# Note the polarity: USSD automation is on by default, because it is the
# app's primary function. What this guards is that a build intended for
# release can still be produced with no PIN capture compiled in at all.
#
# Usage:
# ./tools/check-no-pin-capture.sh
set -Eeuo pipefail
IFS=$'\n\t'
REPO_ROOT="$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
SHEET="$REPO_ROOT/crates/apps/nigig-pay-ui/src/shared_pay_sheet.rs"
if [[ ! -f "$SHEET" ]]; then
echo "error: expected the pay sheet at $SHEET" >&2
exit 2
fi
# ── Part 1: the PIN controls must be hidden in the UI definition itself ──────
#
# The compile probe below proves the *field* is absent from a packaging build.
# It says nothing about the default build, where the field legitimately exists
# and the DSL is what keeps the control off screen until a demo build unhides
# it on init.
#
# That distinction matters: an unrelated commit removed `visible: false` from
# `pin_input` while leaving it on `pin_eye_btn`, and every existing gate still
# passed. A hidden-by-default control that becomes visible-by-default is
# exactly the DSL-reload hole review item 0.3 asks to close (defect B11).
for control in pin_input pin_eye_btn; do
if ! awk -v ctrl="$control" '
index($0, ctrl " :=") { found = 1; next }
found && /visible: false/ { ok = 1; exit }
found && /^[[:space:]]*}/ { exit }
END { exit(ok ? 0 : 1) }
' "$SHEET"; then
echo "FAIL: $control is not hidden by default in the DSL" >&2
echo " (review item 0.3: hiding must survive a DSL reload)" >&2
exit 1
fi
done
echo "PIN controls are hidden by default in the UI definition"
BACKUP="$(mktemp)"
cp "$SHEET" "$BACKUP"
restore() {
local status=$?
cp "$BACKUP" "$SHEET"
rm -f "$BACKUP"
exit "$status"
}
trap restore EXIT HUP INT TERM
ANCHOR=' fn clear_legacy_pin(&mut self, cx: &mut Cx) {'
if ! grep -qF "$ANCHOR" "$SHEET"; then
echo "error: probe anchor not found; update this script" >&2
exit 2
fi
PROBE=' #[allow(dead_code)]\n fn _pin_probe(\&self) -> usize { self.form_pin.len() }\n\n'
# Insert the probe immediately before the anchor.
awk -v probe=" #[allow(dead_code)]\n fn _pin_probe(&self) -> usize { self.form_pin.len() }\n" \
-v anchor="$ANCHOR" \
'index($0, anchor) && !done { print probe; done = 1 } { print }' \
"$BACKUP" > "$SHEET"
if ! grep -q "_pin_probe" "$SHEET"; then
echo "error: probe was not inserted; update this script" >&2
exit 2
fi
cd "$REPO_ROOT"
# A packaging build must refuse: the field does not exist there.
if cargo check -p nigig-pay-ui --no-default-features >/dev/null 2>&1; then
echo "FAIL: form_pin exists in a packaging build — PIN capture was not removed" >&2
exit 1
fi
# The default build must accept: automation is on, so the field exists.
if ! cargo check -p nigig-pay-ui --features demo >/dev/null 2>&1; then
echo "FAIL: the demo build does not compile with a form_pin reference" >&2
echo " (the probe may be stale, or the demo path is broken)" >&2
exit 1
fi
echo "no PIN capture in a packaging build; the default retains it deliberately"