@abloatai/ablo 0.64.3 → 0.64.5

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,49 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.64.5
4
+
5
+ ### Authoritative queries preserve freshness through reload
6
+
7
+ Complete browser queries now keep their freshness requirement when a local-first
8
+ read is already running. Empty server results remain empty, and snapshots
9
+ rejected as older than resident data no longer overwrite the local cache.
10
+ Network query results wait for accepted rows, including expanded relations, to
11
+ finish their storage writes. Storage failures now reject the read instead of
12
+ silently reporting success. The client behavior guide distinguishes query
13
+ hydration, exact point reads and the limits of IndexedDB durability.
14
+
15
+ ### Storage failures leave bootstrap unfinished
16
+
17
+ IndexedDB transactions that abort now reject their pending writes, allowing
18
+ browser startup to report a storage failure instead of waiting indefinitely.
19
+ Bootstrap no longer marks incomplete rows as persisted or advances its checkpoint
20
+ past changes that could not be stored. Applications can retry after local storage
21
+ recovers without treating a partial snapshot as complete.
22
+
23
+ ### Bootstrap allows time for capacity to recover
24
+
25
+ The browser client now honours the server's retry interval when bootstrap is
26
+ temporarily refused for capacity. These responses use a bounded recovery window
27
+ without consuming the attempts reserved for fetch failures. Cancelling bootstrap
28
+ also cancels its retry wait. Companion replication-lease and admission changes
29
+ require a separate sync-server rollout; installing this release does not deploy
30
+ them.
31
+
32
+ ### Clearer connection checks and diagnostics
33
+
34
+ `ablo connect check` still exits with a nonzero status while existing rows are
35
+ loading, but treats that state as an expected polling result. CLI error reports
36
+ retain their stack frames and use valid release identifiers while continuing to
37
+ sanitize diagnostic data.
38
+
39
+ ## 0.64.4
40
+
41
+ ### Cached rows follow account authority
42
+
43
+ The reactive client now separates IndexedDB replicas and offline bootstrap snapshots by authenticated groups and operation grants, alongside user, organization, project and branch. Disposing a client and opening another account in the same organization no longer restores the previous account's rows before reconciliation. Reloading the same authority retains its warm cache.
44
+
45
+ Existing caches start cold because their older namespace cannot establish account ownership. Older IndexedDB files, including pending writes, are retained but are not automatically imported or replayed into the new namespace. A replica widened by live group additions is rejected when reopened under narrower authority, preserving its pending writes.
46
+
3
47
  ## 0.64.3
4
48
 
5
49
  ### Existing connections make room for new tables
@@ -70,6 +70,61 @@ to read.
70
70
  lifecycle filter defaults to `'live'`; pass `'archived'` or `'all'` when you
71
71
  intentionally want non-live rows.
72
72
 
73
+ ## Browser read freshness and persistence
74
+
75
+ These modes apply after `await ablo.ready()` on the reactive browser client.
76
+ Reads before initialization provide no persistence guarantee. A headless HTTP client has no
77
+ local graph or IndexedDB replica; its reads go to the server.
78
+
79
+ | Read | Can return cached data? | Network | Reactive graph | Offline / missing | Persistence when resolved |
80
+ | --- | --- | --- | --- | --- | --- |
81
+ | `local.get`, `local.list`, `local.count` | Yes; memory only | None | Read only | Available offline; `undefined`, `[]`, or `0` means absent locally | No write or durability barrier |
82
+ | `list` with omitted `type` or `type: 'unknown'` | Yes; memory, then IndexedDB | Cold queries block; warm queries confirm in the background once per connection | Hydrates accepted rows | Warm data can be stale; cold network failure rejects; a successful empty network answer returns `[]` | A local hit does not wait for background writes; a network result waits for its accepted rows' storage transactions |
83
+ | `list({ type: 'complete' })` | Never substitutes cached rows for an empty server answer; newer resident versions can supersede returned snapshots | Always awaits a query, including when local data exists | Hydrates accepted rows | Network failure rejects without stale fallback; missing matches return `[]` | Waits for accepted primary and expanded rows' storage transactions; storage failure rejects |
84
+ | `get({ id, type? })`, `read({ id, type? })` | The query hydration stage follows the `list` policy | Also performs an authoritative point read after hydration | The query stage updates the graph; the additional point response does not | Point-read failure rejects even with warm data; missing row returns `undefined` | Query-stage writes finish first; the separate point response is not itself persisted |
85
+
86
+ An unhydrated query with `expand` waits for the network even when its parent is
87
+ cached: a parent alone cannot establish that its children are loaded. Omitted
88
+ `type` is local-first for every model load strategy. Reconnecting clears the
89
+ query hydration ledger. `complete` describes freshness, not an unlimited result
90
+ set; keep queries bounded and inspect the collection's `hasMore`.
91
+
92
+ Query responses meet resident rows by server log position, not `updatedAt`. A
93
+ snapshot known to precede an accepted subscription version cannot replace that
94
+ resident row or overwrite its persisted data. Pending local edits remain visible.
95
+ An empty query result does not delete cached rows: filtered or limited query
96
+ absence is not a deletion event. Synchronized deletes remove rows from the graph;
97
+ a local selector then observes their absence.
98
+
99
+ For a reload-sensitive external publication, explicitly hydrate the desired rows:
100
+
101
+ ```ts
102
+ await ablo.ready();
103
+ // The application server has already confirmed its publication.
104
+ await ablo.sourceSnapshots.list({ where: { id: snapshotId }, type: 'complete' });
105
+ await ablo.sourceHeads.list({ where: { id: headId }, type: 'complete' });
106
+ // Accepted query rows have reached the configured local storage.
107
+ ```
108
+
109
+ Configure `persistence: 'indexeddb'` on the browser client for reload persistence.
110
+ Memory persistence cannot survive a reload. IndexedDB completion here means a
111
+ completed browser transaction, using relaxed durability; it is not a guarantee
112
+ against power loss, browser eviction, or a later authorized update or deletion.
113
+ The barrier covers these queries' accepted writes, not every pending subscription
114
+ or mutation. `waitForFlush()` waits for server mutation confirmation and is not a
115
+ local persistence barrier. If a storage write fails, the graph may already show
116
+ the result; retry the complete read before relying on reload persistence.
117
+
118
+ Use `read` when a later write needs exact captured read evidence. Use a complete
119
+ `list` query when the purpose is to populate and persist the reactive working
120
+ set. A `get`/`read` result and the local graph are distinct snapshots and can differ
121
+ if the row changes between the query and point requests.
122
+
123
+ Account changes require disposing the old client and constructing a new scoped
124
+ client, as shown in [React](./react.md). Do not reuse an old request's result as
125
+ initial data for the new account. The same user, project and branch do not make
126
+ two accounts the same persistence authority.
127
+
73
128
  ## Multiplayer Behavior
74
129
 
75
130
  Two writers both try to mark `report_stockholm` ready at the same time. To stop
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abloatai/ablo",
3
- "version": "0.64.3",
3
+ "version": "0.64.5",
4
4
  "description": "The public Ablo SDK for coordinated reads, commits, claims, observation, and reactive applications.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -147,8 +147,8 @@
147
147
  "directory": "packages/ablo"
148
148
  },
149
149
  "dependencies": {
150
- "@abloatai/humans": "0.64.3",
151
- "@abloatai/transaction": "0.64.3",
150
+ "@abloatai/humans": "0.64.5",
151
+ "@abloatai/transaction": "0.64.5",
152
152
  "zod": "^4.4.3"
153
153
  },
154
154
  "peerDependencies": {