Commit graph

23 commits

Author SHA1 Message Date
d6b35d7989 test(spreadsheet-ui): add headless unit target
Some checks failed
PDF engine / engine (push) Has been cancelled
PDF engine / makepad-integration (push) Has been cancelled
PDF engine / fuzz (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
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
2026-07-31 19:57:04 +00:00
d0f5e74435 feat(pay): Phase 5 platform gateway boundary, and verify Phase 4
Some checks failed
nigig-map / test (push) Has been cancelled
Payment domain, storage and platform / isolated-payment-tests (push) Has been cancelled
nigig-build (CAD) / supply-chain (push) Has been cancelled
nigig-build (CAD) / cad-module (push) Has been cancelled
nigig-build (CAD) / full-crate-check (push) Has been cancelled
doc-engine / engine (push) Has been cancelled
doc-engine / consumer (push) Has been cancelled
PDF engine / fuzz (push) Has been cancelled
PDF engine / makepad-integration (push) Has been cancelled
PDF engine / engine (push) Has been cancelled
Phase 5 of REVIEWS/NIGIG_PAY_CONSOLIDATED_REVIEW.md. Design and the one
item engineering cannot close are in REVIEWS/adr/0007.

## Phase 4 is now verified, not just written

Tranche 5 implemented the draw_walk fixes and said plainly that the
nigig-pay widget edits were unbuilt. That blocker was environmental:
installing the packages tools/makepad-native-libs.sh already lists makes
the UI graph compile. Both commands the status doc listed as required
now pass:

  cargo check -p nigig-pay      pass
  cargo check -p nigig-pay-ui   pass

No code changed for this; the claim is now evidence rather than assertion.

## Phase 5: new nigig-pay-platform crate

ADR 0002 reserved this crate and marked it "not yet created".

5.1 One crate owns the seam. It is the only crate in the payment stack
that may name a platform SDK. CI enforces both directions: payment crates
may not import Makepad, and domain/storage may not import jni or the
robius platform crates.

5.3 Correlation is mandatory and single-flight. SessionRegistry admits an
event as Accepted, Duplicate or Ignored; PlatformEvent cannot be built
without a CorrelationId. Closed session ids are retired permanently, so
an abandoned session's confirmation cannot settle the payment that
replaced it. There is a test named after exactly that scenario.

2.8/5.3 Progress decides retry safety, not error kind. classify_failure
takes the failure and the DispatchProgress reached before it, and
progress is the authority. The same TemporarilyUnavailable is safely
retryable before the dial and ambiguous once the menu is being driven —
the distinction the old code could not make, which is defect B3's
mechanism. A property test asserts across the whole failure space that
nothing which may have reached the provider authorises a fresh attempt.

5.4 Fakes cannot ship. MockGateway is cfg-gated, is a compile_error! in a
release build unless allow-mock-in-release is named explicitly, and
stamps every session id with MOCK-. CI asserts the release build fails.

5.5 No unsafe, no PIN. The crate is #![forbid(unsafe_code)] so the JNI
surface stays in robius-ussd. UssdGateway is !Send/!Sync by construction,
making the main-thread requirement a compile error. The adapter leaves
the pin field empty and a test asserts it.

5.6 The web claim is withdrawn. No browser API can drive USSD and a
Daraja credential must never reach a browser, so WebGateway refuses every
call and maps to Fatal — "never sent" — which owes no reconciliation.

7.5 Adversarial SMS corpus. StrictMpesaSms is the payment-boundary
reader, deliberately separate from nigig-core's permissive tracker parser
(ADR 0007 explains why this is not the duplication ADR 0002 forbids). It
requires an exact 10-char code, exact sender-ID match so MPESA-REFUNDS
and FAKE-MPESA are refused, rejects fractional shillings instead of
rounding, and caps body length. Corpus covers spoofing, forged code
shapes, out-of-range amounts, unicode and NUL injection, and replay. The
closing test asserts the honest limit: a well-crafted forgery is still
only evidence, because the output type has no settled state to reach.

## 5.2 is not done and is not closeable here

The AccessibilityService Play-policy review is a business decision. ADR
0007 records it as blocking, states the termination exposure, and names
what must happen before the rail is enabled. USSD dispatch stays behind
the default-off demo feature. If the review fails, ADR 0001's
tracker/launcher position applies and only the dispatch adapter is lost.

## Validation

  platform: 56 tests, 64 with --features ussd, fmt, clippy -D warnings
            (both feature sets), cargo-deny, mock-in-release guard
            asserted to fail                                      pass
  domain:   75 tests --locked                                     pass
  storage:  36 + 41 tests --locked, incl. sqlcipher                pass
  nigig-pay, nigig-pay-ui: cargo check                            pass

cargo-deny reports advisories/bans/licenses/sources ok. The isolated
runner gained a `platform` target and it runs in CI on every push that
touches the crate.
2026-07-29 02:07:19 +00:00
Arena Bot
33dbece7d8 fix(ui): use valid syntax for assigning ids to metric values
Some checks failed
nigig-build (CAD) / supply-chain (push) Has been cancelled
nigig-build (CAD) / cad-module (push) Has been cancelled
nigig-build (CAD) / full-crate-check (push) Has been cancelled
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
PDF engine / engine (push) Has been cancelled
PDF engine / makepad-integration (push) Has been cancelled
PDF engine / fuzz (push) Has been cancelled
2026-07-29 01:56:41 +00:00
5b7e3bd7f9 test(spreadsheet-ui): add compile-only validation target
Some checks failed
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
PDF engine / engine (push) Has been cancelled
PDF engine / makepad-integration (push) Has been cancelled
PDF engine / fuzz (push) Has been cancelled
2026-07-28 19:20:20 +00:00
36d3255049 feat(valhalla): implement phase 3 valhalla-elevation skadi dem tile sampler, height endpoint, and isochrone service
Some checks failed
nigig-build (CAD) / supply-chain (push) Has been cancelled
nigig-build (CAD) / cad-module (push) Has been cancelled
nigig-build (CAD) / full-crate-check (push) Has been cancelled
PDF engine / engine (push) Has been cancelled
PDF engine / makepad-integration (push) Has been cancelled
PDF engine / fuzz (push) Has been cancelled
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
2026-07-28 17:05:56 +00:00
20e987ab6a feat(valhalla): implement tranche 4 GTFS public transit models, transitcost, and multimodal astar
Some checks failed
PDF engine / engine (push) Has been cancelled
PDF engine / makepad-integration (push) Has been cancelled
PDF engine / fuzz (push) Has been cancelled
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
2026-07-27 17:44:27 +00:00
b23df6a5cb feat(pdf): complete Phase 6 testing infrastructure
Some checks failed
PDF engine / engine (push) Has been cancelled
PDF engine / makepad-integration (push) Has been cancelled
PDF engine / fuzz (push) Has been cancelled
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
Phase 6 of REVIEWS/DART_PDF_VS_MAKEPAD_PDF_GAP_ANALYSIS.md: "Real PDFs. Real
regressions. No test theater."

Step 6.1, corpus. 27 fixtures across basic, fonts, forms, annotations,
images, edge and malformed, in the layout the review specifies. They are
produced by tests/corpus/generate.py rather than committed as opaque blobs,
because a corpus you cannot read is a corpus you cannot trust; CI regenerates
them and fails if they differ. Hand-rolled rather than library-produced,
since fixtures for a parser must contain constructs a library refuses to
emit.

Step 6.2, corpus tests (pdf-document/tests/corpus.rs, 27 tests). Text,
vectors, Flate, multipage, CID fonts, every form field type, inherited field
keys, link actions, hidden annotations, XObjects, inline images with
embedded EI bytes, rotation, crop boxes, nested CTMs and content arrays.

Step 6.3, robustness (pdf-document/tests/robustness.rs, 3 tests) plus five
cargo-fuzz targets. cargo-fuzz needs nightly and libFuzzer so it cannot gate
a stable CI run; the harness covers the same ground deterministically by
mutating the real corpus with a fixed-seed PRNG, so a failure is reproducible
from the seed rather than only from a saved artefact. The fuzz targets remain
the deeper coverage-guided search and run on a schedule.

Three crashes on untrusted input, all found by this work and all previously
reachable from a malformed file:

- collect_pages_ref recursed forever on a /Kids cycle. Stack overflow aborts
  the process; it cannot be caught. Now tracks visited nodes and bounds depth.
- PdfDocument::resolve and the COS lexer recursed once per nesting level, so
  a file of 5000 open brackets overflowed the stack. Both are now bounded.
- decode_85_group multiplied an accumulator that a malformed group can
  overflow, and subtracted below zero on a digit outside the valid range.
  Both panic in a debug build. Now saturating.

Step 6.4, CI (.forgejo/workflows/pdf.yml). An engine job that runs the
corpus and robustness suites under rustfmt and clippy -D warnings; a separate
makepad-integration job so a missing system library is not reported as a PDF
regression; and a scheduled fuzz job. The engine job also enforces the two
architectural rules mechanically rather than in prose: no Makepad dependency
or import in the engine crates, and no process or URL launching anywhere in
them.

Also fixes .gitignore: the blanket *.pdf rule silently excluded all 27
fixtures, which would have left CI unable to run them on a fresh clone.

Validation:
  TEST_TARGET=pdf ./tools/test-rust-clean.sh      (233 tests)
  TEST_TARGET=pdf-ui ./tools/test-rust-clean.sh   (268 tests)
Both rustfmt and clippy -D warnings clean; all five fuzz targets compile.
2026-07-27 17:08:23 +00:00
9861f5e896 feat(valhalla): implement tranche 1 complex turn restrictions, access restrictions, and time domains
Some checks failed
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
2026-07-27 16:49:47 +00:00
5ef0b3a839 feat(valhalla): implement phase 6 OSM PBF parser, contraction hierarchy shortcuts, and golden differential parity suite
Some checks failed
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
2026-07-27 16:27:32 +00:00
66c7590d66 feat(pdf): start Phases 4 and 5, and make pdf-makepad compile
Some checks failed
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
Phases 4 and 5 of REVIEWS/DART_PDF_VS_MAKEPAD_PDF_GAP_ANALYSIS.md.

pdf-makepad had never compiled. It was missing eight PdfDevice methods, had
a non-exhaustive RenderCommand match, called a function through the wrong
path and held a borrow conflict. Everything previously claimed about the
Makepad rendering path was therefore unverified. It now builds and is tested
under a new pdf-ui target; the makepad build needs system GUI libraries, so
that target checks for them with pkg-config and names the missing packages
rather than failing in the linker.

Phase 4 (new pdf-makepad/src/interaction.rs):
- Viewport maps between PDF space (y up) and screen space (y down) in one
  place, so hit testing and rendering cannot disagree. Inverted /Rect
  corners are normalised.
- Click routing follows the review order: form fields first, then annotation
  hit testing. A field overlapping a link takes the click.
- Clicking a link emits PdfAction::OpenUri to the host. The viewer never
  opens a URL itself (rule 5).
- Text editing is buffered: typing changes a working copy and only Enter,
  Tab or blur commits it, so Escape abandons an edit with the document
  untouched. Caret arithmetic is in characters, not bytes, so a non-ASCII
  value cannot panic.
- Checkboxes toggle on click using the state the widget declares.
- Hover reporting for cursor feedback; read-only fields are not targets.
- render_fields() returns placement data so a focused field shows its
  uncommitted buffer while drawing stays trivial.

Phase 5:
- New pdf-graphics/src/cid.rs: composite font support. Codespace ranges give
  variable-width code decoding (the previous CMap was u8 to char, so every
  two-byte CID font decoded as garbage), plus cidchar/cidrange, ToUnicode
  bfchar/bfrange including array destinations and multi-character values
  such as ligatures, /W and /DW CID widths, and Identity-H/V. An unknown
  predefined CMap returns None instead of silently substituting Identity;
  unmapped codes decode to U+FFFD instead of vanishing. Width ranges are
  bounded so a malformed /W cannot exhaust memory.
- New pdf-graphics/src/text.rs: the PageText extraction API. Segments carry
  origin, advance and font size; find() returns matches with rectangles;
  selection spans runs and works in either drag direction. Runs sharing a
  baseline stay on one line even with mixed font sizes.
- renderer.rs: the two unexplained `fs * 0.75` constants are replaced by a
  named DEFAULT_EM_TO_CAP_RATIO used only as a fallback, with the real
  ascent preferred when the descriptor supplies one. Ts (text rise) was
  stored but never applied, so superscripts drew on the baseline.

Also fixes clippy across pdf-makepad, which had never been linted.

Validation:
  TEST_TARGET=pdf ./tools/test-rust-clean.sh      (167 tests)
  TEST_TARGET=pdf-ui ./tools/test-rust-clean.sh   (191 tests)
Both rustfmt and clippy -D warnings clean.
2026-07-27 16:21:37 +00:00
7c11ffd73f feat(valhalla): implement phase 5 valhalla-builder compiler, performance benchmarks, and root facade crate
Some checks failed
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
2026-07-27 16:20:55 +00:00
3712b57745 test(makepad): add native library preflight and cleanup boundary
Some checks failed
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
2026-07-27 16:18:10 +00:00
a6cc1a483b test(spreadsheet): add isolated UI compile target
Some checks failed
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
2026-07-27 16:13:25 +00:00
ab64708f57 feat(valhalla): implement phase 4 makepad ui integration and relocate valhalla suite under crates/apps/valhalla
Some checks failed
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
2026-07-27 16:09:08 +00:00
843dd1d638 feat(valhalla): implement phase 3 search, map matching, narrative directions, and service actor
Some checks failed
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
2026-07-27 16:04:39 +00:00
178da491a0 feat(valhalla): implement phase 2 valhalla-cost and valhalla-path pathfinding engine
Some checks failed
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
2026-07-27 15:58:41 +00:00
fbadab88a6 feat(valhalla): implement phase 1 valhalla-core crate with midgard geometry and baldr graphtile types
Some checks failed
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
2026-07-27 15:55:25 +00:00
af4ef6f170 fix(pdf): restore a compiling, warning-free PDF baseline
Some checks failed
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
Phase 0 of REVIEWS/DART_PDF_VS_MAKEPAD_PDF_GAP_ANALYSIS.md requires a clean
baseline before any feature work. The four pdf crates did not compile at all,
so every test claim about them was unverified.

Compile fixes:
- decode_lzw/decode_run_length returned Vec<u8> where callers expected
  PdfResult, so decode_stream_with_params did not type-check.
- interpret_ops called a current_state_mut() method that PdfDevice does not
  have; colour-space tracking now goes through explicit device hooks.
- image.rs used miniz_oxide without depending on it; PNG inflate now reuses
  the COS crate through a new pdf_cos::filter::inflate_zlib.

Correctness fixes found while making the code build:
- LZW and RunLength silently truncated malformed input and indexed unchecked;
  both now return typed errors (rule 6: no silent degradation).
- Tw/Tc/Tz were parsed and thrown away, and the " operator dropped its word
  and character spacing, so every advance after them drifted.
- TJ attached each kern to the preceding string instead of the following one
  and discarded a trailing kern entirely.
- GlyphWidths::width() fell back to default_width for out-of-range codes;
  PDF 32000-1 9.6.2.1 requires /MissingWidth.
- Text advances silently substituted a guessed font_size * 0.6 when no width
  table was present; ShowTextWithMetrics now carries advance_is_measured so
  callers can distinguish a measurement from an unknown.

Tests: two tests had never compiled and were wrong once they ran (WinAnsi
0x99 is U+2122 not U+2019; q/cm/l/Q records four commands not three). The
document test asserted only that the writer emits a %PDF header; replaced
with real page-tree, out-of-range and malformed-input coverage.

Adds a pdf target to tools/test-rust-clean.sh that tests the three
UI-independent crates bottom-up under rustfmt and clippy -D warnings.

Validation: TEST_TARGET=pdf ./tools/test-rust-clean.sh
72 tests pass; rustfmt and clippy -D warnings clean.
2026-07-27 15:33:15 +00:00
01bc055d1e feat(pay): complete the partially-done review phases
Some checks failed
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
No new phase was started. This finishes every item tranches 1-2 left
partial, so Phases 1, 3, 7 and 8 are complete for the two pure crates or
explicitly blocked on crates that cannot be built here.

Phase 1 (build governance):
- Check in Cargo.lock for both payment crates and build with --locked.
  .gitignore excluded them, which would have made item 1.1 a false claim.
- tools/test-rust-clean.sh now reads the channel from rust-toolchain.toml
  instead of a hardcoded default that had already drifted, and gates on
  fmt, clippy -D warnings, the sqlcipher feature and the benchmarks.
- CI enforces lockfile presence/freshness and a Makepad-boundary check that
  inspects manifests and use/extern lines rather than prose (1.4).

Building on the declared 1.97.1 toolchain surfaced five lints 1.85 missed;
all are fixed. The two Default impls are annotated rather than derived
because each encodes a security or state-machine decision.

Phase 3 (secure repository):
- 3.1 encryption at rest: new encryption.rs and an opt-in sqlcipher feature.
  PRAGMA key is applied first and verified by a forced read, so a wrong key
  fails as KeyRejected rather than as corruption. DatabaseKey redacts its
  Debug and zeroes on drop. No key is ever derived or persisted here, and
  there is no unencrypted fallback. A test asserts the recipient MSISDN is
  absent from the raw database bytes.
- 3.5: preferences.rs replaces the ANDROID_DATA marker file whose existence
  was the value; every field fails safe.
- 3.6: redact.rs. PaymentIntent's derived Debug leaked a customer MSISDN
  into any log line; it now masks phone, name and ids, with a regression
  test. StorageError no longer prints a full intent id.

Phase 7:
- 7.7 benchmarks over money, validation, fees, the intent lifecycle and
  evidence handling, using the stable harness so they run on the pinned
  toolchain. BASELINE.md records measured output.
- 7.1/7.2/7.3 verified already satisfied; the review text is stale.

Phase 8:
- 8.1 simulator.rs with a scripted gateway and biometric, no clock or I/O.
- 8.2 property tests over every permutation of a representative event set:
  no ordering dispatches twice, untrusted events never settle a payment,
  ambiguity never becomes failure, Confirmed is terminal, duplicate
  confirmations are idempotent, and replayed SMS cannot fake a conflict.

Validated on rustc 1.97.1 outside the incomplete workspace graph:
domain 66 tests, storage 20 tests, storage+sqlcipher 25 tests, fmt clean,
clippy -D warnings clean on both crates and both feature sets, benches run.
49 manifests parse; git diff --check clean.

Still unclaimed and blocked on uncompilable crates: UI wiring, Keystore key
provisioning, Phase 4 draw_walk I/O, Phase 5 adapters and legal review, the
Java PIN scrub, and B1/B4/B6 in nigig-core.
2026-07-27 15:07:28 +00:00
fe26cbe29a test(spreadsheet): harden cell reference coverage
Some checks failed
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
2026-07-27 15:02:50 +00:00
2c71f5e166 test(spreadsheet): add isolated engine test target
Some checks failed
Payment domain and storage / isolated-payment-tests (push) Has been cancelled
2026-07-27 15:01:15 +00:00
97798bd6c1 build: pin rust toolchain for isolated payment tests 2026-07-26 19:21:19 +00:00
f6750c8259 feat(pay): add domain coordinator and sqlite storage foundation 2026-07-26 18:42:02 +00:00