Upgrade react-native HotUpdater (0.23.0 → 0.32.0): drops SWCompression /
BitByteData pods and bumps OpenSSL-Universal to 3.6.2000. Set the iOS
launch scheme to Release.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Keep edgeToEdgeEnabled=true so the themed header draws behind the status
bar on pre-Android-15 devices (e.g. Moto G4). Android 15+ is edge-to-edge
OS-enforced regardless.
That flag also routes react-native Modal's native dialog window through RN
core's enableEdgeToEdge() (WindowUtil.kt), which hardcodes nav-bar contrast
enforcement and derives appearance from device dark mode, painting a grey
(white-in-dark) scrim on modal open/close. That code ships in the prebuilt
RN Android AAR and can't be patched.
Work around it without disabling the flag: on Android, BottomModal renders
in the app's React tree via @gorhom/portal (coverScreen={false}) instead of
as a native window, so it never hits that code path. A PortalProvider at the
app root keeps the modal overlaying the bottom tab bar. iOS keeps the native
modal path unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bump all hot-updater packages to a consistent 0.32.0 (CLI,
@hot-updater/react-native, bare, firebase, sentry-plugin), replacing the
previous mixed set (bare was pinned at 0.20.11).
- Add @expo/fingerprint as an explicit devDependency: it is now an
optional peer dep and is required by updateStrategy: "fingerprint".
- Remove patches/@hot-updater+bare+0.20.11.patch: the hermes-compiler
path resolution it added is now upstream in bare 0.32.0
(getHermesCompilerPackagePath).
hot-updater.config.ts needs no changes (firebaseStorage/firebaseDatabase
config shapes unchanged). The live 0.23.1 app runtime stays wire-compatible
with the redeployed 0.32.0 server (identical path-based update-check route).
Infra steps still required (run separately): npx hot-updater init to
refresh Firebase functions + Android native config, then a native rebuild
to enable bundle diffing for new installs.
Also drops dead commented-out @noble/curves Metro resolver workaround.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replaces react-native-quick-sqlite (8.2.7) with @op-engineering/op-sqlite
(16.2.0). The motivating bug: quick-sqlite's JSI binding silently dropped
non-bindable JS objects (e.g. a cashu-ts Amount instance), shifting the
parameter array and corrupting proof rows with no exception.
A new connection adapter (services/db/connection.ts) is the single seam to
the native library and reconciles op-sqlite's API differences so sqlite.ts
is nearly untouched:
- op-sqlite execute() is async; sync is executeSync() -> our execute maps
to executeSync, executeAsync maps to execute
- executeBatch() is async-only with no insertId -> synchronous atomic batch
emulated with BEGIN/COMMIT/ROLLBACK over executeSync
- rows is a plain array -> re-wrapped into the WebSQL { _array, length,
item() } shape the existing query code expects
The adapter also centralizes parameter sanitization (sanitizeParams): every
bind is coerced deliberately (Date -> ISO, numeric-like objects -> Number) or
rejected loudly, so the silent-skip footgun is structurally impossible.
Also collapses 33 repetitive try/catch AppError blocks into a dbError()
helper, which uniformly passes deliberate AppErrors (e.g. NOTFOUND_ERROR)
through instead of flattening them to DATABASE_ERROR (-109 net lines).
Tests: 121/121 pass, no regressions. Note: native rebuild and on-device
verification of the minibits.db file location are still required before ship.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>