Repository navigation
feat(store): lift GRDB message store out of LXMFSwift into app-owned MessageStore/ - #219
Merged
Merged
Conversation
…MessageStore/ Phase 0-1 of the Android-parity store lift: re-architect iOS messaging persistence so the GRDB store is app-owned (Sources/ColumbaApp/Services/ MessageStore/) with zero dependency on the LXMFSwift wire library, matching Android's :data module pattern. New app-owned store (GRDB + Foundation only, no LXMFSwift / RNSAPI / ReticulumSwift): - MessageRow.swift: GRDB row for messages table (24 columns, byte-identical to LXMFSwift MessageRecord minus the LXMessage-coupled init/toLXMessage) - ConversationRecordStore.swift: GRDB row for conversations table (struct named ConversationStoreRow to avoid collision with SwiftUI ConversationRow) - GRDBVocabulary.swift: frozen GRDBState (0x00..0xFF) and GRDBDeliveryMethod (0x01/02/03/05) enums, byte-identical to LXMFSwift and NE Python - MessageStore.swift: GRDB actor with migrations v1-v6 byte-identical to LXMFSwift LXMFDatabase; 5 LXMessage-returning methods re-pointed to row-based surface MessageRepository re-scoped to the collector (Android's MessageCollector role): property LXMFSwift.LXMFDatabase -> MessageStore; 5 LXMessage-welded methods rewritten to row-based; only remaining LXMFSwift refs are the wire codec (LXMessage.unpackFromBytes) in recoverFields/normalizedFieldMap. Tests: 14 new MessageStoreTests (schema freeze vs NE writer, state/method vocabulary round-trips, frozen byte values, unknown-method sentinel, save/ read round-trip, inbound-unread increment, cross-process app-reading-NE-row, makeRow field-map + replyTo + sentinel, outbound-id loading). Updated MicronParserTests adapter tests to app-owned row types. Updated 2 static contract tests (qr_contact_send_path, reported_runtime_bugs) to assert the unknown-method invariant at its new location. Verified: 547/547 ColumbaAppTests green; static Python suite 0 new failures vs pristine main; ModelB device build SUCCEEDED (arm64 + NE + codesign); all 4 store .o files compiled into the ModelB target; installed in-place on iPhone (container B43B0B8A), running, zero GRDB/migration errors in diag.log. Note: LXMFSwift is retained as a transitive SPM dependency for the wire codec. Phase 2 (full LXMFSwift + ReticulumSwift removal) is deferred - it requires a native wire codec + Telemetry repoint + reconciler/contract-test teardown and is a distinct larger lift.
Contributor
|
…L, FK on_delete Greptile P2 (PR #219): the schema-freeze test only asserted column names, PK, and FK table name - not column types, NOT NULL, or FK on_delete behavior. A dropped .cascade would still pass while breaking conversation deletion. Extended both tests to assert the full frozen contract: - columnTypes: all 25 messages columns + all 13 conversations columns - notNullColumns: the exact NOT NULL set for both tables - foreignKeyDetails: (table, from, to, on_delete) tuple per FK Three new introspection helpers (columnTypes, notNullColumns, foreignKeyDetails) added alongside the existing schemaColumns/PK/FK/index helpers. All 547 tests green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 0-1 of the Android-parity store lift: re-architect iOS messaging persistence so the GRDB store is app-owned (
Sources/ColumbaApp/Services/MessageStore/) with zero dependency on the LXMFSwift wire library, matching Android's:datamodule pattern.The NE Python inbound writer keeps landing in the same frozen-schema
lxmf-swift.db; only the location and dependencies of the store's Swift code change.Changes
New app-owned store (
Sources/ColumbaApp/Services/MessageStore/— GRDB + Foundation only, no LXMFSwift / RNSAPI / ReticulumSwift):MessageRow.swift— GRDB row for themessagestable (24 columns, byte-identical to LXMFSwiftMessageRecordminus theLXMessage-coupledinit/toLXMessage).ConversationRecordStore.swift— GRDB row forconversations(struct namedConversationStoreRowto avoid collision with the SwiftUIConversationRowview).GRDBVocabulary.swift— frozenGRDBState(0x00..0xFF) andGRDBDeliveryMethod(0x01/02/03/05) enums, byte-identical to LXMFSwift and the NE Python.MessageStore.swift— GRDB actor, migrations v1-v6 byte-identical to LXMFSwift'sLXMFDatabase; the 5LXMessage-returning methods re-pointed to a row-based surface.MessageRepositoryre-scoped to the collector (Android'sMessageCollectorrole):LXMFSwift.LXMFDatabaseproperty →MessageStore; the 5LXMessage-welded methods rewritten to row-based. The only remaining LXMFSwift references are the wire codec (LXMessage.unpackFromBytes) inrecoverFields/normalizedFieldMap— legitimately kept, exactly as Android'sMessageCollectortouches LXMF-kt.Tests:
MessageStoreTests: schema-freeze vs the NE writer (PK/FK/column set), state + method vocabulary round-trips through the mappers, frozen byte values, unknown-method sentinel (0) round-trip, save/read round-trip, inbound-unread increment + source-hash conversation key, cross-process (app reads a raw NE-styleINSERTrow),makeRowfield-map + replyTo + sentinel, outbound-id loading.MicronParserTestsadapter tests to the app-owned row types.test_qr_contact_send_path_contract,test_reported_runtime_bugs) to assert the unknown-method invariant at its new location.Verification
ColumbaAppTestsgreen (14 new + all 533 existing).main(the 12 remaining are pre-existing, inrns_bridge._durable_mode, unrelated)..ofiles confirmed compiled into the ModelB target.B43B0B8A), running;diag.logshows zero GRDB/migration/schema/store errors — the app opens the existing shared DB cleanly through the new byte-identical migrations.f51bac69...) — the store's outbound path works end-to-end.Deferred (not in this PR)
60186710) and the one remaining live use is the wire codecunpackFromBytes(NE rows carry signed wire;packed_lxmfis dual-meaning). Full removal needs a native wire codec + Telemetry repoint + reconciler/contract-test teardown — a distinct larger lift.