Phase 6 and item 7.3 of REVIEWS/NIGIG_PAY_CONSOLIDATED_REVIEW.md. Rationale in REVIEWS/adr/0008. ## The rule, made into a type Phase 6's exit criterion is that the UI cannot call a transaction successful without trusted confirmation, or failed without known rejection. The old code violated it structurally: the sheet set its status inline in about a dozen places, each from whatever local signal was nearest, so there was nowhere to put the rule. The worst instance is U4. A payment whose confirmation SMS had not arrived in five minutes was marked Failed, the sheet closed, and the user saw "✗ Payment failed" — with a retry button — while the money was gone. payment_view_state.rs makes the rule a type. PaymentPresentation has no Success variant reachable from untrusted evidence and no Failed variant reachable from a missing SMS. VerificationExpired, Unknown and UnknownNeedsReconciliation all present as PendingConfirmation: not success, not failure, and no retry offered. Two defence-in-depth rows: Confirmed without a provider reference reads as unknown rather than settled, and an unclassified failure is not evidence nothing was sent. 6.2: ConfirmationSummary makes every required term a mandatory field, so a confirmation missing the fee or total is not constructible. It is built from the same quote that gets dispatched. material_digest() binds consent to the exact terms shown and is re-checked on OK — if anything material moved in between, the authorisation is void and the screen is shown again. The modal previously showed only recipient and amount. 6.3: must_stay_open() keeps pending payments visible, and the status line begins with the exact required wording, asserted by a test. 6.5: evidence rows are exposed and labelled untrusted; pending payments offer receipt, problem-reporting and data-deletion actions. ## Three defects found by writing the tests 1. Bulk quotes silently under-charged. compute_bulk_costs used filter_map over the fee lookup, so a contact outside the tariff was dropped from the fee total and the user was quoted less than they would pay. 2. The batch total could overflow — .sum() panics in debug, wraps in release. A wrapped total is a quote for the wrong amount. 3. The cost preview showed unknown fees as free via unwrap_or(0). All three are B5/B6 territory. Item 3 is B5 resurfacing in the preview path after tranche 1 fixed it in the dispatch path: fixing a defect at one call site is not the same as fixing the defect. ## A pre-existing failing test, diagnosed rather than deleted money::tests::ksh_rounds_to_nearest_cent asserted format_ksh(1.005) == "1.01" and had been failing on every run — confirmed pre-existing by stashing this work and re-running clean. The expectation is impossible, not the formatter wrong: 1.005 has no binary representation, the nearest f64 is 1.00499999999999989..., so the correctly rounded result is 1.00. This is defect B6 at its smallest. The test now says so, with a companion showing Money handling it exactly. Deleting it would have hidden a live argument for finishing B6. ## 7.3 UI tests in CI The NIGIG_TEST_PAY gate was already gone; what blocked CI was the Makepad link step. tools/makepad-native-libs.sh listed the libraries needed to compile but not libasound2-dev, libpulse-dev and libssl-dev, which are needed to link a test binary — cargo check succeeds and then "unable to find library -lasound" appears much later. The helper now installs and checks them, and a payment-ui-tests job runs the UI tests plus cargo check on nigig-pay-ui, nigig-pay and nigig-mpesa. ## Validation domain : 95 tests --locked, fmt, clippy -D warnings, bench pass storage : 36 + 41 sqlcipher --locked, fmt, clippy pass platform: 56 + 64 ussd --locked, fmt, clippy, mock guard pass nigig-pay-ui: cargo test --lib pass (61) nigig-pay-ui / nigig-pay / nigig-mpesa: cargo check pass Domain 75 -> 95 tests. UI 55 -> 61, with the long-standing failure fixed. Every new CI step was run locally before commit. ## Not claimed complete Phase 6 wiring is partial. PaymentViewState exists and is tested, and the confirmation path uses ConfirmationSummary, but the sheet's remaining status strings are still set inline and the thread_local PayFlowHandler still exists. The type makes that migration mechanical; it does not perform it. 6.6 bulk stays demo-gated pending ADR 0007's unresolved 5.2.
63 lines
1.7 KiB
Bash
63 lines
1.7 KiB
Bash
#!/usr/bin/env bash
|
|
# Native libraries needed to compile Makepad's Linux platform backend.
|
|
# This helper is intentionally opt-in: it never changes the host by default.
|
|
set -Eeuo pipefail
|
|
|
|
PACKAGES=(
|
|
pkg-config
|
|
libwayland-dev
|
|
libxkbcommon-dev
|
|
libx11-dev
|
|
libxi-dev
|
|
libxcursor-dev
|
|
libxrandr-dev
|
|
libgl1-mesa-dev
|
|
# robius-sms enables its Linux backend through polkit/gio.
|
|
libpolkit-gobject-1-dev
|
|
# Needed to *link* a test binary, not merely to `cargo check`. Makepad's
|
|
# audio backend pulls in ALSA and PulseAudio, and reqwest/rustls pulls in
|
|
# OpenSSL. Omitting these gives a confusing "unable to find library
|
|
# -lasound" at link time long after the compile appears to succeed.
|
|
libasound2-dev
|
|
libpulse-dev
|
|
libssl-dev
|
|
)
|
|
|
|
check() {
|
|
if ! command -v pkg-config >/dev/null 2>&1; then
|
|
echo "missing: pkg-config" >&2
|
|
return 1
|
|
fi
|
|
local missing=0
|
|
for pc in wayland-client xkbcommon x11 xi xcursor xrandr polkit-gobject-1 \
|
|
alsa libpulse openssl; do
|
|
if ! pkg-config --exists "$pc"; then
|
|
echo "missing native library: $pc" >&2
|
|
missing=1
|
|
fi
|
|
done
|
|
return "$missing"
|
|
}
|
|
|
|
install() {
|
|
if ! command -v apt-get >/dev/null 2>&1; then
|
|
echo "error: apt-get is required for automatic installation" >&2
|
|
return 2
|
|
fi
|
|
if [[ "${EUID:-$(id -u)}" -eq 0 ]]; then
|
|
apt-get update
|
|
apt-get install -y --no-install-recommends "${PACKAGES[@]}"
|
|
elif command -v sudo >/dev/null 2>&1; then
|
|
sudo apt-get update
|
|
sudo apt-get install -y --no-install-recommends "${PACKAGES[@]}"
|
|
else
|
|
echo "error: run as root or install sudo" >&2
|
|
return 2
|
|
fi
|
|
}
|
|
|
|
case "${1:---check}" in
|
|
--check) check ;;
|
|
--install) install && check ;;
|
|
*) echo "usage: $0 [--check|--install]" >&2; exit 2 ;;
|
|
esac
|