@abloatai/ablo 0.60.0 → 0.62.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,59 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.62.0
4
+
5
+ Every live client now exposes one session-owned `ablo.presence` projection.
6
+ `active` shows the current session's announced activity and `others` shows the
7
+ other visible sessions. The reactive client adds `forModel(model, id?)` to
8
+ narrow the same projection without opening another connection. Read, claim,
9
+ create, update, and delete activity share one typed, model-addressable contract
10
+ and remain attributable to their originating human or agent session.
11
+
12
+ Claims and presence now have separate owners: the durable claim authority
13
+ decides admission, queuing, fencing, expiry, and release, while presence
14
+ projects that lifecycle for live collaborators. Cross-replica HTTP callers
15
+ resolve and release claims against the shared authority instead of a
16
+ process-local roster. An object-form claim also returns its protected row
17
+ snapshot in the acquisition request, removing the post-grant read race and an
18
+ extra round trip.
19
+
20
+ This replaces the earlier participant-oriented presence stream and its raw
21
+ wire event vocabulary. Migrate `PresenceStream`, `Peer`, `Activity`,
22
+ `PresenceUpdate*`, and `PresenceKind` consumers to `Ablo.Presence`,
23
+ `Ablo.PresenceSession`, and `Ablo.PresenceActivity`; read the projection through
24
+ `ablo.presence.active`, `ablo.presence.others`, or
25
+ `ablo.presence.forModel(model, id?)`. The low-level `presence_update` event,
26
+ frame-handler members, presence schemas, and claim-stream participant setters
27
+ are removed because session identity and typed presence snapshot/patch frames
28
+ now own that lifecycle.
29
+
30
+ Admission and other transient failures now expose machine-actionable
31
+ `recovery`, `retryable`, and `retryAfterSeconds` fields through the branded
32
+ package, including session issuance and headless model requests. The headless
33
+ client automatically replays an admission-rejected request after the requested
34
+ delay, without restarting the surrounding claim workflow. Queued HTTP claims
35
+ heartbeat through their known model and row target, so one holder releasing
36
+ cannot make the next queued ticket appear lost during promotion. A visibility
37
+ miss while the fence is minted is retried only inside the ticket's last
38
+ server-acknowledged lease window.
39
+
40
+ ## 0.61.0
41
+
42
+ ### Existing database connections repair in place
43
+
44
+ `ablo connect apply` is now the single repeatable operation for both a new
45
+ database connection and an existing registration. A healthy connection is a
46
+ no-op. When a registration predates current publication, replica-identity,
47
+ grant, or row-level-security requirements, the same command reconciles those
48
+ database-owned invariants through the transient owner URL while preserving
49
+ Ablo's working scoped passwords.
50
+
51
+ If that repair means an earlier initial snapshot may have omitted rows, the
52
+ operation requests the required fresh snapshot and subsequent reruns report its
53
+ loading or ready state. Automation can select `--json` for stable lifecycle and
54
+ per-step codes instead of parsing human output. Credential rotation remains an
55
+ explicit operation for an actually incomplete or invalid role pair.
56
+
3
57
  ## 0.60.0
4
58
 
5
59
  ### Sessions are the connection boundary for people and agents
@@ -2,9 +2,9 @@ export * from '@abloatai/transaction/coordination';
2
2
  /**
3
3
  * Coordination vocabulary that the streams module declares.
4
4
  *
5
- * A caller that holds a claim, watches presence, or types an activity feed
6
- * needs these names, and coordination is where they belong — so they are
5
+ * A caller that holds a claim needs these names, and coordination is where
6
+ * they belong — so they are
7
7
  * surfaced here rather than leaving callers to reach into the type module.
8
8
  */
9
- export type { Activity, Claim, ClaimTarget } from '@abloatai/transaction/types/streams';
9
+ export type { Claim, ClaimTarget } from '@abloatai/transaction/types/streams';
10
10
  //# sourceMappingURL=coordination.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"coordination.d.ts","sourceRoot":"","sources":["../src/coordination.ts"],"names":[],"mappings":"AAAA,cAAc,oCAAoC,CAAC;AAEnD;;;;;;GAMG;AACH,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC"}
1
+ {"version":3,"file":"coordination.d.ts","sourceRoot":"","sources":["../src/coordination.ts"],"names":[],"mappings":"AAAA,cAAc,oCAAoC,CAAC;AAEnD;;;;;;GAMG;AACH,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC"}
package/docs/cli.md CHANGED
@@ -136,6 +136,7 @@ branch-bound runtime credential before starting application code.
136
136
  | `ablo migrate` | **Direct Postgres**: provision just the synced models (plus the adapter's `ablo_outbox` / `ablo_idempotency`) in your own `DATABASE_URL`. Leaves your other tables alone. | `--dry-run`, `--output <file>`, `--schema`, `--export` |
137
137
  | `ablo pull` | **Direct Postgres**: generate `defineSchema(...)` from your existing tables (read-only, like `prisma db pull`). | `--out <path>`, `--app-schema <name>`, `--import <pkg>`, `--force` |
138
138
  | `ablo check` | **Direct Postgres**: verify your _existing_ tables fit the schema (read-only, no schema changes). | `--schema <path>`, `--export <name>`, `--app-schema <name>` |
139
+ | `ablo connect plan\|apply\|check\|rotate\|deregister` | **Direct Postgres**: register and maintain a database plane. Here `--schema` means the existing PostgreSQL namespace, never a TypeScript file. | `--url <postgres-url>`, `--schema <postgres-schema>`, `--env-file <path>`, `--yes` |
139
140
  | `ablo generate` | Emit TypeScript types from the schema. | `--out <path>`, `--schema`, `--export` |
140
141
  | `ablo docs` | Read these pages for the version you installed: offline, no network (see [`ablo docs`](#ablo-docs)). | `--json` |
141
142
 
@@ -157,13 +157,20 @@ see. Options on the claim:
157
157
  - `{ maxQueueDepth }` rejects if the wait line is already too deep.
158
158
 
159
159
  While waiting, schema clients learn when the claim clears from the live claim
160
- stream, so they never poll.
160
+ stream, so they never poll. Headless HTTP clients poll the same durable queue;
161
+ the model client keeps the row target on each heartbeat, so a holder releasing
162
+ cannot make the queued ticket unresolvable by id. During fence minting, it also
163
+ keeps polling through a visibility miss only while the server's last enqueue or
164
+ heartbeat acknowledgement still guarantees that ticket is live.
161
165
 
162
166
  ## Errors
163
167
 
164
168
  All SDK errors extend `AbloError`. `type` is the class-name discriminator, such
165
169
  as `AbloStaleContextError`; `code` is the wire condition, such as
166
170
  `stale_context`. Use `instanceof` in-process and `type` after serialization.
171
+ Every error also exposes a typed `recovery` classification and `retryable`
172
+ boolean. When the server requests a minimum delay, `retryAfterSeconds` is
173
+ present on the same error for both 429 and 503 responses.
167
174
 
168
175
  | Error | Typical cause |
169
176
  |---|---|
@@ -196,8 +203,14 @@ Model writes are retry-safe by default because the SDK attaches an idempotency
196
203
  key. If you provide your own key, keep it stable for retries of the same logical
197
204
  operation and never reuse it for a different payload.
198
205
 
199
- Retry transport failures and 5xx with backoff. Do not blindly retry validation,
200
- permission, idempotency, or stale-context errors without changing the request.
206
+ Retry transport failures and 5xx with backoff. For example, an
207
+ `instance_at_capacity` error has `recovery === 'transient'`; wait at least
208
+ `retryAfterSeconds` before replaying the unchanged request. The headless HTTP
209
+ client performs that exact replay within `timeoutMs`; importantly, it does not
210
+ restart a larger claim/read/write workflow around the rejected request. If the
211
+ deadline is exhausted, the same actionable error reaches the caller. Do not
212
+ blindly retry validation, permission, idempotency, or stale-context errors
213
+ without changing the request.
201
214
 
202
215
  ## Logging
203
216
 
@@ -132,6 +132,27 @@ npx ablo connect apply --env-file .env.local --yes
132
132
  The explicit flag makes the credential choice visible and loads both the
133
133
  branch-bound key and database URL. Shell environment variables take precedence.
134
134
 
135
+ ### Two schema flags, two ownership boundaries
136
+
137
+ `migrate` and `push` read your Ablo TypeScript contract. `connect apply` also
138
+ reads it to derive the mapped Postgres tables; `--tables` is an explicit
139
+ override:
140
+
141
+ ```bash
142
+ # TypeScript contract and export; app-schema selects its Postgres namespace.
143
+ npx ablo migrate --schema ablo/schema.ts --export schema --app-schema public
144
+
145
+ # Existing Postgres namespace only. Never pass ablo/schema.ts here.
146
+ npx ablo connect apply --schema public --yes
147
+
148
+ # Activate the TypeScript contract after the database is connected.
149
+ npx ablo push --schema ablo/schema.ts --export schema
150
+ ```
151
+
152
+ If the database uses its default namespace, omit `connect --schema`; it defaults
153
+ to `public`. Keep the three operations in this order in deployment automation:
154
+ expand tables, connect the database, then activate the hosted schema.
155
+
135
156
  ### One database, several projects
136
157
 
137
158
  Provider database URLs and Postgres schemas solve different isolation jobs:
@@ -190,13 +211,18 @@ npx ablo connect apply --url postgres://admin:...@host:5432/db --schema mail
190
211
  ```
191
212
 
192
213
  Pass an admin connection string with `--url` and select the application namespace
193
- with `--schema` (default `public`). It creates a per-binding publication, two
194
- per-binding scoped roles, and the grants, turns on logical decoding where it can, registers
195
- both scoped roles with Ablo, and proves the setup by reconnecting and reading back.
214
+ with `--schema` (default `public`). It inspects and reconciles a per-binding
215
+ publication, two per-binding scoped roles, grants, replica identity,
216
+ registration, and the initial snapshot. On an existing healthy registration it
217
+ is a no-op and preserves both passwords. A policy-only repair also preserves
218
+ them; credential rotation happens only through the explicit `connect rotate`
219
+ operation.
220
+
196
221
  The admin credential is used on this machine only and never persisted — nothing is
197
- written to your `.env`, which keeps holding only `ABLO_API_KEY`. Pass `--show-sql`
198
- to see every statement first, or drop `--apply` to print the SQL and run it
199
- yourself. Rotate the scoped passwords any time with `ablo connect rotate`.
222
+ written to your `.env`, which keeps holding only `ABLO_API_KEY`. Pass
223
+ `--show-sql` to see every statement first, `--json` for stable result and step
224
+ codes, or drop `--apply` to print the SQL and run it yourself. Rotate the scoped
225
+ passwords any time with `ablo connect rotate`.
200
226
 
201
227
  The rest of this page is what that command sets up, step by step, for when you want
202
228
  to run it by hand or review exactly what changes.
@@ -215,19 +241,20 @@ the row to be visible already, and touching application rows is neither necessar
215
241
  nor a safe bootstrap mechanism.
216
242
 
217
243
  If a connection was snapshotted with an older replication role whose row-level
218
- security hid historical rows, repair that role and request the load again without
219
- deregistering or rotating credentials:
244
+ security hid historical rows, rerun the same operation. It repairs the owned
245
+ policy and requests the necessary fresh load without deregistering or rotating
246
+ credentials:
220
247
 
221
248
  ```bash
222
- npx ablo connect rotate # reasserts BYPASSRLS and safely re-registers both roles
223
- npx ablo connect resnapshot # recreates only the slot; the load is asynchronous
224
- npx ablo connect check # repeat until the existing-row load is complete
249
+ npx ablo connect apply --url postgres://owner:...@host/db --yes --json
250
+ # Rerun the same command: loading becomes ready; a healthy rerun is a no-op.
225
251
  ```
226
252
 
227
- Use the same `resnapshot` step after adding an existing populated table to the
228
- publication. Following its future WAL changes is not enough to load rows written
229
- before publication membership; the snapshot coverage guard therefore refuses to
230
- record completion when even one mapped table is absent. Relation matching is
253
+ Rerun `connect apply` after adding an existing populated table to the contract.
254
+ Following its future WAL changes is not enough to load rows written before
255
+ publication membership, so reconciliation updates membership and requests the
256
+ fresh snapshot together. The snapshot coverage guard refuses to record
257
+ completion when even one mapped table is absent. Relation matching is
231
258
  schema-qualified using the DataSource's configured `schema` (default `public`):
232
259
  an identically named table in another Postgres schema neither counts as coverage
233
260
  nor enters the snapshot or WAL stream for your model.
@@ -242,7 +242,7 @@ examples/
242
242
  inngest-agent/ events, functions, steps, endpoint, AI composition
243
243
  ```
244
244
 
245
- Do not add Inngest to `packages/agent`. A dedicated `@abloatai/inngest` package
245
+ Do not add Inngest orchestration to the Ablo core. A dedicated `@abloatai/inngest` package
246
246
  is justified only after multiple real applications reveal substantial
247
247
  reusable behavior beyond a small function or step wrapper.
248
248
 
@@ -178,7 +178,7 @@ The repository's
178
178
  [`examples/temporal-agent`](../../../../examples/temporal-agent/README.md)
179
179
  contains a Workflow, Activities, Worker, client, durable AI SDK tool, and a
180
180
  simulated lost-response retry. It is a standalone application on purpose:
181
- Temporal stays out of Ablo's core packages and out of `packages/agent`.
181
+ Temporal stays out of Ablo's core packages; applications own their agent composition.
182
182
 
183
183
  A dedicated `@abloatai/temporal` package should be introduced only after
184
184
  multiple production integrations reveal substantial, stable behavior that
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abloatai/ablo",
3
- "version": "0.60.0",
3
+ "version": "0.62.0",
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",
@@ -145,8 +145,8 @@
145
145
  "directory": "packages/ablo"
146
146
  },
147
147
  "dependencies": {
148
- "@abloatai/humans": "^0.60.0",
149
- "@abloatai/transaction": "^0.60.0",
148
+ "@abloatai/humans": "^0.62.0",
149
+ "@abloatai/transaction": "^0.62.0",
150
150
  "zod": "^4.4.3"
151
151
  },
152
152
  "peerDependencies": {