Commit graph

669 commits

Author SHA1 Message Date
97f03fd2bd docs(nigig-site): record SITE-03 publication
Some checks failed
nigig-site / Media limits (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Real server interoperability (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Security and supply-chain baseline (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
nigig-site / Owned paths and honest test contracts (push) Has been cancelled
nigig-site / Cargo check-all-targets (push) Has been cancelled
nigig-site / Cargo clippy-site-owned (push) Has been cancelled
nigig-site / Cargo contained-media-export-fixtures (push) Has been cancelled
nigig-site / Cargo containment-storage-crypto (push) Has been cancelled
nigig-site / Cargo integration-non-live (push) Has been cancelled
nigig-site / Cargo production-dependency-containment (push) Has been cancelled
nigig-site / Cargo site02-crypto (push) Has been cancelled
nigig-site / Cargo site02-repository (push) Has been cancelled
nigig-site / Cargo site02-store (push) Has been cancelled
nigig-site / Cargo unit (push) Has been cancelled
nigig-site / SITE-02 native provider/filesystem (macos-latest) (push) Has been cancelled
nigig-site / SITE-02 native provider/filesystem (ubuntu-latest) (push) Has been cancelled
nigig-site / SITE-02 native provider/filesystem (windows-latest) (push) Has been cancelled
nigig-site / SITE-02 desktop runtime and normal shutdown (push) Has been cancelled
nigig-site / SITE-02 migration, recovery, and fault corpus (push) Has been cancelled
nigig-site / Release capability gate (push) Has been cancelled
2026-09-26 03:18:57 +03:00
834755205b feat(site-03): site-scoped versioned aggregates and explicit context
Some checks failed
nigig-site / Owned paths and honest test contracts (push) Has been cancelled
nigig-site / Cargo check-all-targets (push) Has been cancelled
nigig-site / Cargo clippy-site-owned (push) Has been cancelled
nigig-site / Cargo contained-media-export-fixtures (push) Has been cancelled
nigig-site / Cargo containment-storage-crypto (push) Has been cancelled
nigig-site / Cargo integration-non-live (push) Has been cancelled
nigig-site / Cargo production-dependency-containment (push) Has been cancelled
nigig-site / Cargo site02-crypto (push) Has been cancelled
nigig-site / Cargo site02-repository (push) Has been cancelled
nigig-site / Cargo site02-store (push) Has been cancelled
nigig-site / Cargo unit (push) Has been cancelled
nigig-site / SITE-02 native provider/filesystem (macos-latest) (push) Has been cancelled
nigig-site / SITE-02 native provider/filesystem (ubuntu-latest) (push) Has been cancelled
nigig-site / SITE-02 native provider/filesystem (windows-latest) (push) Has been cancelled
nigig-site / SITE-02 desktop runtime and normal shutdown (push) Has been cancelled
nigig-site / SITE-02 migration, recovery, and fault corpus (push) Has been cancelled
nigig-site / Media limits (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Real server interoperability (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Security and supply-chain baseline (push) Has been cancelled
nigig-site / Release capability gate (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
- New opaque id newtypes (ids.rs) and SiteContext with no-fallback
  selection, pagination and revision CAS (site_context.rs).
- New aggregates.rs: per-site versioned split (16 MiB cap), envelope
  site binding, shared supplier quarantine, device-local preferences
  excluded from replication, per-aggregate revision ledger with CAS.
- store.rs: mutate_scoped and all site queries take &SiteContext;
  scoped_context() binds selection at the durable revision; stale
  base revisions fail compare-and-swap; ledger bumps only mutated
  scopes. Queries without context no longer compile.
- Screens and scheduler converted; multi-site compilation takes an
  explicit site list. No selected_or_first fallback remains.
- Migration: legacy whole store splits by site_id with quarantine
  report; original bytes untouched.

Verified: check --all-targets, lib 83 green (19 new SITE-03
tests), integration jobs, clippy -D warnings, fmt --check.
2026-09-26 03:17:42 +03:00
9b07b8f7d5 docs(site): SITE-14 scanner-owned OCR design plus SITE-20-32 product scope
Some checks failed
nigig-site / Owned paths and honest test contracts (push) Has been cancelled
nigig-site / Cargo check-all-targets (push) Has been cancelled
nigig-site / Cargo clippy-site-owned (push) Has been cancelled
nigig-site / Cargo contained-media-export-fixtures (push) Has been cancelled
nigig-site / Cargo containment-storage-crypto (push) Has been cancelled
nigig-site / Cargo integration-non-live (push) Has been cancelled
nigig-site / Cargo production-dependency-containment (push) Has been cancelled
nigig-site / Cargo site02-crypto (push) Has been cancelled
nigig-site / Cargo site02-repository (push) Has been cancelled
nigig-site / Cargo site02-store (push) Has been cancelled
nigig-site / Cargo unit (push) Has been cancelled
nigig-site / SITE-02 native provider/filesystem (macos-latest) (push) Has been cancelled
nigig-site / SITE-02 native provider/filesystem (ubuntu-latest) (push) Has been cancelled
nigig-site / SITE-02 native provider/filesystem (windows-latest) (push) Has been cancelled
nigig-site / SITE-02 desktop runtime and normal shutdown (push) Has been cancelled
nigig-site / SITE-02 migration, recovery, and fault corpus (push) Has been cancelled
nigig-site / Media limits (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Real server interoperability (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Security and supply-chain baseline (push) Has been cancelled
nigig-site / Release capability gate (push) Has been cancelled
repo hygiene / hygiene (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
- SITE-14 revised: engine owned by nigig_doc_scanner/ocr, site
  consumes buffer API only, no pdf dependency; nigig-ocr app noted
  as parallel OS-provider effort with Linux-fallback delegation.
- New feature tranches SITE-20-32 with R1-R5 roadmap, FR
  traceability, product budgets and gates, out-of-scope v1 and open
  decisions from construction-site-app-scope.md and
  construction-site-app-scope2.md.
2026-09-25 22:41:42 +03:00
f535296b43 feat(scanner-ocr): on-device recognition behind ocr feature; gate pdf seam
nigig_doc_scanner splits the app shell (Makepad UI, nigig-core/uikit,
device location) from a new ocr feature: pure-Rust TemplateOcr
(Otsu plus 8-connected components plus embedded 5x7 templates for
0-9A-Z, confidence floor 0.80 plus runner-up margin, checked
budgets) with field suggestions and a deterministic fixture renderer
shared with downstream crates. Downstream device crates enable
nigig_doc_scanner/ocr with default-features=false (dep tree proven
free of UI/location crates). Binary requires app.

nigig-pdf-document gates its engine-free ocr seam behind an ocr
cargo feature (default on); recognition must not pull the
document/signing stack.

Verified: scanner ocr-only check plus 11 lib tests green;
pdf-document check green with default and --no-default-features;
pdf ocr tests 5/5. Pre-existing xmp.rs unused_mut warning untouched.
2026-09-25 22:41:38 +03:00
b3a9005795 feat(pdf): image ink colorants + downsample/pixels + shading/interpreter ports
Some checks failed
nigig-site / SITE-02 native provider/filesystem (macos-latest) (push) Successful in 41m47s
nigig-site / Owned paths and honest test contracts (push) Has been cancelled
nigig-site / Cargo check-all-targets (push) Has been cancelled
nigig-site / Cargo clippy-site-owned (push) Has been cancelled
nigig-site / Cargo contained-media-export-fixtures (push) Has been cancelled
nigig-site / Cargo containment-storage-crypto (push) Has been cancelled
nigig-site / Cargo integration-non-live (push) Has been cancelled
nigig-site / Cargo production-dependency-containment (push) Has been cancelled
nigig-site / Cargo site02-crypto (push) Has been cancelled
nigig-site / Cargo site02-repository (push) Has been cancelled
nigig-site / Cargo site02-store (push) Has been cancelled
nigig-site / Cargo unit (push) Has been cancelled
nigig-site / SITE-02 native provider/filesystem (ubuntu-latest) (push) Has been cancelled
nigig-site / SITE-02 native provider/filesystem (windows-latest) (push) Has been cancelled
nigig-site / SITE-02 desktop runtime and normal shutdown (push) Has been cancelled
nigig-site / SITE-02 migration, recovery, and fault corpus (push) Has been cancelled
nigig-site / Media limits (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Real server interoperability (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Security and supply-chain baseline (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
repo hygiene / hygiene (push) Has been cancelled
nigig-site / Release capability gate (push) Has been cancelled
2026-09-14 09:46:52 +03:00
Arena Agent
75ec2f9f20 fix(nigig-site): harden macOS native evidence
Some checks failed
nigig-site / Owned paths and honest test contracts (push) Has been cancelled
nigig-site / Cargo check-all-targets (push) Has been cancelled
nigig-site / Cargo clippy-site-owned (push) Has been cancelled
nigig-site / Cargo contained-media-export-fixtures (push) Has been cancelled
nigig-site / Cargo containment-storage-crypto (push) Has been cancelled
nigig-site / Cargo integration-non-live (push) Has been cancelled
nigig-site / Cargo production-dependency-containment (push) Has been cancelled
nigig-site / Cargo site02-crypto (push) Has been cancelled
nigig-site / Cargo site02-repository (push) Has been cancelled
nigig-site / Cargo site02-store (push) Has been cancelled
nigig-site / Cargo unit (push) Has been cancelled
nigig-site / SITE-02 native provider/filesystem (ubuntu-latest) (push) Has been cancelled
nigig-site / SITE-02 native provider/filesystem (windows-latest) (push) Has been cancelled
nigig-site / SITE-02 desktop runtime and normal shutdown (push) Has been cancelled
nigig-site / SITE-02 migration, recovery, and fault corpus (push) Has been cancelled
nigig-site / Media limits (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Real server interoperability (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Security and supply-chain baseline (push) Has been cancelled
nigig-site / Release capability gate (push) Has been cancelled
nigig-site / SITE-02 native provider/filesystem (macos-latest) (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
2026-09-14 06:31:57 +00:00
Arena Agent
41259b096a ci(nigig-site): budget clean native builds honestly
Some checks failed
nigig-site / SITE-02 native provider/filesystem (macos-latest) (push) Failing after 2h0m16s
nigig-site / Owned paths and honest test contracts (push) Has been cancelled
nigig-site / Cargo check-all-targets (push) Has been cancelled
nigig-site / Cargo clippy-site-owned (push) Has been cancelled
nigig-site / Cargo contained-media-export-fixtures (push) Has been cancelled
nigig-site / Cargo containment-storage-crypto (push) Has been cancelled
nigig-site / Cargo integration-non-live (push) Has been cancelled
nigig-site / Cargo production-dependency-containment (push) Has been cancelled
nigig-site / Cargo site02-crypto (push) Has been cancelled
nigig-site / Cargo site02-repository (push) Has been cancelled
nigig-site / Cargo site02-store (push) Has been cancelled
nigig-site / Cargo unit (push) Has been cancelled
nigig-site / SITE-02 native provider/filesystem (ubuntu-latest) (push) Has been cancelled
nigig-site / SITE-02 native provider/filesystem (windows-latest) (push) Has been cancelled
nigig-site / SITE-02 desktop runtime and normal shutdown (push) Has been cancelled
nigig-site / SITE-02 migration, recovery, and fault corpus (push) Has been cancelled
nigig-site / Media limits (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Real server interoperability (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Security and supply-chain baseline (push) Has been cancelled
nigig-site / Release capability gate (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
2026-09-13 16:26:31 +00:00
Arena Agent
3c9dc7943a classify Site schema versions before decoding
Some checks failed
nigig-site / SITE-02 migration, recovery, and fault corpus (push) Has been cancelled
nigig-site / Media limits (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Real server interoperability (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Security and supply-chain baseline (push) Has been cancelled
nigig-site / Release capability gate (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
email / gates (push) Has been cancelled
nigig-map / test (push) Has been cancelled
sms / gates (push) Has been cancelled
spreadsheet / engine-coverage (push) Has been cancelled
traffic / gates (push) Has been cancelled
traffic / nigig-traffic (push) Has been cancelled
traffic / supply-chain (push) Has been cancelled
doc-engine / engine (push) Has been cancelled
doc-engine / coverage (push) Has been cancelled
doc-engine / consumer (push) Has been cancelled
email / email-domain (push) Has been cancelled
email / nigig-email (push) Has been cancelled
email / supply-chain (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
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
sms / robius-sms (push) Has been cancelled
sms / supply-chain (push) Has been cancelled
spreadsheet / ui-controller-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
sms / android (push) Has been cancelled
sms / nigig-sms (push) Has been cancelled
2026-09-13 07:22:38 +00:00
Arena Agent
bbce8fb015 harden SITE-02 repository and native vault contracts 2026-09-13 06:51:39 +00:00
Arena Agent
92f1508325 site: verify native vault and production dependency trust 2026-09-12 23:03:56 +00:00
Arena Agent
c568a99948 site: exercise abrupt SITE-02 publication exits 2026-09-12 22:21:22 +00:00
Arena Agent
8c786ae163 site: define blocked SITE-02 key lifecycle review 2026-09-12 22:18:22 +00:00
Arena Agent
6d6f887ba6 site: harden SITE-02 process and scope boundaries 2026-09-12 22:11:59 +00:00
Arena Agent
a7a057f44a site: gate SITE-02 runtime and security review 2026-09-12 21:54:30 +00:00
Arena Agent
aa10b06d9b site: prove locked legacy migration contracts 2026-09-12 21:47:35 +00:00
Arena Agent
8dbfae8f72 site: add SITE-02 encrypted repository candidate 2026-09-12 21:44:00 +00:00
Arena Agent
1cb6ad289b docs(nigig-site): record SITE-00 and SITE-01 publication
Some checks failed
nigig-site / Owned paths and honest test contracts (push) Has been cancelled
nigig-site / Cargo check-all-targets (push) Has been cancelled
nigig-site / Cargo clippy-site-owned (push) Has been cancelled
nigig-site / Cargo contained-media-export-fixtures (push) Has been cancelled
nigig-site / Cargo containment-storage-crypto (push) Has been cancelled
nigig-site / Cargo integration-non-live (push) Has been cancelled
nigig-site / Cargo production-dependency-containment (push) Has been cancelled
nigig-site / Cargo unit (push) Has been cancelled
nigig-site / Runtime UI (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Migration and recovery (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Media limits (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Real server interoperability (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Security and supply-chain baseline (push) Has been cancelled
nigig-site / Release capability gate (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
2026-09-12 15:50:05 +00:00
Arena Agent
5d2d890f70 feat(nigig-site): enforce SITE-01 fail-closed containment
Some checks failed
nigig-site / Migration and recovery (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Media limits (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Real server interoperability (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Security and supply-chain baseline (push) Has been cancelled
nigig-site / Release capability gate (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
doc-engine / engine (push) Has been cancelled
doc-engine / coverage (push) Has been cancelled
doc-engine / consumer (push) Has been cancelled
email / gates (push) Has been cancelled
email / email-domain (push) Has been cancelled
email / nigig-email (push) Has been cancelled
email / supply-chain (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
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
nigig-map / test (push) Has been cancelled
sms / gates (push) Has been cancelled
sms / robius-sms (push) Has been cancelled
sms / android (push) Has been cancelled
sms / nigig-sms (push) Has been cancelled
sms / supply-chain (push) Has been cancelled
spreadsheet / engine-coverage (push) Has been cancelled
spreadsheet / ui-controller-coverage (push) Has been cancelled
traffic / gates (push) Has been cancelled
traffic / nigig-traffic (push) Has been cancelled
traffic / supply-chain (push) Has been cancelled
Contain production capabilities, remove the production sync surface, and keep legacy media/export/transport implementations test-only.

Require authenticated existing-key storage with preservation-first recovery and sticky write disablement, backed by deterministic fault and concurrency tests plus dependency and workflow contracts.
2026-09-12 15:46:30 +00:00
Arena Agent
f49d8b16ac ci(nigig-site): establish truthful SITE-00 gates
Some checks failed
nigig-site / Owned paths and honest test contracts (push) Has been cancelled
nigig-site / Cargo check-all-targets (push) Has been cancelled
nigig-site / Cargo clippy-site-owned (push) Has been cancelled
nigig-site / Cargo integration-non-live (push) Has been cancelled
nigig-site / Cargo media-export-baseline (push) Has been cancelled
nigig-site / Cargo storage-crypto-baseline (push) Has been cancelled
nigig-site / Cargo unit (push) Has been cancelled
nigig-site / Runtime UI (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Migration and recovery (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Media limits (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Real server interoperability (explicitly skipped until enabled) (push) Has been cancelled
nigig-site / Security and supply-chain baseline (push) Has been cancelled
nigig-site / Release capability gate (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
2026-09-12 09:08:22 +00:00
Arena Agent
672fdd54b7 style(nigig-site): establish SITE-00 formatting baseline
Some checks failed
repo hygiene / hygiene (push) Has been cancelled
2026-09-12 09:04:00 +00:00
Arena Agent
bae671f357 docs(nigig-traffic): add correctness remediation execution plan
Some checks failed
repo hygiene / hygiene (push) Has been cancelled
traffic / gates (push) Has been cancelled
traffic / nigig-traffic (push) Has been cancelled
traffic / supply-chain (push) Has been cancelled
2026-09-12 07:59:51 +00:00
Arena Agent
16a98334f1 docs(nigig-site): add security remediation execution plan
Some checks failed
repo hygiene / hygiene (push) Has been cancelled
2026-09-12 07:59:51 +00:00
Arena Agent
5297c94180 docs(nigig-build): add audited remediation execution plan
Some checks failed
repo hygiene / hygiene (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
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
2026-09-12 07:59:51 +00:00
Arena Agent
4665973b57 docs(cad-ui): add audited remediation execution plan
Some checks failed
repo hygiene / hygiene (push) Has been cancelled
2026-09-12 07:59:51 +00:00
Arena Agent
3666c6ce3a docs(cad-core): add audited remediation execution plan
Some checks failed
repo hygiene / hygiene (push) Has been cancelled
2026-09-12 07:59:51 +00:00
e899a271c6 feat(pdf): shading port test (12 passed) + function updates
Some checks failed
repo hygiene / hygiene (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-09-12 09:22:48 +03:00
cea969cce5 feat(pdf): function module updates
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
2026-09-12 09:14:08 +03:00
c66a8ec9db docs+test(site,pdf): assessment update + font_info port cases
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
Verified: font_info_port 22 passed.
2026-09-12 08:55:20 +03:00
5614121eae feat(site+pdf): report editor video + font ports
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
- nigig-site: video module, report editor WYSIWYG updates.
- pdf-graphics: colorant_raster, font_text, unicode_names modules +
  colorant raster port test; font + font_info test updates.
Verified: nigig-site + pdf-graphics check clean; pdf-graphics tests
all pass (20 suites, 0 failures).
2026-09-12 08:45:35 +03:00
2142e1834b fix(nigig-site): report editor WYSIWYG wiring for new makepad API
Some checks failed
repo hygiene / hygiene (push) Has been cancelled
- Use WidgetRef::borrow_mut/borrow directly for the DocEditor host
  (new Widget derive: borrow has no generics on refs, as_* only on
  WidgetRefExt; WidgetExt blanket impl covers View lookups).
- Semicolon fix for RefMut temporary lifetime in set_rich_mode.
2026-09-12 08:22:43 +03:00
a620609ff9 feat(cad-ui): sun position controls
Some checks failed
repo hygiene / hygiene (push) Has been cancelled
2026-09-12 07:21:51 +03:00
ac8f8aa002 chore: sync full working tree to gitdab
Some checks failed
nigig-build (CAD) / cad-module (push) Has been cancelled
nigig-build (CAD) / full-crate-check (push) Has been cancelled
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
traffic / gates (push) Has been cancelled
traffic / nigig-traffic (push) Has been cancelled
traffic / supply-chain (push) Has been cancelled
doc-engine / engine (push) Has been cancelled
doc-engine / coverage (push) Has been cancelled
doc-engine / consumer (push) Has been cancelled
email / gates (push) Has been cancelled
email / email-domain (push) Has been cancelled
email / nigig-email (push) Has been cancelled
email / supply-chain (push) Has been cancelled
nigig-map / test (push) Has been cancelled
sms / gates (push) Has been cancelled
sms / robius-sms (push) Has been cancelled
sms / android (push) Has been cancelled
sms / nigig-sms (push) Has been cancelled
sms / supply-chain (push) Has been cancelled
spreadsheet / engine-coverage (push) Has been cancelled
spreadsheet / ui-controller-coverage (push) Has been cancelled
p2p-intel / engine (push) Has been cancelled
p2p-intel / notifications (push) Has been cancelled
p2p-intel / coverage (push) Has been cancelled
p2p-intel / makepad-app (push) Has been cancelled
p2p-intel / exchange-tab (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
Whole-tree sync: cad-core/cad-ui split sources, nigig-build
construction_frame migration, pdf port progress, mpesa/pay/uikit/doc
updates, workspace members/profiles/lock, CI workflows and reviews.
See individual file history for details.
2026-09-12 07:15:24 +03:00
338b8c818f fix(android): enable cad-ui on mobile + new-API fixes
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
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
spreadsheet / engine-coverage (push) Has been cancelled
spreadsheet / ui-controller-coverage (push) Has been cancelled
- nigig-build: cad-ui + construction_frame back on unconditionally.
  The host-only gate is dropped: cad-ui now compiles for aarch64, and
  pageflipnav mobile needs ConstructionScreen / BuildProjectsPage
  (CAD/Docs/Spreadsheet buttons) — gating produced the white screen.
- cad-ui: ScriptVmHost for standalone eval (no more vm.std / () host),
  std::thread workers (Cx::spawn_thread removed upstream).
- viewport: same worker fix + section_state helper for the CPU cull path.
- script_bindings: new script/geometry binding module.
- spreadsheet grid + invoice Walk literals: ..Default::default() for
  new aspect/cell/deferred fields; explicit style::CellAlign import
  (makepad added its own CellAlign).
Verified: pageflipnav aarch64 release links with 0 errors; APK built,
installed (54M) and running with home screen drawing.
2026-09-12 00:26:43 +03:00
5ae5d5a84c fix(android): gate cad-ui host-only + port map to new makepad API
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
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
nigig-map / test (push) Has been cancelled
- nigig-build: cad-ui + construction_frame host-only (DO NOT enable
  unconditionally: CadViewport Script derive fails ScriptApply for
  aarch64 and breaks every pageflipnav android build).
- map: vendor TagThreadPool (removed upstream with the task-pool
  scheduler) into thread_pool.rs; Walk literals gain
  ..Default::default() for new aspect/cell/deferred fields.
Verified by pageflipnav aarch64 release rust build (0 errors).
2026-09-11 08:46:05 +03:00
b1045d79d4 feat(pdf): graphics/document port progress + android gates
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
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
repo hygiene / hygiene (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
- pdf-graphics: new cff, truetype, cjk_cmap, disk_cache, document_ai,
  path, reflow, text_diff modules + port tests (all green); syntax/type
  fixes for the aarch64 build (stray brace, &u8 derefs, f2dot14 assign).
- pdf-document: ocr, pdf_a, xmp modules + roundtrip tests; annotation
  editor updates.
- pdf-makepad: handle RenderCommand::SetOverprint (report via
  TransparencyError per ADR 0009, no silent drop); renderer/page_view
  updates for the new recording ops.
- matrix_client: nimanyatta native module (ungated; the aarch64 wrapper
  needs it unconditionally).
- pageflipnav home_screen: project_store sync is host-only until
  cad-ui's Widget Script derive is fixed for aarch64.

Verified: cargo check on all four crates clean at fork 66cc4f15f;
nigig-pdf-graphics tests pass; pageflipnav aarch64 release links.
2026-09-11 05:09:11 +03:00
c901f1d4f1 chore(deps): bump makepad fork rev to b9a083c26 + workspace updates
Some checks failed
doc-engine / engine (push) Has been cancelled
doc-engine / coverage (push) Has been cancelled
doc-engine / consumer (push) Has been cancelled
email / gates (push) Has been cancelled
email / email-domain (push) Has been cancelled
email / nigig-email (push) Has been cancelled
email / supply-chain (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
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
nigig-map / test (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
sms / gates (push) Has been cancelled
sms / robius-sms (push) Has been cancelled
sms / android (push) Has been cancelled
sms / nigig-sms (push) Has been cancelled
sms / supply-chain (push) Has been cancelled
spreadsheet / engine-coverage (push) Has been cancelled
spreadsheet / ui-controller-coverage (push) Has been cancelled
Fork nigig-makepad-test-android now at b9a083c26 (upstream merge +
robot secondary-dex bundling + app_main wrapper fix, on top of the
game-libs/arcade port). All 16 workspace makepad revs follow.

Also takes the in-tree workspace updates: exclude nested
crates/nimanyatta workspace, add crates/apps/nigig-site member, and
PERF-OPS Phase 1 profile tuning (thin LTO + engine opt-level 3).
cad-core/cad-ui split and nigig-traffic members stay WIP.
2026-09-10 16:36:11 +03:00
12dff81b05 fix(build): make cad-ui host-only for Android
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
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
cad-ui's Widget Script derive (CadViewport) needs LiveHook fix for
aarch64; until then, gate it behind cfg(not(target_os="android"))
in nigig-build so pageflipnav's aarch64 wrapper (which pulls
nigig-build) can link without cad-ui. Host builds still include
cad-ui. Unblocks pageflipnav aarch64 release.
2026-09-08 22:28:11 +03:00
075d775e9f fix(robius-ussd): fix Android JNI getPackageName handling for new jni crate
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
JString::from(JObject) + get_string borrowing was incorrect for
aarch64 android target (jni 0.21): JavaStr doesn't impl Display and
temporary JObject dropped while borrowed. Store package_obj in local
and use JString::from(package_obj). Fixes pageflipnav android build
which pulls robius-ussd via pageflipnav -> nigig-build -> cad-ui.
2026-09-07 03:50:53 +03:00
366b80dd16 refactor(pageflipnav): use AndroidManifest.xml.template and dedup robius java
Some checks failed
repo hygiene / hygiene (push) Has been cancelled
- Rename resources/android/AndroidManifest.xml -> AndroidManifest.xml.template
  so the current cargo-makepad (template-based, not --manifest flag) picks
  up the custom manifest with permissions/services (ussd, sms, trigger).
  Old --manifest flag was removed in makepad's android/mod.rs; template
  is now the supported override.

- Remove duplicate java at resources/android/java/robius/{sms,trigger,ussd}
  (7 files). These are now compiled via their owning crates' build.rs
  (robius-sms/src/sys/android/*.java, robius-trigger/src/android/*.java,
  robius-ussd/src/sys/android/*.java) producing secondary dex that
  cargo-makepad bundles. Keeping them in the app caused duplicate sources
  and is not needed; java belongs in the respective crates.
2026-09-07 03:02:06 +03:00
212abe6e8b refactor(cad): port AI subsystem from makepad-ai Agent API to makepad-ai-hub worker-thread ChatProvider model (adopt upstream example/cad), bump makepad fork rev to 7bddebb
Some checks failed
doc-engine / engine (push) Has been cancelled
doc-engine / coverage (push) Has been cancelled
doc-engine / consumer (push) Has been cancelled
email / gates (push) Has been cancelled
email / email-domain (push) Has been cancelled
email / nigig-email (push) Has been cancelled
email / supply-chain (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
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
nigig-map / test (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
sms / gates (push) Has been cancelled
sms / robius-sms (push) Has been cancelled
sms / android (push) Has been cancelled
sms / nigig-sms (push) Has been cancelled
sms / supply-chain (push) Has been cancelled
spreadsheet / engine-coverage (push) Has been cancelled
spreadsheet / ui-controller-coverage (push) Has been cancelled
2026-09-03 08:39:07 +03:00
560116189c fix(cad-build): land CAD workspace on project dashboard, not a blank editor
Some checks failed
repo hygiene / hygiene (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
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
The CAD dashboard's CadDashboard node never realized as a widget, so
tapping 'CAD Workspace' opened to a blank/editor-only sheet. Empirical
device dumps showed the first child after the root realizes reliably
while a sibling placed after the editor AdaptiveView does not, and a
root ':=' widget child alone never realizes here.

- Place dashboard_layer as the FIRST direct child of CadWorkspaceBase,
  wrapping mod.widgets.CadDashboard so it is a reliably-realizable,
  togglable View layer (matching the working doc workspace pattern).
- Wrap the editor AdaptiveView in editor_layer (a plain View) and toggle
  editor_layer/dashboard_layer visibility from apply_dashboard_visibility
  instead of toggling the AdaptiveView variants, which always draw their
  active variant regardless of visible.
- Add use mod.widgets.* to the CadDashboard script_mod (matches the
  CadEditorSheet registration that realizes inside this workspace).
- Add regression test candlands_on_dashboard asserting the dashboard
  title and + New Project button land when opening the workspace.
2026-09-02 09:06:20 +03:00
3a3db4efa6 feat(robius-notification): iOS via UNUserNotificationCenter, and the Apple/Windows logic comes out of the cfg blocks
Some checks failed
repo hygiene / hygiene (push) Has been cancelled
doc-engine / engine (push) Has been cancelled
doc-engine / coverage (push) Has been cancelled
doc-engine / consumer (push) Has been cancelled
email / gates (push) Has been cancelled
email / email-domain (push) Has been cancelled
email / nigig-email (push) Has been cancelled
email / supply-chain (push) Has been cancelled
nigig-map / test (push) Has been cancelled
p2p-intel / engine (push) Has been cancelled
p2p-intel / notifications (push) Has been cancelled
p2p-intel / coverage (push) Has been cancelled
p2p-intel / makepad-app (push) Has been cancelled
p2p-intel / exchange-tab (push) Has been cancelled
sms / gates (push) Has been cancelled
sms / robius-sms (push) Has been cancelled
sms / android (push) Has been cancelled
sms / nigig-sms (push) Has been cancelled
sms / supply-chain (push) Has been cancelled
spreadsheet / engine-coverage (push) Has been cancelled
spreadsheet / ui-controller-coverage (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
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
Two gaps remained on the Apple and Windows side after the last commit, and
they are different in kind.

The first was a missing backend. iOS returned PermanentlyUnavailable with a
note saying it was not implemented. It now uses UNUserNotificationCenter --
the only option there, since every iOS process is bundled, so the
Objective-C exception that rules that API out on macOS cannot occur. The
objc2-user-notifications bindings are real and fetchable, so this
type-checks for aarch64-apple-ios against the actual framework, and the
module was confirmed genuinely reachable by injecting a type error and
watching the target build fail.

Its is_available() returns a constant false, and that is a limit worth
naming rather than burying. The real answer comes from
getNotificationSettingsWithCompletionHandler:, which is asynchronous -- it
hands the settings to a block on an arbitrary queue. A synchronous
is_available() could only produce that by blocking on a completion handler,
which on the main thread is a deadlock rather than a delay. Returning false
errs toward telling the user delivery is unverified; the alternative is
claiming an availability the platform never confirmed, which is the whole
failure this crate was written to remove. A correct answer needs an async
entry point, which is a change to the public API rather than a bug fix, so
it is recorded in the ADR instead of being quietly wrong.

The second gap is subtler and, I think, the more valuable fix. The Apple and
Windows backends contain pure logic -- XML escaping, tag clamping -- that
was sitting inside #[cfg(target_os = "windows")], where cargo test on the
only available machine could never reach it. Those functions had zero tests
and no prospect of any.

They now live in src/payload.rs, which is cfg-free and runs on every target.
Eleven tests cover them, and they cover exactly the rules a compiler cannot:
an unescaped `&` in a merchant name makes the toast XML malformed and
Windows discards the whole notification rather than showing a mangled
character, and the Binance P2P book is full of `&`. A byte-wise truncation
of the 64-character tag limit panics outright on the full-width names that
book also contains -- so the clamp cuts on character boundaries, pinned by a
test that would panic if anyone changed it back.

One test pins something deliberately counter-intuitive: escaping is not
idempotent, and escape_xml("&") is "&". That is correct, and the
test exists so nobody "fixes" double-escaping by teaching the function to
detect already-escaped input, which is precisely how escaping filters grow
holes.

The distinction this commit is really about: the last one made the Apple and
Windows backends *compile*, which catches wrong selectors -- it found
CreateToastNotifier(&HSTRING), which does not exist. It could not catch
wrong behaviour. Extracting the logic is what makes the behaviour testable
on a machine that will never run either platform.

62 tests, up from 51. Clippy clean with -D warnings on all five targets:
linux-gnu, linux-android, apple-darwin, apple-ios, windows-msvc. p2p-intel
unchanged at 225.
2026-09-01 20:10:50 +00:00
3ef182414e feat(robius-notification): real macOS and Windows backends, type-checked against the actual frameworks
Some checks failed
repo hygiene / hygiene (push) Has been cancelled
p2p-intel / engine (push) Has been cancelled
p2p-intel / notifications (push) Has been cancelled
p2p-intel / coverage (push) Has been cancelled
p2p-intel / makepad-app (push) Has been cancelled
p2p-intel / exchange-tab (push) Has been cancelled
The previous commit refused to write these two, on the grounds that code no
compiler has ever seen is not an implementation -- it is plausible-looking
text that would sit in the same crate as tested code and be read as equally
finished. That reasoning holds. The premise behind it did not.

`cargo check` needs the *target's standard library*, not a linker or a
platform SDK. `rustup target add x86_64-pc-windows-msvc aarch64-apple-darwin`
puts the real `windows` and `objc2` crates -- genuine WinRT metadata, genuine
Objective-C class definitions -- in front of the type checker on a Linux
host. So both backends are now written and both compile against the
frameworks they call.

Compile-checking earned its place immediately. The Windows backend was
written against `ToastNotificationManager::CreateToastNotifier(&HSTRING)`,
which does not exist: the AUMID overload is `CreateToastNotifierWithId`.
Nothing short of a compiler holding the real metadata would have caught
that, and it would have shipped looking entirely correct.

Because a cfg-gated module can silently compile to nothing -- leaving a
green check that proves only that the module was skipped -- each backend was
verified to be genuinely reachable by injecting a type error and confirming
the target build failed. Both macOS and Windows were checked this way, then
restored.

Two platform decisions worth recording.

macOS uses NSUserNotification, not UNUserNotificationCenter, and that is a
deliberate downgrade to a deprecated API. `UNUserNotificationCenter.current()`
raises an Objective-C exception when the process has no bundle identifier;
that unwinds through Rust frames and aborts. A plain `cargo run` host has no
bundle, so the modern API would crash the caller instead of reporting
unavailable -- which is worse than deprecated. The nil check on
`defaultUserNotificationCenter` is there for the same reason: msg_send on nil
returns zero rather than crashing, so every later call would silently do
nothing, which is precisely the failure this crate exists to remove.

Windows requires the host to supply an AppUserModelID, because a library
cannot invent one. It comes from an MSIX manifest or a Start Menu shortcut,
and a fabricated id produces a notifier that constructs happily and then
fails at Show. `set_app_user_model_id` is therefore public, a no-op off
Windows so portable hosts call it unconditionally, and `is_available()` is
false with a reason naming exactly what is missing until it is called. Toast
payloads are XML, so text is escaped -- the same bug class as the Telegram
MarkdownV2 escaping p2p-intel needed before it dropped Telegram, and a
merchant nickname containing `&` is not hypothetical.

The support table now has two columns, "compiles" and "executed", because
they are different claims. All four backends compile; only Linux has posted
a notification. iOS remains unavailable by design: it needs UN* with a
bundle and an entitlement, which is an app-packaging concern rather than
something this crate can satisfy.

Off Windows the module defines no entry points at all rather than stubs.
Clippy was right to call them dead: sys/mod.rs dispatches elsewhere, so they
existed only to satisfy a symmetry nothing needs.

CI gains a step that clippies all four cross-targets with -D warnings, so a
cfg-gated backend cannot rot unnoticed -- which is exactly how the
CreateToastNotifier mistake would have survived.

51 tests, clippy clean on five targets, p2p-intel still at 225.
2026-09-01 18:54:57 +00:00
e16d1d1d44 feat(robius-notification): a zero-dependency D-Bus notifier, and p2p-intel's last limit closes on Linux
Some checks failed
p2p-intel / engine (push) Has been cancelled
p2p-intel / notifications (push) Has been cancelled
p2p-intel / coverage (push) Has been cancelled
p2p-intel / makepad-app (push) Has been cancelled
p2p-intel / exchange-tab (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
sms / gates (push) Has been cancelled
sms / robius-sms (push) Has been cancelled
sms / android (push) Has been cancelled
sms / nigig-sms (push) Has been cancelled
sms / supply-chain (push) Has been cancelled
doc-engine / engine (push) Has been cancelled
doc-engine / coverage (push) Has been cancelled
doc-engine / consumer (push) Has been cancelled
spreadsheet / engine-coverage (push) Has been cancelled
spreadsheet / ui-controller-coverage (push) Has been cancelled
email / gates (push) Has been cancelled
email / email-domain (push) Has been cancelled
email / nigig-email (push) Has been cancelled
email / supply-chain (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
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
nigig-map / test (push) Has been cancelled
ADR 0035 left one of p2p-intel's four limits open: no OS notification
backend, so alerts stopped when the window closed. The seam existed with one
implementation that truthfully did nothing. This is the crate that fills it.

Posting a notification on Linux is one D-Bus method call. Three ways to make
it were measured rather than assumed: notify-rust with libdbus is twelve
crates but a C library, which needs pkg-config and breaks the Android and
iOS cross-compile this crate family keeps clean; notify-rust with zbus is
pure Rust and 169 crates including an async executor; writing the wire
format out is about 250 lines and nothing at all. robius-sms deleted polkit
and gio for exactly this reason -- its E9 note records they were the sole
source of two RUSTSEC advisories and an LGPL question for every consumer --
so pulling a 169-crate tree back into the same family for one method call
would reverse that decision for a worse reason.

The cost of hand-rolling is that the protocol has to be exactly right, and a
mistake makes the daemon disconnect with no diagnostic. That cost was paid
in tests: the suite starts a private dbus-daemon per test and talks to it.
This matters more than it sounds. The marshaller and the parser were written
from the same reading of the specification, so them agreeing with each other
proves only that I was consistently wrong or consistently right; only a
third party can say which.

It found three bugs no unit test would have.

The first is the one worth dwelling on. Every error reply parsed as success.
The header-field walk assumed all fields were strings, but REPLY_SERIAL is a
u32, and reading its four bytes as a string length desynchronised the cursor
so ERROR_NAME was never reached. `post` returned Ok against a bus with no
notification service running. That is precisely the bug this crate was
written to eliminate -- a notifier that reports success and delivers nothing
-- reintroduced by accident inside its own parser. I cannot think of a
stronger argument for testing against something you did not write.

Second, is_available() was true on a bare bus, because NameHasOwner
*succeeds* and answers false in its body; checking only for an error
reported a working notifier on a machine with no notification daemon.

Third, replies were not correlated. The bus sends NameAcquired unprompted
right after Hello, so "read the next message" consumed a signal and treated
it as the answer. Replies are now matched on REPLY_SERIAL, and a single read
carrying several messages is walked rather than truncated.

The suite also serialises every test that mutates DBUS_SESSION_BUS_ADDRESS
behind a mutex. The variable is process-wide and cargo runs tests in
parallel threads; three consecutive parallel runs are now green.
--test-threads=1 would have made the failures go away too, and would have
hidden a real hazard from whoever reads the file next.

On the four platforms, honestly. Linux is implemented and tested. Android is
implemented and *compiles* -- cargo check and clippy both pass for
aarch64-linux-android -- but has never run on a device, and the module says
so in its first paragraph. It handles the two things Android drops silently,
missing POST_NOTIFICATIONS on API 33+ and a missing channel on API 26+,
because both are the same accepted-and-discarded failure this crate exists
to remove.

Apple and Windows are deliberately not written. Neither could be compiled
here -- no macOS or Windows toolchain and no way to add one -- and objc2
message sends or WinRT calls that no compiler has ever seen are not an
implementation. They are plausible-looking text that would sit in the same
crate as tested code and be read as equally finished. Both return
PermanentlyUnavailable with a reason naming ADR 0036, and their module docs
record the call sequence so the next person starts from a design rather than
a blank file. The support table says "written" and "verified" in separate
columns for the same reason.

p2p-intel's dashboard now uses SystemNotifications instead of
UnavailableNotifications. The latter stays: on a platform with no backend it
is still the truthful answer, and a test needs something that reliably
cannot deliver. Alerts are tagged per fiat so a market replaces its own
previous notification rather than stacking -- a 30-second poll would
otherwise fill the shade, and a full shade is what makes someone turn
notifications off for the app entirely, which costs more than the feature is
worth. Two new tests pin the invariant that a sink must never report
delivery it did not achieve.

CI gains a notifications job that installs dbus and sets
ROBIUS_NOTIFICATION_REQUIRE_DBUS=1. The bus-backed tests skip when
dbus-daemon is absent so the suite stays green on a bare machine, but a
silent skip in CI would mean the integration tests quietly stopped running
while the build stayed green. I verified the guard fails by hiding
dbus-daemon behind a stub that exits 127.

50 tests in the new crate, 225 in p2p-intel, clippy clean on host and
Android, and the app still starts under Xvfb.
2026-09-01 18:43:07 +00:00
da326142bf fix(pay-ui): stop re-setting ussd/phone-perm toggles on refresh so manual user state is preserved
Some checks failed
repo hygiene / hygiene (push) Has been cancelled
Payment domain, storage, platform and UI / payment-ui-tests (push) Has been cancelled
Payment domain, storage, platform and UI / isolated-payment-tests (push) Has been cancelled
2026-09-01 21:40:49 +03:00
1d8b3a6053 merge(local): reapply local WIP onto merged main -- cad dashboard/explode/script_parts/xray merged with remote Phase-5 LOD, plus doc-ui extraction, spreadsheet xls-import, android ussd, camera and test work
Some checks failed
makepad-table / model (push) Has been cancelled
makepad-table / widget (push) Has been cancelled
makepad-table / hygiene (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, 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
doc-engine / engine (push) Has been cancelled
doc-engine / coverage (push) Has been cancelled
doc-engine / consumer (push) Has been cancelled
email / gates (push) Has been cancelled
email / email-domain (push) Has been cancelled
email / nigig-email (push) Has been cancelled
email / supply-chain (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
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
nigig-map / test (push) Has been cancelled
sms / gates (push) Has been cancelled
sms / robius-sms (push) Has been cancelled
sms / android (push) Has been cancelled
sms / nigig-sms (push) Has been cancelled
sms / supply-chain (push) Has been cancelled
spreadsheet / engine-coverage (push) Has been cancelled
spreadsheet / ui-controller-coverage (push) Has been cancelled
2026-09-01 21:13:52 +03:00
159f3c7fee Merge remote-tracking branch 'origin/main' 2026-09-01 20:31:44 +03:00
8bf62e2644 feat(p2p-intel): the exchange tab becomes spread intelligence, with rails, drift capture, and three of four limits closed
Some checks failed
doc-engine / engine (push) Has been cancelled
doc-engine / coverage (push) Has been cancelled
doc-engine / consumer (push) Has been cancelled
email / gates (push) Has been cancelled
email / email-domain (push) Has been cancelled
email / nigig-email (push) Has been cancelled
email / supply-chain (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
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
nigig-map / test (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
sms / gates (push) Has been cancelled
sms / robius-sms (push) Has been cancelled
sms / android (push) Has been cancelled
sms / nigig-sms (push) Has been cancelled
sms / supply-chain (push) Has been cancelled
spreadsheet / engine-coverage (push) Has been cancelled
spreadsheet / ui-controller-coverage (push) Has been cancelled
p2p-intel / engine (push) Has been cancelled
p2p-intel / coverage (push) Has been cancelled
p2p-intel / makepad-app (push) Has been cancelled
p2p-intel / exchange-tab (push) Has been cancelled
The exchange tab in nigig-mpesa and nigig-pay was a swap mock-up -- Sell/Buy
cards showing hardcoded ETH and AAVE at $38,409.24, wired to nothing -- above
six rate labels, each built from the *first* cached advert for its exchange:

    Binance P2P: USDT BUY @ 129.92 KES  min 1000 max 200000  via BANK

That is a price, not an opportunity. It never compared the two sides of the
book, said nothing about whether the counterparty could be dealt with, and
ignored what it costs to move the money. Against the live KES book it would
have shown a 134.60 advert from a merchant with three completed trades.

Both pages now run the p2p-intel analyzer over the adverts the app already
caches. No new endpoint, no new traffic, api.rs untouched -- the data was
always there, nothing was being asked of it. The two files are
byte-identical and CI now fails if they drift apart, which they already had
once: data.rs differs between the apps by 188 lines of tests one copy has
and the other does not.

**Rails, because a spread alone is a lie.** 29 bps on a 10,000 KES trade is
29 KES of gross margin; M-Pesa Send Money costs 55 KES a leg, 110 round
trip. The trade is deeply negative and the spread says nothing about it.
rail.rs prices every route and ranks by what survives. M-Pesa fees come from
the published Safaricom bands in robius_ussd::mpesa_bands -- real tariff
rows, not estimates, and flat rather than percentage, which is exactly why
the same spread is ruinous at 500 KES and fine at 200,000. Both legs are
charged. An amount outside the tariff reports OutOfRange and an
unconfigured bank reports Unknown; neither reports zero, because zero is a
claim and it is the wrong one. Bank tariffs ship unconfigured for the same
reason: every bank differs and there is no table to default to.

**API drift capture.** These endpoints are internal and undocumented. When
one changes the symptom is an empty panel -- indistinguishable from a quiet
market -- and the response that broke it is gone by the time anyone looks.
Every parse failure is now recorded with the payload excerpt that caused it
and copyable as a plain-text report. Deduplicated, because a 30-second poll
against a changed endpoint fails 120 times an hour and 120 identical rows is
a log nobody reads; the excerpt is excluded from the equality check, since
two responses differing only in advert ids are the same drift. The exported
header states that it carries response excerpts only and never a request,
credential or account number -- the type can only be constructed from a
response body, so that is enforced rather than promised. Cutting the excerpt
is done on character boundaries: Binance really returns names like
BennyBoss and a byte slice would panic mid-character.

The repo's other clipboard code (nigig-build's crdt_widget.rs) answers a
Hit::TextCopy, which is the query-driven path the platform uses for Ctrl+C
on a focused widget. Right for a text editor, wrong for a button exporting a
report the user never selected, so this uses cx.copy_to_clipboard and
confirms in the UI -- a copy button with no feedback is one people press
three times.

On the four limits, the honest scoreboard is two closed, one usefully
sidestepped, one open. ADR 0035 records why, because rounding all four up to
"addressed" would have been the easy write-up and the wrong one.

The poll timer and the host clock are closed outright. cx.start_interval
delivers the tick as an ordinary UI-thread event, so there is no runtime and
nothing to join at shutdown, and the interval reads through
effective_poll_seconds so the fifteen-second floor still applies -- a config
file cannot be used to hammer a rate-limited endpoint, which a test pins by
name. Staleness is now shown, because a price from four minutes ago is not a
price. One ambiguity is recorded rather than hidden: last_scan_ms == 0 is the
"never scanned" sentinel, so a scan whose timestamp genuinely is 0 reads as
never. That only happens when the host clock is broken, which is exactly
when the UI should not claim the data is current.

The headless-backend limit is sidestepped, and the distinction matters
enough to write down. Xvfb is a real X11 server that draws into memory, so
the app gets the display it insists on and tools/test-p2p-app-smoke.sh runs
the real binary end to end. That earned its place immediately: it caught
`Row = <View> { ... }`, which is not valid in this fork's script language
and which cargo build is entirely silent about, because script_mod! is
parsed at *runtime* -- a broken widget tree compiles perfectly and then
renders nothing. The gate greps for [E] in the log for that reason; the
process exits 0. I verified it fails by reintroducing the bad syntax. What
it still cannot do is drive widgets: makepad_test's Selector::id(..).click()
needs the harness to own the event loop, so the six #[ignore]d interaction
tests stay ignored.

OS notifications stay open. There is no robius-notification crate beside
robius-sms and robius-ussd, and Makepad exposes none on any target; building
one means NotificationCompat on Android, UNUserNotification on iOS and a
D-Bus call on Linux. What shipped is the seam plus one implementation named
UnavailableNotifications -- named for what it is, because a DefaultNotifier
that silently discarded every alert would read like a working feature at
every call site. is_delivering() returns false and the UI shows the reason,
so the user is told that alerts stop with the window instead of assuming
they are covered. A no-op reporting success is the exact "declared versus
delivered" failure ADR 0017 exists to prevent.

223 tests, coverage 97.03% with fifteen per-file floors -- seven of them new
and all measured, after I noticed an earlier edit had silently failed to
apply and the new files were being counted in the total but gated by
nothing. CI gains the Xvfb smoke job and an exchange-tab job that builds
both host apps and diffs their pages.
2026-09-01 16:07:43 +00:00
fefde1ecca refactor(p2p-intel): Makepad's HTTP stack, in-app alerts, and micro_serde -- serde and reqwest are gone
Some checks failed
p2p-intel / engine (push) Has been cancelled
p2p-intel / coverage (push) Has been cancelled
p2p-intel / makepad-app (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
Three changes that turn out to be one change: the app now uses the
platform's own facilities instead of carrying its own. Networking moves to
Cx::http_request, alerting moves into the UI, and deserialisation moves to
makepad_micro_serde. The default dependency graph drops from serde +
serde_derive + serde_json + toml + reqwest + rustls + tokio + hyper to
**twenty-five crates total**, none of which is any of those.

Networking follows nigig-mpesa/src/pages/exchange/api.rs: build an
HttpRequest, hand it to Cx::http_request keyed by a LiveId, match the reply
in handle_network_responses. There is no HTTP client, no TLS stack and no
async runtime in this workspace any more. That is not only leanness -- on
Android and iOS the platform stack is the only one that works without
shipping a second TLS implementation, so the `live` feature that gated
reqwest has been deleted rather than made default.

Correlating replies is where the real trap was. A scan of five markets puts
ten requests in flight and the replies come back in whatever order the
network gives them, so the LiveId has to say which market and which side.
RequestKey encodes both plus a generation counter and round-trips through a
u64 with the high bit set, so a LiveId Makepad derived from a name is never
decoded as a scan reply, and a late reply from a previous round is dropped
instead of folded into fresh data. Six tests cover the codec, including the
one that matters most: the two sides of one market must not share an id, or
the second reply overwrites the first and every spread is measured against
itself.

The transport allowlist is lifted from the nigig-mpesa review, which reached
the same conclusion I would have: Makepad exposes no certificate pinning --
its only TLS control is set_ignore_ssl_cert, which weakens verification --
so what is enforceable at this layer is that only HTTPS to p2p.binance.com
can be dialled at all. The tests cover the two ways a naive check leaks: the
lookalike host p2p.binance.com.evil.example, which passes any starts_with
test, and the userinfo smuggle https://p2p.binance.com@evil.example/, which
resolves to evil.example while reading as Binance.

Telegram is gone, as asked, and the app alerts itself: a banner, an unread
badge on the status line, an Alerts tab holding the history, and a chime.
Removing it removes a bot token from the threat model entirely -- a token in
a config file is a bot anyone who reads the file can drive -- and removes a
second network dependency from a tool already gated on one endpoint. One
test now records the *absence* of a bug rather than its fix: Twin_traders00
is a real merchant from the live capture, and its underscore previously had
to be escaped or Telegram rejected the whole message with a 400 and
delivered nothing. Rendering in our own UI deletes that failure mode, and
the test asserts the name appears unescaped.

The trade-off is stated in the README rather than glossed: an in-app alert
only reaches you while the app is running. No OS notification is raised, so
a minimised window is a missed alert.

The chime is synthesised rather than bundled -- a two-note rising blip
generated at the device's sample rate, which is a few dozen lines instead of
an audio asset shipped on three platforms, and which can therefore be
tested. It is, and the tests found the bugs you would expect from writing
audio: a freshly rendered chime starts *finished* so opening the output does
not announce itself at startup, both note edges fade so neither clicks, the
tail pads with silence rather than replaying whatever the buffer last held,
and a nonsense sample rate falls back instead of panicking. Rising rather
than falling because a falling interval reads as a dismissal and this is an
invitation to act.

The micro_serde migration surfaced two behaviours that differ from serde and
both bit before they were understood.

**micro_serde is strict by default.** deserialize_json errors on the first
key it does not model. Binance sends about forty fields per advert and we
model eight, so the strict parser cannot read the response at all -- and for
a config file it means an older build cannot open a file written by a newer
one. Everything uses deserialize_json_lenient, and a test pins that the
strict call *would* have failed, because the two differ by one word and the
strict one looks more correct.

**There is no #[serde(default)].** Optional config entries are modelled as
Option<T> on a Raw* struct and resolved into the real Config by hand. A few
more lines in exchange for two fewer dependency trees. config.toml became
config.json for the same arithmetic: micro_serde has no TOML reader, and
toml depends on serde, so a single config file would have dragged all of
serde back in through the back door.

Also worth recording: DeJsonErr implements Debug but not Display, and Debug
is the variant carrying line and column, so every error path formats it with
{e:?} deliberately rather than by accident.

CI gains a check that fails the build if reqwest, tokio, rustls, hyper,
serde, serde_derive, serde_json or toml reappears in the default graph. I
verified it fails by adding serde back to p2p-core and watching it match
serde_derive, then reverted. A gate that cannot fail is decoration.

136 tests in the default feature set and 36 more with --features ui,
including the RequestKey codec, which cannot be measured by the coverage job
because it lives behind the feature that needs Makepad. Coverage 96.92% with
ten per-file floors, up from eight -- chime.rs at 100% and client.rs at
95.69% are new. The desktop binary was built and linked to prove the app
half is real.
2026-09-01 09:37:20 +00:00
eaeebd3910 feat(p2p-intel): Binance P2P spread intelligence, shaped by what the live book actually contains
Some checks failed
p2p-intel / engine (push) Has been cancelled
p2p-intel / coverage (push) Has been cancelled
p2p-intel / makepad-app (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
doc-engine / engine (push) Has been cancelled
doc-engine / coverage (push) Has been cancelled
doc-engine / consumer (push) Has been cancelled
email / gates (push) Has been cancelled
email / email-domain (push) Has been cancelled
email / nigig-email (push) Has been cancelled
email / supply-chain (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
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
nigig-map / test (push) Has been cancelled
sms / gates (push) Has been cancelled
sms / robius-sms (push) Has been cancelled
sms / android (push) Has been cancelled
sms / nigig-sms (push) Has been cancelled
sms / supply-chain (push) Has been cancelled
spreadsheet / engine-coverage (push) Has been cancelled
spreadsheet / ui-controller-coverage (push) Has been cancelled
A new nested workspace under crates/apps/p2p-intel: six engine crates, a
CLI, and a Makepad dashboard that builds for desktop, Android and iOS. It
reads public P2P adverts, measures the spread that is actually fillable,
alerts when one is worth acting on, and tracks what the float really cost.

It never places an order. Binance publishes no P2P trading API, and
automating an escrow release is how a merchant loses their float to
chargeback fraud. This is the intelligence layer; execution stays manual.

The design came from a live capture rather than a sketch, and the capture
contradicted the sketch three times. All three are now pinned by tests
against checked-in real payloads.

**The best price is routinely the least fillable one.** In the KES book the
top sell advert was 134.60 from a merchant with three completed trades,
implying a 3.6% spread; the next was 130.30. Another advert showed a 0%
completion rate. A best-price scan with no quality floor does not find
opportunities, it finds outliers, and outliers on a P2P book are bait or a
merchant about to run dry. QualityFilter defaults to 95% completion and 50
orders, and analyse() reports every exclusion with its reason rather than
dropping it silently.

The honest consequence is recorded in the integration suite: at those
defaults **not one sell-side advert in the captured KES book qualified**.
There was no fillable arbitrage. A tool that reported the raw best-price
number would have sent its user after a trade that does not exist, so the
test asserts best_sell is None and net_bps is None rather than asserting a
comfortable number.

**tradeType is inverted between request and response.** Asking the endpoint
for tradeType "BUY" returns adverts whose own adv.tradeType reads "SELL".
Both are correct: the request parameter is what you want to do, the response
field is what the advertiser is doing. Conflating them inverts every spread
and the result still looks plausible, which makes it the most expensive
mistake available here. Side keeps the two apart with
request_trade_type()/advert_trade_type(), and a test asserts they are never
equal.

**An empty market answers HTTP 200 with success: true.** NGN returned zero
adverts. "No ads" and "no answer" need opposite responses, so
is_empty_market() is a named predicate and ScanError separates Malformed
(Binance changed the payload; retrying makes it worse) from Network
(transient). basis_points_above returns None against a zero base rather than
an infinity, so an empty book cannot read as an infinite opportunity at 3am.

Money is never a float, following the rule in nigig-pay-domain/src/money.rs.
IEEE 754 cannot represent 0.1 and a spread is a difference of two nearly
equal numbers, which is exactly where binary floating point loses the digits
that matter. Binance sends prices as decimal strings, so Price parses them
straight into scaled i128 integers and never passes through f64. i128 rather
than i64 because the intermediate in a bps calculation overflows, not the
result. Excess precision is refused rather than rounded and a thousands
separator is refused rather than dropped: "1,299.92" read as 129992 is a
1000x error that still looks like a price. Tests pin 0.1 + 0.2 == 0.3 and
rotate 100 round trips at one price asserting exactly zero P&L.

Alerting is mostly restraint. At a 30-second poll one wide spread would fire
120 identical messages an hour, and a channel that cries wolf gets muted, at
which point the tool has negative value because the user believes they are
covered. AlertGate suppresses repeats inside a cooldown and re-alerts early
only when the spread improves materially -- a collapsing spread is not worth
waking someone for. Telegram MarkdownV2 escaping is tested against a real
merchant name from the capture, Twin_traders00, whose underscore would
otherwise make Telegram reject the message with a 400 and deliver nothing.

Writing the dashboard view model found a bug in my own comparator: sorting
descending by swapping the tuple to (b, a) also silently swaps the meaning
of the None arms, which put dead markets at the top of the opportunity list.
The test that caught it was written first and named for the behaviour, not
the implementation.

Networking is behind a non-default `live` feature, so an ordinary cargo test
cannot make a request and CI never depends on Binance being reachable. A CI
step asserts reqwest is absent from the default dependency graph so this
cannot regress quietly. A live scan was run once to confirm the fixtures
match reality; it reported a negative spread for KES and an empty NGN book,
which is the tool working correctly.

Conventions follow the repo rather than the generic layout in the request:
.forgejo/workflows/p2p-intel.yml rather than .github, and no Dockerfile,
since the stack is pure Rust and nothing else here is containerised.
error_set is used instead of anyhow, matching nigig-core. The root
Cargo.toml excludes the nested workspace by name, as it already does for
makepad_table, so the isolation is intentional rather than dependent on a
table inside someone else's manifest.

106 tests, coverage 96.86% with per-file floors enforced by
tools/test-p2p-coverage.sh. Both the total and per-file gates were verified
to actually fail by running them with impossible floors; a gate that cannot
fail is decoration. Two files are excluded and only because they were first
emptied of decisions: the Makepad widget, which needs a GPU and a windowing
backend this repo has no headless backend for, and the CLI main, which is
argument parsing and println. Every rule the widget renders lives in
view_model.rs, measured at 97%. That split is deliberate --
spreadsheet-ui/grid.rs once hid 36 pure functions behind a file-level
exclusion, and excluding a file you have not emptied of logic is how that
happens.

The Makepad desktop binary was built and linked in the sandbox to prove the
app half is real and not just a compiling stub.
2026-09-01 09:13:43 +00:00