#!/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"