Every durable SQLite operation used by the app is listed here. covered scenario names refer to fixtures in
modules/vescape-core/shared/; Android runs them through the production Room DAO/persistence seams
and macOS runs the same fixture through production GRDB seams. A composite operation covers its
private leaf statements because the transaction, ordering, and rollback are the observable contract.
| Store | Production operations | Status, executable scenario, or exact reason |
|---|---|---|
| Ride Recording | insert frames; insert/update/merge minute buckets; insert markers; insert/merge exclusion ranges | moving-recording-close-reopen; remaining-stores-close-reopen-rollback covers exclusion merge and late transaction failure |
| Ride Track and recording identity | begin/end recording; insert GPS fixes with buckets; identity-scoped history reads/deletion | RideTrackPersistenceHostTest and the Swift persistence host cover GPS-only close/reopen, retained poor accuracy, and late-write rollback; native suites cover lifecycle and identity isolation. Production backup exchange preserves recording end intent and GPS fixes in both directions. |
| Ride History | summary; paged sessions; buckets; frames/range; markers; Board names; profile stats | precomputed-history-reads |
| Telemetry maintenance | delete before; delete Board range; delete all-Board range; clear; rebuild buckets | remaining-stores-close-reopen-rollback executes the app-used orchestration on both production hosts, including Favorite bucket protection, Board-scoped exclusion preservation, sparse Android frame reconstruction, and rollback when the second range fails |
| Boards | list/get/name lookup; atomic Board+settings upsert; tombstone with settings/warnings/alerts/config/notice cascade | board-settings-close-reopen |
| Board settings | list by one/many Boards; upsert/delete | board-settings-close-reopen, through atomic Board save/delete |
| App settings | list/get/upsert/delete | covered: board-settings-close-reopen |
| Navigation/Group Ride settings | navigation path/profile, direction point, Group Ride identity/target multi-write ordering | remaining-stores-close-reopen-rollback covers typed path/profile and atomic Direction Point persistence across reopen; focused navigation controller tests cover ordered path/profile writes |
| Privacy Zones | list/list enabled; typed upsert; enable/disable; delete | remaining-stores-close-reopen-rollback covers typed upsert/read/reopen, failed update preservation, and delete |
| Alert Rules | list/list enabled; upsert; enable/disable; delete one/all | tune-history-alert-close-reopen-rollback; all-delete is covered by board-settings-close-reopen tombstone cascade |
| Tune Profiles | list/get/count; create; rename; save with history; rollback; copy; delete with history | tune-history-alert-close-reopen-rollback |
| Favorites | list/get; create; update; delete | favorite-create-rename-trim-delete-reopen |
| Favorite Media | list; insert manifest after file publish; delete/reconcile manifest; Favorite cascade | favorite-create-rename-trim-delete-reopen; filesystem compensation is in platform unit tests because Room/GRDB host contracts cover SQLite, not platform filesystems |
| Local Diagnostic Events | insert; range query; clear; prune with telemetry retention | remaining-stores-close-reopen-rollback covers typed insert/range/reopen, prune, clear, and failed insert propagation on both hosts |
| Board Config Values | exact/latest read; typed upsert; patch; delete; replace baseline plus notice atomically | Covered: remaining-stores-close-reopen-rollback; patch is the same typed-row update and has focused config unit coverage |
| Motor Config Values | latest read; typed upsert; delete; replace baseline plus shared notice atomically | Covered: remaining-stores-close-reopen-rollback |
| Board Config Change Notice | read; typed upsert; delete; merge Board/Motor diffs | Covered: remaining-stores-close-reopen-rollback, including corrupt notice and late baseline rollback; Board tombstone cascade covered by board-settings-close-reopen |
| Board Warnings | one/Board/all reads; typed upsert; delete one/all | remaining-stores-close-reopen-rollback covers typed upsert/read/reopen/query failure; delete one/all is exercised through the production registry suites and Board tombstone contract |
| VESC Fault Occurrences | Board/all/open/one reads; insert-or-advance; dismiss | remaining-stores-close-reopen-rollback covers progression, dismissal preservation, open/all reads, reopen, and query failure; coordinator suites cover lifecycle decisions |
| VESC Fault Captures | typed capture upsert/read; append/read ordered samples | remaining-stores-close-reopen-rollback covers metadata, ordered append/read, reopen, and late append rollback |
| Enrolled Accessories | list/get; enroll and re-validate upsert; touch last connection; adopt a new capability baseline; forget with calibrations | accessory-enrollment-close-reopen covers close/reopen, a rename plus firmware change plus new BLE handle landing on one row with its original enrollment time, touch on a missing row, and forget leaving other enrollments alone |
| Ground-clearance calibration | list/get; save; clear one; cascade on forget | accessory-enrollment-close-reopen covers close/reopen of saved near/far/direction/strength, two capabilities on one Accessory staying independent, revalidation leaving both alone, adoptCapabilities moving the frozen baseline, and forget taking every calibration in one transaction |
map_points, map_point_reactions |
none | Legacy migration tables only. Map Points are server-owned and production native code performs no SQLite operation. Kept until #468 tests supported migration/backup restoration. |
| Device credentials | Keychain/EncryptedSharedPreferences read/write/delete | Outside SQLite host contract: platform security-store tests own it; no table exists in the native database. |
| Session resume and navigation runtime snapshot | UserDefaults/shared-preference read/write/delete | Outside SQLite host contract: platform unit tests own these OS preference adapters; no table exists in the native database. |
All SQLite read/write bridge failures are reported with a sanitized operation name. Full disk, corruption, I/O, cannot-open, and read-only classifications additionally enter the durable app storage failure state and stop storage actions. Ordinary query/schema/domain failures reject their operation without disabling BLE, live gauges, or in-memory Alert evaluation. Startup clears a saved outage only after a real transactional create/write/drop check succeeds.
AccessoryPersistence.saveBrakeLight / AccessoryStore.saveBrakeLight persist sensitivity and
parked preference per accessory/capability in accessory_brake_light, schema 46. Forgetting an
accessory deletes its light settings in the enrollment transaction. Saving requires an enrolled
owner in the same transaction. accessory-persistence-contract.json drives Room and GRDB
close/reopen and forget-isolation coverage in AccessoryPersistenceHostTest and the macOS host.
The complete test:persistence gate also exchanges production archives across both platforms.
AccessoryPersistence.saveCapabilitySettings / AccessoryStore.saveCapabilitySettings store an
independent enabled flag in accessory_capability_settings (schema 47). Missing rows default to
enabled; failed reads do not enable hardware. Writes require an enrolled owner. Forget removes its
switches in the enrollment transaction. The shared accessory fixture drives Room/GRDB reopen,
calibration preservation, owner isolation, and rejected orphan-write coverage in
AccessoryPersistenceHostTest and the macOS host. The migration manifest includes schema 47.
Schema 48 adds nullable sampling_rate_hz to these same per-capability settings. Existing switches
survive migration with no selected rate, using the initial 10 Hz preference. Rate changes preserve
the enabled flag; enable/disable changes preserve the selected rate. The shared fixture also checks
that selected rates survive close/reopen and remain isolated across accessories.