@chipmobilesdk/rn-local-db 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/CHANGELOG.md +191 -102
  2. package/README.md +728 -728
  3. package/package.json +62 -62
  4. package/skills/sdk-rn-local-db/SKILL.md +0 -1
  5. package/src/adapter/budgets.ts +67 -67
  6. package/src/adapter/collection.ts +303 -298
  7. package/src/adapter/deletion.ts +252 -252
  8. package/src/adapter/index.ts +64 -68
  9. package/src/adapter/lifecycle.ts +517 -520
  10. package/src/adapter/transaction.ts +71 -71
  11. package/src/artifacts/availability.ts +67 -67
  12. package/src/artifacts/cascade.ts +114 -114
  13. package/src/artifacts/paths.ts +29 -29
  14. package/src/artifacts/reconcile.ts +63 -63
  15. package/src/artifacts/store.ts +334 -345
  16. package/src/contract/adapter.ts +76 -78
  17. package/src/contract/attachment.ts +75 -78
  18. package/src/contract/backup.ts +28 -28
  19. package/src/contract/config.ts +54 -54
  20. package/src/contract/encryption.ts +34 -34
  21. package/src/contract/errors.ts +76 -76
  22. package/src/contract/migration.ts +42 -42
  23. package/src/contract/query.ts +81 -81
  24. package/src/contract/record.ts +46 -51
  25. package/src/contract/schema.ts +36 -36
  26. package/src/contract/scope.ts +36 -36
  27. package/src/contract/transaction.ts +52 -54
  28. package/src/crypto/chunked-cipher.ts +153 -150
  29. package/src/crypto/derive.ts +64 -64
  30. package/src/crypto/key-provider.ts +78 -78
  31. package/src/crypto/provider.ts +75 -81
  32. package/src/diagnostics/dev-log.ts +132 -108
  33. package/src/diagnostics/errors.ts +63 -66
  34. package/src/diagnostics/faults.ts +58 -64
  35. package/src/diagnostics/map-native.ts +108 -106
  36. package/src/diagnostics/redact.ts +119 -141
  37. package/src/index.ts +80 -110
  38. package/src/migration/executor.ts +132 -136
  39. package/src/migration/ledger.ts +95 -97
  40. package/src/migration/validate-chain.ts +65 -65
  41. package/src/platform/backup-android-verify.ts +88 -88
  42. package/src/platform/backup-ios.ts +49 -48
  43. package/src/platform/bytes.ts +157 -144
  44. package/src/platform/fs.ts +90 -89
  45. package/src/platform/location.ts +135 -135
  46. package/src/query/budgets.ts +54 -54
  47. package/src/query/compare.ts +91 -91
  48. package/src/query/cursor.ts +100 -100
  49. package/src/query/filter.ts +82 -82
  50. package/src/query/paginate.ts +51 -51
  51. package/src/query/sort.ts +55 -56
  52. package/src/query/validate.ts +171 -171
  53. package/src/schema/declare.ts +42 -45
  54. package/src/schema/validate-config.ts +158 -158
  55. package/src/scope/hash.ts +131 -134
  56. package/src/scope/normalize.ts +83 -90
  57. package/src/scope/validate.ts +83 -83
  58. package/src/sqlite/adapter.ts +26 -26
  59. package/src/sqlite/batch.ts +242 -242
  60. package/src/sqlite/catalog.ts +105 -108
  61. package/src/sqlite/connection.ts +227 -227
  62. package/src/sqlite/index-coverage.ts +54 -56
  63. package/src/sqlite/native.ts +84 -83
  64. package/src/sqlite/row-codec.ts +217 -221
  65. package/src/sqlite/sql-builder.ts +244 -244
  66. package/src/sqlite/transaction-queue.ts +87 -87
  67. package/src/sqlite/transactions.ts +33 -33
  68. package/src/sqlite/values.ts +24 -24
  69. package/src/testing/conformance/attachments.ts +139 -136
  70. package/src/testing/conformance/encryption.ts +151 -150
  71. package/src/testing/conformance/index.ts +161 -161
  72. package/src/testing/conformance/lifecycle.ts +99 -99
  73. package/src/testing/conformance/migrations.ts +177 -177
  74. package/src/testing/conformance/queries.ts +204 -167
  75. package/src/testing/conformance/records.ts +169 -169
  76. package/src/testing/conformance/scopes.ts +86 -88
  77. package/src/testing/conformance/transactions.ts +149 -149
  78. package/src/testing/faults.ts +21 -21
  79. package/src/testing/index.ts +17 -21
  80. package/src/testing/memory-adapter/collection.ts +214 -219
  81. package/src/testing/memory-adapter/index.ts +511 -492
  82. package/src/testing/memory-adapter/migrations.ts +117 -119
  83. package/src/testing/memory-adapter/reset.ts +50 -50
  84. package/src/testing/memory-adapter/store.ts +128 -134
package/CHANGELOG.md CHANGED
@@ -1,102 +1,191 @@
1
- # Changelog
2
-
3
- All notable changes to `@chipmobilesdk/rn-local-db` are recorded here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this package follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
-
5
- ## [0.2.0] — 2026-11-01
6
-
7
- Fixes a data-loss defect in transactions and attachment handling that failed on every
8
- Hermes device. **One behaviour change needs a code change** (see Changed).
9
-
10
- ### Fixed
11
-
12
- - **A write from outside a transaction is no longer lost with its rollback.** The
13
- connection routed every statement into whatever transaction was in flight, so a write
14
- from another screen or a background sync while a transaction ran was rolled back with
15
- it, and a reader outside saw uncommitted data. Each handle now queues work behind a
16
- running transaction; only the executor the transaction hands out reaches it. The
17
- memory adapter isolates the same way, so conformance now catches a regression. After
18
- `tx.abort()` the body's remaining statements are refused instead of running in
19
- autocommit.
20
- - **Attachments work on Hermes.** Writes and reads used Node's global `Buffer`, which
21
- Hermes does not have. Byte handling is now `Uint8Array` with a self-contained base64
22
- codec; the encrypted file format is unchanged.
23
- - **A batch upsert over a soft-deleted record restores it**, and a batch insert over one
24
- conflicts — the collection API's rules. The batch used to issue an INSERT and fail the
25
- whole batch on the primary key.
26
- - **Index names are scoped to their collection.** Two collections declaring an index of
27
- the same name used to get only the first one, a UNIQUE constraint included. Existing
28
- indexes are renamed on the next open; no data moves. `explain()` still reports the
29
- declared name.
30
- - **Deleting an encrypted scope no longer needs its key.** A failing or destroyed key
31
- failed the call after the scope was marked, leaving it stuck in `deleting`. The data is
32
- deleted and the outcome sets `recordCountUnavailable`.
33
- - **Cascaded attachment removal is transaction-safe and reported.** Inside a
34
- transaction, files are removed only after it commits, so a rollback no longer leaves a
35
- reference to a deleted file. The reference is deleted before the file, a file that
36
- could not be removed is reported in `failedRemovals`, batch deletes cascade, and the
37
- memory adapter implements cascading.
38
-
39
- ### Changed
40
-
41
- - **Needs a code change:** inside a transaction body, write attachments through
42
- `tx.attachments()` (new) instead of `handle.attachments()`. The handle's call now waits
43
- for the transaction; awaited from inside the body it is refused with
44
- `TRANSACTION_STATE` after 10 seconds and the transaction rolls back, instead of
45
- hanging. The same applies to `handle.collection()`, which inside a transaction was
46
- already documented as a mistake.
47
- - `MigrationContext` no longer includes `attachments()`.
48
-
49
- ### Added
50
-
51
- - `Transaction.attachments()`.
52
- - `WriteOutcome.cascade` on a delete when `cascadeAttachments` is on.
53
- - `DeletionOutcome.recordCountUnavailable`.
54
-
55
- ## [0.1.0] — 2026-08-01
56
-
57
- First release. New package, no existing consumers, no migration burden.
58
-
59
- ### Added
60
-
61
- - **Scope-isolated storage.** One SQLite database file per scope. Scope is bound to a handle at open and immutable for its lifetime; no read, write, or query operation accepts a scope argument, and there is no `switchScope`. Scope components are hashed — only the SHA-256 digest reaches disk, a log, or an error.
62
- - **Records.** `insert`, `update`, `upsert` (reporting created versus updated), `get`, `find`, `delete`, `softDelete`, `restore`. Payloads round-trip with zero coercions, and the four value conditions — record absent, field null, field absent, record soft-deleted — stay distinguishable.
63
- - **Queries.** Twelve operators plus `and`/`or`/`not`, multi-key sorting with a deterministic `id` tiebreaker, keyset pagination, and `count` that always agrees with the corresponding list. An invalid query is an error rather than an empty or complete result. Development-mode index-coverage reporting via `explain`.
64
- - **Transactions and batches.** Real ACID transactions with read-your-own-writes, explicit abort, and terminal-state rejection. Batches of up to 1,000 operations applied as one unit.
65
- - **Migrations.** Ascending, at most once per scope, one transaction each, with a per-scope ledger. A failing chain returns no handle and alters nothing; a downgrade is refused rather than truncating. `resetScope` is the separately named recovery path.
66
- - **Deletion lifecycle.** `deleteScopeData`, `deleteDatabase`, and `resetScope` as module-level functions that work with or without an open handle. Nothing is ever deleted unasked — no expiry, no eviction, no sweep on close or upgrade. Every deletion reports what it removed and what it could not.
67
- - **Attachments.** Package-owned artifacts with availability checks that never open the file, owner-scoped listing, opt-in cascade on record deletion, and app-triggered reconciliation for orphaned files and dangling references. Every filesystem operation is confined to the managed storage area.
68
- - **Encryption at rest.** Opt-in under an app-supplied key. SQLCipher for records; chunked AES-256-GCM with HKDF-derived per-artifact subkeys for files, one 256 KB chunk in flight so memory is flat in artifact size. The package never generates, persists, caches beyond the handle, returns, or logs key material, and depends on no keychain library.
69
- - **Backup posture.** Excluded by default. Enforced on iOS via `NSURLIsExcludedFromBackupKey`; verified and reported on Android, where participation is manifest-owned and unreachable from a library that authors no native code.
70
- - **Typed diagnostics.** Twenty-nine stable `DiagnosticCode` values with `isCode` so no consumer parses a message. Disk-full, filesystem-access, and corruption stay distinct. Redaction happens at construction, so no error carries a payload, query parameter, scope component, or key material in any build.
71
- - **`./testing` entrypoint.** In-memory adapter, the conformance suite both adapters must pass identically, deterministic reset, seeding through production write paths, and fault injection for every diagnostic code.
72
-
73
- ### Documented
74
-
75
- - Six knowing divergences between the in-memory and on-device adapters, in the README.
76
- - The full diagnostic table with recommended recovery per condition.
77
- - The FR-088 budgets, and which four are hard limits.
78
- - The consumer data-behaviour note: what is stored, where, what leaves the device (nothing), the at-rest and backup postures, and what scope deletion does and does not guarantee.
79
-
80
- ### Semver impact
81
-
82
- New package at `0.1.0`. Nothing to migrate from.
83
-
84
- | Surface | Status | Notes |
85
- |---|---|---|
86
- | Lifecycle, records, query, transaction, batch | **Stable** | Breaking changes need a major |
87
- | Scope deletion and reset | **Stable** | |
88
- | Attachments including reconciliation | **Stable** | |
89
- | Diagnostic codes | **Stable, additive** | A new code is a minor; renaming one is breaking |
90
- | Encryption and key provider | **Experimental** | Field-level encryption and posture conversion may extend it |
91
- | Backup posture reporting | **Experimental** | The Android `observed` / `enforcedBy` shape may change as verification improves |
92
- | `StorageAdapter` interface | **Experimental** | Exported so the conformance suite is usable; not yet a stable extension point |
93
- | Testing entrypoint | **Experimental** | |
94
-
95
- Reserved as additive minors: reactive query subscriptions, field-level encryption, in-place encryption-posture conversion, further filter operators, and further diagnostic codes. Any change to the physical layout, the artifact format, or the encryption format ships with an internal migration or is breaking.
96
-
97
- ### Known limitations
98
-
99
- - **Android backup exclusion cannot be enforced by this package.** It ships the exact configuration, verifies coverage at runtime, and reports the observed posture; the manifest entry is the app's.
100
- - **Encryption posture cannot be converted in place.** Export, delete the scope, re-import.
101
- - **A transaction never spans two scopes.** One database file per scope makes this a type error rather than a runtime one.
102
- - **No reactive subscriptions.** Queries are pull-based in this version.
1
+ # @chipmobilesdk/rn-local-db
2
+
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - One diagnostic stream: install a sink with `installSdkSink` from
8
+ `@chipmobilesdk/rn-core` and it receives what every package observes (events,
9
+ failures, warnings) as `SdkDiagnostic`s, redacted. Listeners are notified through
10
+ rn-core, so a listener that throws no longer stops the others nor fails the call that
11
+ notified, and its error is reported rather than swallowed. ([#17](https://github.com/operationd8979/chip-mobile-sdk/pull/17))
12
+
13
+ - rn-ads: a banner's auto-refresh is a new cycle, so its `loaded` and `impression`
14
+ events are no longer deduplicated away; the dedupe memory is bounded. A throwing
15
+ status, consent or placement listener is reported as an `internal_error` event.
16
+ - rn-i18n: new `onDiagnostic` config receives every diagnostic (`I18nDiagnostic`,
17
+ with a stable `code`); without it, warnings go to `console.warn` in development
18
+ builds only. The warn-once memory is bounded.
19
+ - rn-chart: now depends on rn-core for its diagnostics.
20
+ - rn-payment: status, entitlement and pending listeners report a throw to the logger
21
+ instead of swallowing it.
22
+
23
+ - The package's errors extend `SdkError` from the new `@chipmobilesdk/rn-core`
24
+ dependency: `isSdkError` recognises them alongside every other package's, and each
25
+ carries `pkg`, `code` and `retryable`. Names and codes are unchanged. ([#17](https://github.com/operationd8979/chip-mobile-sdk/pull/17))
26
+
27
+ - rn-ai and rn-camera: `retryable` is the new name of `recoverable`, which stays as a
28
+ deprecated alias.
29
+ - rn-auth: `retryable` is true for `network-unavailable`. `redact` also removes URLs,
30
+ e-mail addresses and UUIDs.
31
+ - rn-ads: `redact` also removes JWTs and e-mail addresses, and reduces an `AdsError`
32
+ to its code.
33
+ - rn-ai: an error message quoted from the gateway is pattern-redacted.
34
+ - rn-camera: `redact` also removes JWTs, e-mail addresses and UUIDs.
35
+ - rn-theme: `ThemeConfigError` has `code: 'invalid_config'` and `ThemeContrastError`
36
+ `code: 'contrast'` (new `ThemeErrorCode` type).
37
+ - rn-i18n: `I18nConfigError` has `code: 'invalid_config'` and `UnitConversionError`
38
+ `code: 'unit_conversion'` (new `I18nErrorCode` type).
39
+
40
+ - Native peers load through `lazyPeer` from `@chipmobilesdk/rn-core`, on first use,
41
+ and a missing one is each package's own typed error. ([#17](https://github.com/operationd8979/chip-mobile-sdk/pull/17))
42
+
43
+ - rn-auth: creating `auth` no longer loads react-native-app-auth or
44
+ react-native-keychain; each loads on first use. New entrypoints
45
+ `@chipmobilesdk/rn-auth/app-auth` and `/keychain`. The default platform comes from
46
+ rn-core.
47
+ - rn-camera: a preview whose VisionCamera feed cannot load fails the session with
48
+ `cameraUnavailable` (new `controller.reportSurfaceUnavailable()`), instead of
49
+ showing black with no error. A missing VisionCamera module is `cameraUnavailable`.
50
+ - rn-notification: `createMmkvStore` reports a fallback to memory as
51
+ `STATE_STORE_DEGRADED` (to the SDK sinks and a new `onDegraded` option) and
52
+ exposes `durable`.
53
+ - rn-payment: an iOS app validates its catalog against the iOS product ids; the
54
+ default platform used to be Android everywhere. A missing react-native-iap is
55
+ `PAYMENT_UNAVAILABLE`.
56
+ - rn-theme: `buildThemes` runs without React Native (new `hairlineWidth` option) and
57
+ importing the package no longer loads Unistyles; `applyThemeMode` loads it on
58
+ first use.
59
+ - rn-ads, rn-local-db: the same loading, with the same error codes as before.
60
+
61
+ ### Patch Changes
62
+
63
+ - The `./testing` memory adapter and conformance suite no longer use Node's `Buffer`, so
64
+ they run on Hermes as well as under Jest; base64 goes through the same byte helpers the
65
+ SQLite adapter uses. Optional properties in the public types (`Query`, `PageRequest`,
66
+ `DatabaseConfig.encryption`, `AttachmentReference.owner`, `StorageError` and others)
67
+ now accept an explicit `undefined`, so apps compiling with
68
+ `exactOptionalPropertyTypes` can pass a value that may be missing. ([#17](https://github.com/operationd8979/chip-mobile-sdk/pull/17))
69
+ - Updated dependencies ([#17](https://github.com/operationd8979/chip-mobile-sdk/pull/17), [#17](https://github.com/operationd8979/chip-mobile-sdk/pull/17), [#17](https://github.com/operationd8979/chip-mobile-sdk/pull/17)):
70
+ - @chipmobilesdk/rn-core@0.1.0
71
+
72
+ ## 0.2.1
73
+
74
+ ### Patch Changes
75
+
76
+ - Packaging only; no code change. The package no longer declares `engines.node`: a
77
+ React Native package does not run on Node, so the field only produced install
78
+ warnings in apps on another Node version. rn-i18n's command-line tooling does run
79
+ on Node; its README's compatibility table states the version it needs. ([#14](https://github.com/operationd8979/chip-mobile-sdk/pull/14))
80
+
81
+ ## [0.2.0] — 2026-11-01
82
+
83
+ Fixes a data-loss defect in transactions and attachment handling that failed on every
84
+ Hermes device. **One behaviour change needs a code change** (see Changed).
85
+
86
+ ### Fixed
87
+
88
+ - **A write from outside a transaction is no longer lost with its rollback.** The
89
+ connection routed every statement into whatever transaction was in flight, so a write
90
+ from another screen or a background sync while a transaction ran was rolled back with
91
+ it, and a reader outside saw uncommitted data. Each handle now queues work behind a
92
+ running transaction; only the executor the transaction hands out reaches it. The
93
+ memory adapter isolates the same way, so conformance now catches a regression. After
94
+ `tx.abort()` the body's remaining statements are refused instead of running in
95
+ autocommit.
96
+ - **Attachments work on Hermes.** Writes and reads used Node's global `Buffer`, which
97
+ Hermes does not have. Byte handling is now `Uint8Array` with a self-contained base64
98
+ codec; the encrypted file format is unchanged.
99
+ - **A batch upsert over a soft-deleted record restores it**, and a batch insert over one
100
+ conflicts — the collection API's rules. The batch used to issue an INSERT and fail the
101
+ whole batch on the primary key.
102
+ - **Index names are scoped to their collection.** Two collections declaring an index of
103
+ the same name used to get only the first one, a UNIQUE constraint included. Existing
104
+ indexes are renamed on the next open; no data moves. `explain()` still reports the
105
+ declared name.
106
+ - **Deleting an encrypted scope no longer needs its key.** A failing or destroyed key
107
+ failed the call after the scope was marked, leaving it stuck in `deleting`. The data is
108
+ deleted and the outcome sets `recordCountUnavailable`.
109
+ - **Cascaded attachment removal is transaction-safe and reported.** Inside a
110
+ transaction, files are removed only after it commits, so a rollback no longer leaves a
111
+ reference to a deleted file. The reference is deleted before the file, a file that
112
+ could not be removed is reported in `failedRemovals`, batch deletes cascade, and the
113
+ memory adapter implements cascading.
114
+
115
+ ### Changed
116
+
117
+ - **Needs a code change:** inside a transaction body, write attachments through
118
+ `tx.attachments()` (new) instead of `handle.attachments()`. The handle's call now waits
119
+ for the transaction; awaited from inside the body it is refused with
120
+ `TRANSACTION_STATE` after 10 seconds and the transaction rolls back, instead of
121
+ hanging. The same applies to `handle.collection()`, which inside a transaction was
122
+ already documented as a mistake.
123
+ - `MigrationContext` no longer includes `attachments()`.
124
+
125
+ ### Added
126
+
127
+ - `Transaction.attachments()`.
128
+ - `WriteOutcome.cascade` on a delete when `cascadeAttachments` is on.
129
+ - `DeletionOutcome.recordCountUnavailable`.
130
+
131
+ ## [0.1.2] — 2026-09-12
132
+
133
+ ### Changed
134
+
135
+ - The shipped agent skill and the README were clarified. No code change.
136
+
137
+ ## [0.1.1] — 2026-08-01
138
+
139
+ ### Changed
140
+
141
+ - The package now ships its agent skill (`skills/`), which consuming apps
142
+ copy in with `scripts/sync-sdk-skills.mjs`. No code change.
143
+
144
+ ## [0.1.0] — 2026-08-01
145
+
146
+ First release. New package, no existing consumers, no migration burden.
147
+
148
+ ### Added
149
+
150
+ - **Scope-isolated storage.** One SQLite database file per scope. Scope is bound to a handle at open and immutable for its lifetime; no read, write, or query operation accepts a scope argument, and there is no `switchScope`. Scope components are hashed — only the SHA-256 digest reaches disk, a log, or an error.
151
+ - **Records.** `insert`, `update`, `upsert` (reporting created versus updated), `get`, `find`, `delete`, `softDelete`, `restore`. Payloads round-trip with zero coercions, and the four value conditions — record absent, field null, field absent, record soft-deleted — stay distinguishable.
152
+ - **Queries.** Twelve operators plus `and`/`or`/`not`, multi-key sorting with a deterministic `id` tiebreaker, keyset pagination, and `count` that always agrees with the corresponding list. An invalid query is an error rather than an empty or complete result. Development-mode index-coverage reporting via `explain`.
153
+ - **Transactions and batches.** Real ACID transactions with read-your-own-writes, explicit abort, and terminal-state rejection. Batches of up to 1,000 operations applied as one unit.
154
+ - **Migrations.** Ascending, at most once per scope, one transaction each, with a per-scope ledger. A failing chain returns no handle and alters nothing; a downgrade is refused rather than truncating. `resetScope` is the separately named recovery path.
155
+ - **Deletion lifecycle.** `deleteScopeData`, `deleteDatabase`, and `resetScope` as module-level functions that work with or without an open handle. Nothing is ever deleted unasked — no expiry, no eviction, no sweep on close or upgrade. Every deletion reports what it removed and what it could not.
156
+ - **Attachments.** Package-owned artifacts with availability checks that never open the file, owner-scoped listing, opt-in cascade on record deletion, and app-triggered reconciliation for orphaned files and dangling references. Every filesystem operation is confined to the managed storage area.
157
+ - **Encryption at rest.** Opt-in under an app-supplied key. SQLCipher for records; chunked AES-256-GCM with HKDF-derived per-artifact subkeys for files, one 256 KB chunk in flight so memory is flat in artifact size. The package never generates, persists, caches beyond the handle, returns, or logs key material, and depends on no keychain library.
158
+ - **Backup posture.** Excluded by default. Enforced on iOS via `NSURLIsExcludedFromBackupKey`; verified and reported on Android, where participation is manifest-owned and unreachable from a library that authors no native code.
159
+ - **Typed diagnostics.** Twenty-nine stable `DiagnosticCode` values with `isCode` so no consumer parses a message. Disk-full, filesystem-access, and corruption stay distinct. Redaction happens at construction, so no error carries a payload, query parameter, scope component, or key material in any build.
160
+ - **`./testing` entrypoint.** In-memory adapter, the conformance suite both adapters must pass identically, deterministic reset, seeding through production write paths, and fault injection for every diagnostic code.
161
+
162
+ ### Documented
163
+
164
+ - Six knowing divergences between the in-memory and on-device adapters, in the README.
165
+ - The full diagnostic table with recommended recovery per condition.
166
+ - The FR-088 budgets, and which four are hard limits.
167
+ - The consumer data-behaviour note: what is stored, where, what leaves the device (nothing), the at-rest and backup postures, and what scope deletion does and does not guarantee.
168
+
169
+ ### Semver impact
170
+
171
+ New package at `0.1.0`. Nothing to migrate from.
172
+
173
+ | Surface | Status | Notes |
174
+ |---|---|---|
175
+ | Lifecycle, records, query, transaction, batch | **Stable** | Breaking changes need a major |
176
+ | Scope deletion and reset | **Stable** | |
177
+ | Attachments including reconciliation | **Stable** | |
178
+ | Diagnostic codes | **Stable, additive** | A new code is a minor; renaming one is breaking |
179
+ | Encryption and key provider | **Experimental** | Field-level encryption and posture conversion may extend it |
180
+ | Backup posture reporting | **Experimental** | The Android `observed` / `enforcedBy` shape may change as verification improves |
181
+ | `StorageAdapter` interface | **Experimental** | Exported so the conformance suite is usable; not yet a stable extension point |
182
+ | Testing entrypoint | **Experimental** | |
183
+
184
+ Reserved as additive minors: reactive query subscriptions, field-level encryption, in-place encryption-posture conversion, further filter operators, and further diagnostic codes. Any change to the physical layout, the artifact format, or the encryption format ships with an internal migration or is breaking.
185
+
186
+ ### Known limitations
187
+
188
+ - **Android backup exclusion cannot be enforced by this package.** It ships the exact configuration, verifies coverage at runtime, and reports the observed posture; the manifest entry is the app's.
189
+ - **Encryption posture cannot be converted in place.** Export, delete the scope, re-import.
190
+ - **A transaction never spans two scopes.** One database file per scope makes this a type error rather than a runtime one.
191
+ - **No reactive subscriptions.** Queries are pull-based in this version.