One Rust core owns every rule and every query. The desktop talks to it over HTTP on loopback, and the phone will use the same routes in M6, so no screen has to know whether the core runs next to it or on another machine.
rules live herestoragelater milestone
The six rules the code is held to
Money is integer centimes with checked arithmetic. No float near a total.
One HTTP contract: the desktop and the phone are the same caller over the same routes.
Every query is scoped by shop_id; the API answers for one shop.
Errors are mapped, never re-derived: one enum per layer, a translation key per code, no Rust or SQL text on a screen.
No unwrap or expect in shipped Rust; no as assertions in TypeScript.
Types cross the boundary once, generated; a stale commit fails the gate.