main
dev
chore/365-cut-1.2.1
fix/363-pin-db-path
feat/351-contact-settings-menu
feat/349-window-geometry
feat/355-migration-merge
integration/290-306-335
release/1.1.2-rc.3-allplatforms
fix/309-path-len-decode
chore/298-path-logging
fix/285-ingest-timelog
fix/252-block-outgoing-dm
feat/64-observer-config
feat/batch1-ux
chore/offband-rebrand
v1.2.1
v1.2.0
v1.1.2-rc.3-allplatforms
v1.1.2-rc.3
v1.1.2-rc.2
v1.0.0
observer-g2-rc3
observer-g2-rc4
observer-g2-rc5
observer-g2-rc6
observer-g2-rc7
observer-g2-rc8
observer-g2-rc9
v1.1.0-rc.1
v1.1.0-rc.2
v1.1.0-rc.3
v1.1.2-beta.1
v1.1.2-beta.2
v1.1.2-beta.3
v1.1.2-ble-test
v1.1.2-queuediag
v1.1.2-rc.1
v1.1.2-rc.1-b45-nearbyrep
v1.1.2-rc.1-b46-pathhash
v1.1.2-rc.1-b47-tracewidth
v1.1.2-rc.1-b48-repeatertrace
v1.1.2-rc.1-b49-maptrace
v1.1.2-rc.1-b50-tracefix
v1.1.2-rc.1-b51-originstrip
v1.1.2-rc.1-b52-channelqr
v1.1.2-rc.1-b53-viarepeater
v1.1.2-rc.1-b54-rxfed
v1.1.2-rc.1-b55-topology
v1.1.2-rc.1-b57-routeux
v1.1.2-rc.1-b58-toporeadout
v1.1.2-rc.3-b59-pathlen
${ noResults }
4 Commits (dd67391a0e8afd1ce298094f6fd710a662ac4f23)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
dd67391a0e |
feat(#335): switch bulk stores over to drift
Wires the migration into startup and points the four bulk stores at drift. SharedPreferences keeps the settings, which is what it is for. Startup runs the migration after prefs are up and BEFORE any store reads, and awaits it. Letting stores race a half-finished migration is precisely the shape of #333, where a storage path silently chose the wrong key and 566 real messages read as empty. Converted: message_store, channel_message_store, contact_store, contact_discovery_store. All four now have ZERO prefs get/set for bulk data. Three safety properties, deliberately built in: 1. readWithPrefsFallback - if a key is somehow not in drift, the prefs copy is still served rather than reading as empty. It logs a WARNING when it fires, because a fallback during normal operation means the migration is incomplete and someone needs to know. Silence here is what made #333 look like data loss. 2. deleteEverywhere / keysWithPrefix span BOTH backends. A clear that only removed the drift row would leave a pre-migration prefs copy to reappear through the fallback, resurrecting deleted history. 3. The legacy-key migrations inside the stores now check both backends and only touch prefs when a legacy key actually exists. This also carries the #306 fix into this branch: the unconditional prefs.remove was still present here, since this branched from dev rather than from the #306 work. Verified: analyze clean, format clean, 504 tests pass, Windows and web both build. Migration rehearsed earlier against a copy of a real 7 MB store: 69 keys, 5.21 MB, zero failures. NOT yet run against live data - that happens on first launch of this build, and the owner should have a prefs backup before that. |
3 days ago |
|
|
a2c7302aad |
feat(#335): migrate bulk data from SharedPreferences into drift
Moves message history, contacts and discovered contacts out of the settings store. Settings stay in SharedPreferences, which is what it is for. Ordering is the whole safety argument: WRITE, VERIFY BY READING BACK, and only then remove the source. #333 was a storage path that chose a key silently and made 566 real messages read as empty; deleting before verifying would make that class of mistake permanent instead of cosmetic. On any failure the source is left intact and the error is logged - never a silent drop (SAFELANE 6). Idempotent by construction: a key already present in drift is not overwritten, so re-running is a no-op. If an older build re-writes a migrated key into prefs, the migrated copy wins and the stale prefs copy is discarded rather than promoted. Rehearsed against a COPY of a real 7 MB store, as the plan required before touching live data: REHEARSAL: 69 migrated, 0 failed, 5.21 MB, 69 bulk keys expected Every key checked for exact length, confirmed removed from prefs, and every settings key confirmed untouched. The live store was never opened. Two things the tests caught that review would not have: 1. getString THROWS on a non-string value rather than returning null, so a non-string under a bulk prefix was counted as a migration FAILURE. It now type-checks with prefs.get() and skips. Alarming falsely is its own bug. 2. The `contacts` prefix was checked against the real store rather than assumed: it matches only the 6 bulk contact blobs, and correctly does NOT match contact_unread_count*. Not yet wired into app startup - that is the switchover, and it is deliberately a separate commit so this can be reviewed on its own. flutter analyze clean, dart format clean, 504 tests pass. |
3 days ago |
|
|
847a28df3e |
feat(#335): prove drift/SQLite-WASM works in a real browser
Step 1 gate, web half. Building is not evidence, so this was run in a browser. Assets: sqlite3.wasm (748 KB) and drift_worker.js (355 KB), both taken from the SAME drift-2.34.2 release so they are built against each other. Validated before use - the wasm has correct WebAssembly magic (0061 736d) and carries SQLite 3.53.3; the worker is genuine compiled Dart JS. Note the filename: the release ships `drift_worker.js`, not the `drift_worker.dart.js` the docs name. The database URI was corrected to match, which would otherwise have been a silent 404 at runtime. Browser result, served over HTTP with COOP/COEP and Content-Type: application/wasm: Using WasmStorageImplementation.opfsLocks PROBE-OK open+write+read PROBE-OK 6MiB round-trip (localStorage cap is 5MiB) drift selected OPFS, the top storage tier, and round-tripped 6 MiB - data the current localStorage-backed web build physically cannot hold. No exceptions. Adds web/_headers for Cloudflare Pages: forces application/wasm on the wasm asset and sets COOP/COEP for cross-origin isolation. Verified to ship into build/web. Without COOP/COEP drift still works, falling back to IndexedDB, which is slower but still unbounded next to localStorage - a performance tier, not a correctness requirement. web_probe/ is a standalone entrypoint that exercises ONLY the drift stack, so a pass or fail is unambiguous without BLE and the rest of the app in the way. It is not part of the app build. Still no user data touched and no store switched over. The migration is the next step. flutter analyze clean, dart format clean, 497 tests pass. |
3 days ago |
|
|
19858698ee |
feat(#335): add drift and prove it opens on the targets buildable here
Step 1 of #335, deliberately before any data migration: prove the store works before trusting it with message history. Adds drift + drift_flutter, a key/value StoredBlobs table mapping 1:1 onto the existing SharedPreferences keys, and verifyReadWrite() as a runtime probe. Key/value rather than relational tables on purpose: it maps directly onto the current store interfaces, so callers do not change and the migration can be verified row-for-row against the old keys. Relational schemas come later, once this is proven and querying is actually wanted. Verified here: - 3 tests pass, including a 6 MiB round-trip - larger than the 5 MiB localStorage cap that makes the web build impossible today - flutter analyze clean - Windows release build succeeds - Web release build compiles Two findings from the gate that a plan-on-paper would have missed: 1. sqlite3_flutter_libs 0.6.0+eol is a DEPRECATED no-op. From sqlite3 v3.x it is unnecessary and drift_flutter already covers it, so it is not a direct dependency here. 2. The web build COMPILES BUT WOULD FAIL AT RUNTIME: drift needs sqlite3.wasm and drift_worker.dart.js shipped in web/, and neither is present. Per drift docs they are downloaded from GitHub releases, version-matched to pubspec.lock (drift 2.34.2, sqlite3 3.5.0), and the server must serve .wasm as Content-Type: application/wasm. Not done here - downloading files needs explicit human approval. Also noted: the drift_dev CLI does not compile at these versions (allSchemaEntities missing from the drift3_preview GeneratedDatabase), so its asset tooling is unavailable. build_runner code generation is unaffected. No user data is touched. No store is switched over. The migration is the next step and remains gated on the web assets question. |
3 days ago |