mirror of
https://github.com/minibits-cash/minibits_wallet.git
synced 2026-08-09 08:14:44 +00:00
Completes the mint-identity work. A mint url is a network locator and mints move, but the url had become the de facto foreign key for nearly every persisted row, so a url edit had to fan out across the schema and mostly did not. Each table now references the mint by an identity that a move cannot disturb, and setMintUrl shrinks to the two things that genuinely hold a url: Mint.mintUrl and the proofs.mintUrl cache. Which identity, per table mintId (Mint.id) where the row needs the mint itself: - onchain_mint_quotes. The critical one: a quote's address stays creditable for as long as the mint exists (rows are never deleted), so the reference has to outlive a move. It followed row.mintUrl, and the watcher swallows errors by design — a renamed mint stranded deposits permanently and silently. - reservations. A url edit racing an open send did not merely misfile the proofs; commitReservation resolved the mint by url, so it threw "Mint not found" and aborted the commit of an operation the mint had already performed. - transactions. `mint` was two things at once, switched by status: a historical record of where a finished payment happened, AND a live pointer dialled for an open one. That conflation is why a rename had to rewrite in-flight rows — rewriting the very column that records the past. mintId takes the identity job, so `mint` is frozen as history and the status-scoped rewrite is retired. No reference at all where the row already has a parent: - inflight_requests, melt_recovery are CHILD rows of a transaction (their primary key IS transactionId), so the parent owns "which mint". Their mintUrl and keysetId copies had ZERO readers — the keyset that is used comes from inside meltPreview. Both dropped; the one mint-scoped query joins through transactions.mintId. Nothing left to go stale. Mint.id gets referential authority only, never identity authority: findById answers "which mint is this row about?" and must never answer "are these the same mint?" — it is random and unrelated to the keys, so that question stays with the keysets. The backfills are IS NULL-guarded so a resolved row can never be re-pointed at whichever mint now answers an old url. Backfills run from JS (v38 seed), not SQL: mints live in the MST/MMKV snapshot, so nothing in SQL can map url -> id. Matching on url is trustworthy at exactly that moment and no other — until now a url could not change without these rows being rewritten to match. The join is spent once, at rest, instead of on every rename. Migration-system fixes found along the way - _dbVersion is now DERIVED from the migration list. It was a hand-maintained literal, and it was already wrong: it said 33 while migration 34 existed, so 34 would never have run. The failure is silent and asymmetric — fresh installs build from schema.ts and are fine, while upgrading devices land on a schema the code does not have. dbMigrationRegistry.test.ts pins this and the ordering invariants. - Migrations 26/28/29/31 built their tables from the LIVE schema constants. A device replaying them would get today's shape, and the later ALTER adding the column would fail with "duplicate column name" — breaking upgrades from exactly the versions those migrations serve. Historical shapes are frozen locally now, and the schema.ts header no longer recommends the sharing. - rootStoreModelVersion was left at 37 while the seed guarded on < 38, so the backfill would have re-run on every launch forever. Tests: 421 pass. Six hand-mirrored suites had drifted from the schema they claim to mirror; transactionsMintUrl.test.ts was worse — still passing while testing a function this commit deletes, so it is removed. The mirroring pattern is worth revisiting. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>