nigig-org/crates/apps/nigig-mpesa/Cargo.toml
andodeki 23fce675de
Some checks failed
Payment domain, storage, platform and UI / isolated-payment-tests (push) Has been cancelled
Payment domain, storage, platform and UI / payment-ui-tests (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
feat(pay): USSD automation on by default; containment moves to packaging
Option A, as requested. Plus an audit of the whole review against the code.

## The default flips

  nigig-pay-ui   default = []            (leaf stays off; see below)
  nigig-pay      default = ["demo"]
  nigig-mpesa    default = ["demo"]
  pageflipnav    default = ["native", "demo"]

`cargo run -p pageflipnav` now drives *334#, shows the PIN field and
dispatches. That is the app's primary function and it works out of the box.

A release build opts out:

  cargo build -p pageflipnav --no-default-features --features native

This was not one line. A first attempt flipped the four `default =` lines
and the opt-out still leaked: the app crates depended on nigig-pay-ui with
its own defaults, so `--no-default-features` on pageflipnav was silently
re-enabled one level down. Verified with a compile probe rather than
cargo tree, which truncates. The inner deps now carry
`default-features = false`, and the probe confirms both directions:
default -> demo ON, --no-default-features -> demo OFF.

ADR 0007's Play-policy note is untouched. The containment requirement of
review item 0.1 is not dropped — the flag exists, CI exercises both
directions, and a shipped build still cannot dispatch. What changed is
which way it points by default, so development and device testing are not
fighting it.

CI guards inverted to match: they now assert automation is on by default
*and* that the packaging opt-out still works. check-no-pin-capture.sh now
probes the packaging build, since the default legitimately captures a PIN.

## REVIEWS/IMPLEMENTATION_AUDIT.md

Every phase checked against the code, not against the tranche notes. Where
they disagreed the code won. Summary: phases 0-5 and 7 done bar 5.2 and
Keystore provisioning; phase 6 substantially done with the thread_local
session ownership outstanding; phase 8 partly.

## B7 found live while auditing

Month navigation had never been examined. Both copies of the transactions
widget still stepped months with Duration::days(31) and years with
Duration::days(366). Reproduced before touching it:

  2025-12-28 -1 month => 2025-11-27   (drifts a day)
  2026-03-30 -1 month => 2026-02-27   (drifts; repeated steps skip a month)
  2027-06-15 +1 year  => 2028-06-15   (366d wrong on a non-leap year)

Now uses checked_add_months/checked_sub_months, which clamp to the end of
the target month, and checked_add_signed on the day path. An
unrepresentable date leaves the view where it was.

Neither claimed done nor flagged open — simply never looked at. That is the
argument for auditing code rather than notes.

## Validation

  domain 137 / storage 41 / platform 64 / mpesa 29 / pay-ui 61   pass
  cargo check: pay-ui, pay, mpesa, core (default and opt-out)    pass
  demo-on-by-default probe, both directions                      pass
  no-PIN-capture guard against the packaging build               pass

Unrelated and still blocking a full APK: nigig-map fails to compile on
clean HEAD (12 errors, no field center_lat on ViewportState).
2026-08-02 08:06:43 +00:00

58 lines
2.5 KiB
TOML

[package]
name = "nigig-mpesa"
version = "0.1.0"
edition = "2021"
[features]
## USSD automation is ON by default.
##
## Review item 0.1 asked for dispatch behind a compile-time flag. That was
## implemented as default-off, which made the *334# automation — the app's
## primary function — unreachable in an ordinary build, and unreachable at
## all from the APK crate until 9f0e133.
##
## The containment requirement has not been dropped; it has moved to release
## packaging, which is where a shipping decision belongs. A Play-listed build
## must be produced with `--no-default-features` (plus the features it does
## want), and the unresolved Google Play policy risk is recorded in
## REVIEWS/adr/0007-payment-platform-boundary.md.
##
## Turning it off for a build:
## cargo build -p pageflipnav --no-default-features --features native
default = ["demo"]
## Forwards to `nigig-pay-ui/demo`, which enables USSD dispatch, auto-retry
## and bulk pay.
##
## Off by default on purpose (review items 0.1/0.3): the default build is a
## tracker that never dials USSD and never handles an M-Pesa PIN. Without
## this feature the Pay sheet reports that dispatch is unavailable, which is
## the intended behaviour rather than a build error.
##
## Enabling it turns on AccessibilityService-driven USSD automation. That
## remains an unresolved Google Play policy risk (review item 5.2,
## REVIEWS/adr/0007) and must not be enabled for a shipped build.
##
## USSD only has a real backend on Android; every other target returns
## `PermanentlyUnavailable`, so this feature does nothing useful on desktop.
demo = ["nigig-pay-ui/demo"]
[dependencies]
makepad-widgets = { git = "https://gitdab.com/andodeki/makepad", rev = "a79f0dce4d477e2232344facca0798d3f25043ec", features = ["test"] }
nigig-core = { path = "../../nigig-core" }
nigig-uikit = { path = "../../nigig-uikit" }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
chrono = { version = "0.4", features = ["serde"] }
robius-sms = { version = "0.1.0", path = "../../robius-sms" }
robius-location = { git = "https://github.com/project-robius/robius", rev = "b766e62b0600f5d2ee21cc6995648346fc277bd8" }
robius-ussd = { path = "../../robius-ussd", features = ["serde"] }
robius-fingerprinting = { path = "../../robius-fingerprinting" }
nigig-pay-domain = { path = "../../nigig-pay-domain" }
nigig-pay-ui = { path = "../nigig-pay-ui", default-features = false }
robius-contacts = { version = "0.1.0", path = "../../robius-contacts" }
robius-trigger = { version = "0.1.0", path = "../../robius-trigger" }
[dev-dependencies]