@abloatai/ablo 0.34.1 → 0.35.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 (483) hide show
  1. package/AGENTS.md +2 -1
  2. package/CHANGELOG.md +674 -5
  3. package/README.md +39 -22
  4. package/dist/BaseSyncedStore.d.ts +152 -44
  5. package/dist/BaseSyncedStore.js +300 -184
  6. package/dist/Database.d.ts +9 -24
  7. package/dist/Database.js +37 -22
  8. package/dist/InstanceCache.d.ts +25 -4
  9. package/dist/InstanceCache.js +48 -15
  10. package/dist/LazyReferenceCollection.d.ts +3 -3
  11. package/dist/LazyReferenceCollection.js +4 -4
  12. package/dist/Model.d.ts +6 -6
  13. package/dist/Model.js +10 -10
  14. package/dist/ModelRegistry.d.ts +4 -4
  15. package/dist/ModelRegistry.js +3 -3
  16. package/dist/{SyncEngineContext.d.ts → RuntimeContext.d.ts} +20 -13
  17. package/dist/{SyncEngineContext.js → RuntimeContext.js} +11 -12
  18. package/dist/SyncClient.d.ts +42 -32
  19. package/dist/SyncClient.js +166 -110
  20. package/dist/ai-sdk/coordinatedTool.d.ts +2 -2
  21. package/dist/ai-sdk/coordinatedTool.js +1 -1
  22. package/dist/ai-sdk/coordinationContext.d.ts +2 -2
  23. package/dist/ai-sdk/coordinationContext.js +1 -1
  24. package/dist/ai-sdk/wrap.d.ts +3 -3
  25. package/dist/ai-sdk/wrap.js +2 -2
  26. package/dist/auth/index.d.ts +1 -156
  27. package/dist/auth/index.js +8 -301
  28. package/dist/cli.cjs +3344 -1073
  29. package/dist/client/Ablo.d.ts +42 -287
  30. package/dist/client/Ablo.js +118 -963
  31. package/dist/client/abloClient.d.ts +309 -0
  32. package/dist/client/abloClient.js +13 -0
  33. package/dist/client/clientPrelude.d.ts +52 -0
  34. package/dist/client/clientPrelude.js +60 -0
  35. package/dist/client/consoleLogger.d.ts +2 -2
  36. package/dist/client/coreClient.d.ts +60 -0
  37. package/dist/client/coreClient.js +118 -0
  38. package/dist/client/createInternalComponents.d.ts +4 -4
  39. package/dist/client/createInternalComponents.js +9 -8
  40. package/dist/client/createModelProxy.d.ts +78 -373
  41. package/dist/client/createModelProxy.js +114 -86
  42. package/dist/client/humans.d.ts +48 -0
  43. package/dist/client/humans.js +52 -0
  44. package/dist/client/modelRegistration.d.ts +1 -1
  45. package/dist/client/modelRegistration.js +9 -9
  46. package/dist/client/options.d.ts +73 -17
  47. package/dist/client/reactiveEngine.d.ts +48 -0
  48. package/dist/client/reactiveEngine.js +910 -0
  49. package/dist/client/resourceTypes.d.ts +9 -250
  50. package/dist/client/resourceTypes.js +8 -5
  51. package/dist/client/schemaConfig.d.ts +4 -4
  52. package/dist/client/schemaConfig.js +6 -2
  53. package/dist/client/validateAbloOptions.d.ts +3 -2
  54. package/dist/client/validateAbloOptions.js +1 -1
  55. package/dist/client/wsMutationExecutor.d.ts +3 -3
  56. package/dist/client/wsMutationExecutor.js +3 -3
  57. package/dist/context.d.ts +9 -9
  58. package/dist/context.js +10 -9
  59. package/dist/coordination/ClaimLog.d.ts +26 -0
  60. package/dist/coordination/ClaimLog.js +32 -0
  61. package/dist/coordination/index.d.ts +1 -15
  62. package/dist/coordination/index.js +8 -31
  63. package/dist/core/DatabaseManager.js +1 -1
  64. package/dist/core/QueryView.d.ts +1 -1
  65. package/dist/core/QueryView.js +1 -1
  66. package/dist/core/StoreManager.d.ts +4 -23
  67. package/dist/core/StoreManager.js +5 -55
  68. package/dist/core/index.d.ts +2 -2
  69. package/dist/core/index.js +2 -2
  70. package/dist/core/storeContract.d.ts +2 -2
  71. package/dist/docs/catalog.d.ts +72 -0
  72. package/dist/docs/catalog.js +227 -0
  73. package/dist/docs/index.d.ts +10 -0
  74. package/dist/docs/index.js +10 -0
  75. package/dist/environment.d.ts +1 -40
  76. package/dist/environment.js +8 -37
  77. package/dist/index.d.ts +40 -34
  78. package/dist/index.js +26 -20
  79. package/dist/interfaces/index.d.ts +44 -134
  80. package/dist/keys/index.d.ts +1 -77
  81. package/dist/keys/index.js +8 -190
  82. package/dist/mutators/{RecordingTransaction.d.ts → RecordingMutation.d.ts} +4 -4
  83. package/dist/mutators/{RecordingTransaction.js → RecordingMutation.js} +2 -2
  84. package/dist/mutators/Transaction.d.ts +1 -1
  85. package/dist/mutators/Transaction.js +1 -1
  86. package/dist/mutators/UndoManager.d.ts +6 -6
  87. package/dist/mutators/UndoManager.js +5 -5
  88. package/dist/mutators/defineMutators.d.ts +3 -3
  89. package/dist/mutators/defineMutators.js +1 -1
  90. package/dist/mutators/inverseOp.js +2 -2
  91. package/dist/mutators/mutateActions.d.ts +3 -3
  92. package/dist/mutators/mutateActions.js +1 -1
  93. package/dist/mutators/readerActions.d.ts +1 -1
  94. package/dist/mutators/undoApply.d.ts +1 -1
  95. package/dist/mutators/undoApply.js +1 -1
  96. package/dist/policy/index.d.ts +2 -2
  97. package/dist/policy/index.js +1 -1
  98. package/dist/query/client.d.ts +2 -2
  99. package/dist/query/client.js +4 -4
  100. package/dist/query/types.d.ts +6 -41
  101. package/dist/query/types.js +2 -2
  102. package/dist/react/AbloProvider.d.ts +6 -8
  103. package/dist/react/AbloProvider.js +5 -7
  104. package/dist/react/context.d.ts +1 -1
  105. package/dist/react/context.js +1 -1
  106. package/dist/react/index.d.ts +5 -5
  107. package/dist/react/index.js +3 -3
  108. package/dist/react/internalContext.d.ts +1 -1
  109. package/dist/react/useAblo.d.ts +3 -3
  110. package/dist/react/useAblo.js +1 -1
  111. package/dist/react/useCurrentUserId.js +1 -1
  112. package/dist/react/useErrorListener.js +1 -1
  113. package/dist/react/useMutationFailureListener.d.ts +2 -2
  114. package/dist/react/useMutationFailureListener.js +1 -1
  115. package/dist/react/useMutators.d.ts +3 -3
  116. package/dist/react/useMutators.js +3 -3
  117. package/dist/react/useUndoScope.d.ts +5 -5
  118. package/dist/react/useUndoScope.js +1 -1
  119. package/dist/schema/coordination.d.ts +69 -10
  120. package/dist/schema/coordination.js +86 -9
  121. package/dist/schema/ddl.js +2 -2
  122. package/dist/schema/diff.d.ts +1 -1
  123. package/dist/schema/generate.js +1 -1
  124. package/dist/schema/index.d.ts +10 -10
  125. package/dist/schema/index.js +18 -18
  126. package/dist/schema/queries.d.ts +27 -27
  127. package/dist/schema/queries.js +23 -23
  128. package/dist/schema/select.d.ts +3 -3
  129. package/dist/schema/select.js +3 -3
  130. package/dist/schema/serialize.d.ts +15 -6
  131. package/dist/schema/serialize.js +17 -3
  132. package/dist/schema/sugar.d.ts +6 -7
  133. package/dist/schema/sugar.js +9 -12
  134. package/dist/schema/syncDeltaRow.d.ts +4 -152
  135. package/dist/schema/syncDeltaRow.js +4 -105
  136. package/dist/server/adapter.d.ts +18 -1
  137. package/dist/server/commit.d.ts +10 -16
  138. package/dist/server/index.d.ts +1 -1
  139. package/dist/server/index.js +1 -1
  140. package/dist/server/readConfig.d.ts +1 -1
  141. package/dist/source/adapters/drizzle.d.ts +1 -1
  142. package/dist/source/adapters/drizzle.js +2 -2
  143. package/dist/source/adapters/kysely.d.ts +1 -1
  144. package/dist/source/adapters/kysely.js +1 -1
  145. package/dist/source/adapters/kyselyMutationCore.d.ts +1 -1
  146. package/dist/source/adapters/kyselyMutationCore.js +2 -2
  147. package/dist/source/adapters/memory.js +1 -1
  148. package/dist/source/adapters/prisma.d.ts +8 -3
  149. package/dist/source/adapters/prisma.js +1 -1
  150. package/dist/source/connector.js +1 -1
  151. package/dist/source/connectorProtocol.d.ts +2 -8
  152. package/dist/source/connectorProtocol.js +3 -2
  153. package/dist/source/contract.d.ts +29 -17
  154. package/dist/source/contract.js +27 -22
  155. package/dist/source/factory.d.ts +1 -1
  156. package/dist/source/footprint.d.ts +111 -0
  157. package/dist/source/footprint.js +0 -0
  158. package/dist/source/idempotency.js +2 -2
  159. package/dist/source/index.d.ts +1 -0
  160. package/dist/source/index.js +3 -0
  161. package/dist/source/next.d.ts +1 -1
  162. package/dist/source/signing.d.ts +9 -2
  163. package/dist/source/signing.js +4 -1
  164. package/dist/source/types.d.ts +6 -4
  165. package/dist/source/types.js +1 -1
  166. package/dist/stores/ObjectStore.d.ts +1 -1
  167. package/dist/stores/SyncActionStore.d.ts +1 -1
  168. package/dist/stores/SyncActionStore.js +2 -10
  169. package/dist/stores/syncAction.d.ts +26 -0
  170. package/dist/stores/syncAction.js +16 -0
  171. package/dist/surface.d.ts +3 -3
  172. package/dist/surface.js +6 -4
  173. package/dist/sync/BootstrapFetcher.d.ts +123 -6
  174. package/dist/sync/BootstrapFetcher.js +492 -66
  175. package/dist/sync/ConnectionManager.d.ts +6 -198
  176. package/dist/sync/ConnectionManager.js +6 -677
  177. package/dist/sync/OnDemandLoader.d.ts +2 -2
  178. package/dist/sync/OnDemandLoader.js +60 -21
  179. package/dist/sync/SubscriptionManager.d.ts +13 -2
  180. package/dist/sync/SubscriptionManager.js +23 -5
  181. package/dist/sync/SyncWebSocket.d.ts +27 -510
  182. package/dist/sync/SyncWebSocket.js +76 -954
  183. package/dist/sync/awaitClaimGrant.d.ts +4 -44
  184. package/dist/sync/awaitClaimGrant.js +4 -109
  185. package/dist/sync/commitFrames.d.ts +6 -40
  186. package/dist/sync/commitFrames.js +6 -97
  187. package/dist/sync/contextPorts.d.ts +18 -0
  188. package/dist/sync/contextPorts.js +31 -0
  189. package/dist/sync/createClaimStream.d.ts +5 -49
  190. package/dist/sync/createClaimStream.js +5 -469
  191. package/dist/sync/createPresenceStream.d.ts +26 -4
  192. package/dist/sync/createPresenceStream.js +28 -20
  193. package/dist/sync/createSnapshot.d.ts +2 -2
  194. package/dist/sync/createSnapshot.js +1 -1
  195. package/dist/sync/credentialLifecycle.d.ts +5 -173
  196. package/dist/sync/credentialLifecycle.js +5 -320
  197. package/dist/sync/deltaPipeline.d.ts +1 -1
  198. package/dist/sync/participants.d.ts +5 -4
  199. package/dist/sync/participants.js +29 -22
  200. package/dist/sync/schemaDrift.d.ts +55 -0
  201. package/dist/sync/schemaDrift.js +53 -0
  202. package/dist/sync/schemas.d.ts +21 -32
  203. package/dist/sync/schemas.js +26 -17
  204. package/dist/sync/syncPlan.d.ts +3 -3
  205. package/dist/sync/wsFrameHandlers.d.ts +6 -114
  206. package/dist/sync/wsFrameHandlers.js +6 -392
  207. package/dist/testing/fixtures/bootstrap.d.ts +1 -1
  208. package/dist/testing/fixtures/deltas.d.ts +1 -1
  209. package/dist/testing/fixtures/httpResponses.d.ts +70 -0
  210. package/dist/testing/fixtures/httpResponses.js +90 -0
  211. package/dist/testing/fixtures/models.js +1 -1
  212. package/dist/testing/helpers/wait.js +1 -1
  213. package/dist/testing/mocks/MockMutationExecutor.d.ts +2 -2
  214. package/dist/testing/mocks/MockMutationExecutor.js +8 -14
  215. package/dist/testing/mocks/MockSyncContext.d.ts +11 -11
  216. package/dist/testing/mocks/MockSyncContext.js +10 -9
  217. package/dist/testing/mocks/MockSyncStore.js +1 -1
  218. package/dist/testing/mocks/MockWebSocket.d.ts +2 -2
  219. package/dist/transaction/ablo.d.ts +88 -0
  220. package/dist/transaction/ablo.js +33 -0
  221. package/dist/{client/auth.d.ts → transaction/auth/apiKey.d.ts} +43 -8
  222. package/dist/{client/auth.js → transaction/auth/apiKey.js} +19 -0
  223. package/dist/transaction/auth/bootstrapScope.d.ts +15 -0
  224. package/dist/transaction/auth/bootstrapScope.js +1 -0
  225. package/dist/transaction/auth/capability.d.ts +177 -0
  226. package/dist/transaction/auth/capability.js +199 -0
  227. package/dist/{auth → transaction/auth}/credentialSource.d.ts +8 -1
  228. package/dist/{client → transaction/auth}/identity.d.ts +8 -7
  229. package/dist/{client → transaction/auth}/identity.js +1 -1
  230. package/dist/transaction/auth/index.d.ts +162 -0
  231. package/dist/transaction/auth/index.js +304 -0
  232. package/dist/{auth → transaction/auth}/schemas.d.ts +1 -1
  233. package/dist/{auth → transaction/auth}/schemas.js +13 -13
  234. package/dist/{client → transaction/auth}/sessionMint.d.ts +8 -8
  235. package/dist/{client → transaction/auth}/sessionMint.js +4 -7
  236. package/dist/transaction/coordination/awaitClaimGrant.d.ts +49 -0
  237. package/dist/transaction/coordination/awaitClaimGrant.js +112 -0
  238. package/dist/transaction/coordination/claimMeta.d.ts +49 -0
  239. package/dist/transaction/coordination/claimMeta.js +52 -0
  240. package/dist/transaction/coordination/createClaimStream.d.ts +64 -0
  241. package/dist/transaction/coordination/createClaimStream.js +475 -0
  242. package/dist/transaction/coordination/events.d.ts +74 -0
  243. package/dist/transaction/coordination/events.js +7 -0
  244. package/dist/transaction/coordination/index.d.ts +19 -0
  245. package/dist/transaction/coordination/index.js +44 -0
  246. package/dist/transaction/coordination/locator.d.ts +83 -0
  247. package/dist/transaction/coordination/locator.js +82 -0
  248. package/dist/transaction/coordination/schema.d.ts +1473 -0
  249. package/dist/{coordination → transaction/coordination}/schema.js +490 -55
  250. package/dist/transaction/coordination/targetConflict.d.ts +2 -0
  251. package/dist/transaction/coordination/targetConflict.js +103 -0
  252. package/dist/{coordination → transaction/coordination}/trace.d.ts +7 -18
  253. package/dist/{coordination → transaction/coordination}/trace.js +18 -25
  254. package/dist/transaction/durableWrites.d.ts +62 -0
  255. package/dist/{client → transaction}/durableWrites.js +28 -3
  256. package/dist/transaction/environment.d.ts +105 -0
  257. package/dist/transaction/environment.js +108 -0
  258. package/dist/{errorCodes.d.ts → transaction/errorCodes.d.ts} +11 -11
  259. package/dist/{errorCodes.js → transaction/errorCodes.js} +35 -12
  260. package/dist/{errors.d.ts → transaction/errors.d.ts} +37 -13
  261. package/dist/{errors.js → transaction/errors.js} +85 -16
  262. package/dist/transaction/index.d.ts +20 -0
  263. package/dist/transaction/index.js +20 -0
  264. package/dist/transaction/keys/index.d.ts +87 -0
  265. package/dist/transaction/keys/index.js +207 -0
  266. package/dist/transaction/log/syncDeltaRow.d.ts +158 -0
  267. package/dist/transaction/log/syncDeltaRow.js +95 -0
  268. package/dist/{sync/syncPosition.d.ts → transaction/logPosition.d.ts} +22 -8
  269. package/dist/{sync/syncPosition.js → transaction/logPosition.js} +15 -6
  270. package/dist/transaction/logger.d.ts +16 -0
  271. package/dist/transaction/logger.js +7 -0
  272. package/dist/transaction/observability.d.ts +53 -0
  273. package/dist/transaction/observability.js +19 -0
  274. package/dist/transaction/plugin.d.ts +192 -0
  275. package/dist/transaction/plugin.js +87 -0
  276. package/dist/{policy → transaction/policy}/types.d.ts +3 -3
  277. package/dist/{policy → transaction/policy}/types.js +2 -0
  278. package/dist/transaction/resources/httpResources.d.ts +266 -0
  279. package/dist/transaction/resources/httpResources.js +7 -0
  280. package/dist/transaction/resources/modelOperations.d.ts +319 -0
  281. package/dist/transaction/resources/modelOperations.js +12 -0
  282. package/dist/transaction/resources/mutationOptions.d.ts +66 -0
  283. package/dist/transaction/resources/mutationOptions.js +9 -0
  284. package/dist/transaction/resources/where.d.ts +85 -0
  285. package/dist/transaction/resources/where.js +70 -0
  286. package/dist/{client → transaction/resources}/writeOptionsSchema.d.ts +2 -6
  287. package/dist/{client → transaction/resources}/writeOptionsSchema.js +9 -5
  288. package/dist/{schema → transaction/schema}/field.d.ts +5 -5
  289. package/dist/{schema → transaction/schema}/field.js +5 -5
  290. package/dist/transaction/schema/loadStrategy.d.ts +45 -0
  291. package/dist/transaction/schema/loadStrategy.js +46 -0
  292. package/dist/{schema → transaction/schema}/model.d.ts +50 -35
  293. package/dist/{schema → transaction/schema}/model.js +30 -20
  294. package/dist/transaction/schema/openapi.d.ts +57 -0
  295. package/dist/transaction/schema/openapi.js +340 -0
  296. package/dist/{schema → transaction/schema}/relation.d.ts +14 -14
  297. package/dist/{schema → transaction/schema}/relation.js +7 -7
  298. package/dist/{schema → transaction/schema}/residency.d.ts +0 -9
  299. package/dist/{schema → transaction/schema}/residency.js +0 -5
  300. package/dist/{schema → transaction/schema}/roles.d.ts +5 -5
  301. package/dist/{schema → transaction/schema}/roles.js +5 -5
  302. package/dist/{schema → transaction/schema}/schema.d.ts +12 -10
  303. package/dist/{schema → transaction/schema}/schema.js +4 -3
  304. package/dist/{schema → transaction/schema}/tenancy.d.ts +1 -1
  305. package/dist/{schema → transaction/schema}/tenancy.js +7 -4
  306. package/dist/transaction/transactionLayer.d.ts +82 -0
  307. package/dist/transaction/transactionLayer.js +24 -0
  308. package/dist/{transactions → transaction/transactions/settlement}/commitEnvelope.d.ts +4 -5
  309. package/dist/{transactions → transaction/transactions/settlement}/commitEnvelope.js +9 -13
  310. package/dist/{transactions → transaction/transactions/settlement}/httpCommitEnvelope.d.ts +9 -2
  311. package/dist/{transactions → transaction/transactions/settlement}/httpCommitEnvelope.js +5 -9
  312. package/dist/{transactions/durableWriteStore.d.ts → transaction/transactions/settlement/pendingWrite.d.ts} +10 -36
  313. package/dist/transaction/transactions/settlement/pendingWrite.js +20 -0
  314. package/dist/transaction/transport/commitFrames.d.ts +90 -0
  315. package/dist/transaction/transport/commitFrames.js +134 -0
  316. package/dist/transaction/transport/connectionManager.d.ts +215 -0
  317. package/dist/transaction/transport/connectionManager.js +673 -0
  318. package/dist/transaction/transport/credentialLifecycle.d.ts +177 -0
  319. package/dist/transaction/transport/credentialLifecycle.js +324 -0
  320. package/dist/{sync → transaction/transport}/heartbeat.d.ts +3 -1
  321. package/dist/{sync → transaction/transport}/heartbeat.js +6 -4
  322. package/dist/{client → transaction/transport}/httpClient.d.ts +59 -16
  323. package/dist/{client → transaction/transport}/httpClient.js +5 -5
  324. package/dist/transaction/transport/httpOptions.d.ts +33 -0
  325. package/dist/transaction/transport/httpOptions.js +12 -0
  326. package/dist/{client → transaction/transport}/httpTransport.js +171 -85
  327. package/dist/{sync/NetworkProbe.d.ts → transaction/transport/networkProbe.d.ts} +7 -4
  328. package/dist/{sync/NetworkProbe.js → transaction/transport/networkProbe.js} +14 -13
  329. package/dist/transaction/transport/wsFrameHandlers.d.ts +128 -0
  330. package/dist/transaction/transport/wsFrameHandlers.js +429 -0
  331. package/dist/transaction/transport/wsTransport.d.ts +576 -0
  332. package/dist/transaction/transport/wsTransport.js +1017 -0
  333. package/dist/transaction/types/assertExact.d.ts +17 -0
  334. package/dist/transaction/types/assertExact.js +1 -0
  335. package/dist/{types → transaction/types}/global.d.ts +17 -2
  336. package/dist/{types → transaction/types}/global.js +2 -1
  337. package/dist/{types → transaction/types}/index.d.ts +14 -46
  338. package/dist/{types → transaction/types}/index.js +7 -16
  339. package/dist/{types → transaction/types}/streams.d.ts +63 -45
  340. package/dist/{utils → transaction/utils}/json.d.ts +18 -0
  341. package/dist/transaction/utils/json.js +276 -0
  342. package/dist/transaction/wire/accountResponses.d.ts +351 -0
  343. package/dist/transaction/wire/accountResponses.js +255 -0
  344. package/dist/transaction/wire/auth.d.ts +49 -0
  345. package/dist/transaction/wire/auth.js +57 -0
  346. package/dist/transaction/wire/claimEvent.d.ts +76 -0
  347. package/dist/transaction/wire/claimEvent.js +73 -0
  348. package/dist/transaction/wire/claims.d.ts +463 -0
  349. package/dist/transaction/wire/claims.js +229 -0
  350. package/dist/{wire → transaction/wire}/commit.d.ts +125 -193
  351. package/dist/{wire → transaction/wire}/commit.js +68 -47
  352. package/dist/{wire → transaction/wire}/delta.d.ts +66 -17
  353. package/dist/{wire → transaction/wire}/delta.js +37 -13
  354. package/dist/transaction/wire/errorEnvelope.d.ts +72 -0
  355. package/dist/{wire → transaction/wire}/errorEnvelope.js +36 -5
  356. package/dist/transaction/wire/feedCursor.d.ts +60 -0
  357. package/dist/transaction/wire/feedCursor.js +82 -0
  358. package/dist/transaction/wire/feedEvent.d.ts +177 -0
  359. package/dist/transaction/wire/feedEvent.js +39 -0
  360. package/dist/transaction/wire/frames.d.ts +194 -0
  361. package/dist/transaction/wire/frames.js +50 -0
  362. package/dist/transaction/wire/inboundFrames.d.ts +552 -0
  363. package/dist/transaction/wire/inboundFrames.js +116 -0
  364. package/dist/transaction/wire/index.d.ts +50 -0
  365. package/dist/transaction/wire/index.js +74 -0
  366. package/dist/{wire → transaction/wire}/listEnvelope.d.ts +13 -14
  367. package/dist/transaction/wire/listEnvelope.js +42 -0
  368. package/dist/transaction/wire/modelResponses.d.ts +85 -0
  369. package/dist/transaction/wire/modelResponses.js +43 -0
  370. package/dist/transactions/{TransactionQueue.d.ts → mutations/MutationQueue.d.ts} +79 -38
  371. package/dist/transactions/{TransactionQueue.js → mutations/MutationQueue.js} +110 -59
  372. package/dist/transactions/{TransactionStore.d.ts → mutations/MutationStore.d.ts} +8 -8
  373. package/dist/transactions/{TransactionStore.js → mutations/MutationStore.js} +2 -2
  374. package/dist/transactions/{coalesceRules.d.ts → mutations/coalesceRules.d.ts} +10 -10
  375. package/dist/transactions/{coalesceRules.js → mutations/coalesceRules.js} +1 -1
  376. package/dist/transactions/mutations/commitLatency.d.ts +52 -0
  377. package/dist/transactions/mutations/commitLatency.js +130 -0
  378. package/dist/transactions/{commitOutboxStore.d.ts → mutations/commitOutboxStore.d.ts} +1 -5
  379. package/dist/transactions/{commitOutboxStore.js → mutations/commitOutboxStore.js} +1 -1
  380. package/dist/transactions/{commitPayload.d.ts → mutations/commitPayload.d.ts} +16 -15
  381. package/dist/transactions/{commitPayload.js → mutations/commitPayload.js} +12 -12
  382. package/dist/transactions/{deltaConfirmation.d.ts → mutations/deltaConfirmation.d.ts} +11 -11
  383. package/dist/transactions/{deltaConfirmation.js → mutations/deltaConfirmation.js} +7 -7
  384. package/dist/transactions/mutations/durableWriteStore.d.ts +14 -0
  385. package/dist/transactions/mutations/durableWriteStore.js +12 -0
  386. package/dist/transactions/{optimisticApply.d.ts → mutations/optimisticApply.d.ts} +7 -7
  387. package/dist/transactions/{replayValidation.d.ts → mutations/replayValidation.d.ts} +3 -3
  388. package/dist/transactions/{replayValidation.js → mutations/replayValidation.js} +4 -3
  389. package/dist/utils/mobxSetup.d.ts +1 -1
  390. package/dist/utils/mobxSetup.js +5 -2
  391. package/dist/webhooks/events.d.ts +2 -2
  392. package/dist/wire/index.d.ts +1 -34
  393. package/dist/wire/index.js +8 -49
  394. package/docs/agent-messaging.md +3 -3
  395. package/docs/agents.md +19 -12
  396. package/docs/api-keys.md +8 -4
  397. package/docs/api.md +22 -18
  398. package/docs/audit.md +2 -0
  399. package/docs/cli.md +31 -3
  400. package/docs/client-behavior.md +8 -6
  401. package/docs/concurrency-convention.md +30 -24
  402. package/docs/coordination.md +48 -38
  403. package/docs/data-sources.md +3 -1
  404. package/docs/debugging.md +5 -3
  405. package/docs/deployment.md +267 -0
  406. package/docs/examples/agent-human.md +49 -42
  407. package/docs/examples/ai-sdk-tool.md +69 -44
  408. package/docs/examples/existing-python-backend.md +8 -6
  409. package/docs/examples/nextjs.md +129 -47
  410. package/docs/examples/scoped-agent.md +45 -44
  411. package/docs/examples/server-agent.md +46 -26
  412. package/docs/groups.md +32 -29
  413. package/docs/guarantees.md +4 -2
  414. package/docs/how-it-works.md +9 -7
  415. package/docs/idempotency.md +126 -0
  416. package/docs/identity.md +58 -54
  417. package/docs/index.md +172 -86
  418. package/docs/integration-guide.md +17 -16
  419. package/docs/interaction-model.md +6 -4
  420. package/docs/mcp.md +41 -16
  421. package/docs/migration.md +63 -5
  422. package/docs/operating-on-your-database.md +3 -1
  423. package/docs/projects.md +2 -0
  424. package/docs/quickstart.md +22 -5
  425. package/docs/react.md +12 -10
  426. package/docs/schema-contract.md +5 -3
  427. package/docs/session-settings.md +108 -0
  428. package/docs/sessions.md +3 -1
  429. package/docs/webhooks.md +3 -1
  430. package/llms.txt +47 -17
  431. package/package.json +10 -8
  432. package/dist/agent/Agent.d.ts +0 -366
  433. package/dist/agent/Agent.js +0 -514
  434. package/dist/agent/index.d.ts +0 -115
  435. package/dist/agent/index.js +0 -128
  436. package/dist/agent/session.d.ts +0 -93
  437. package/dist/agent/session.js +0 -149
  438. package/dist/agent/types.d.ts +0 -68
  439. package/dist/agent/types.js +0 -9
  440. package/dist/client/durableWrites.d.ts +0 -21
  441. package/dist/coordination/schema.d.ts +0 -722
  442. package/dist/schema/openapi.d.ts +0 -29
  443. package/dist/schema/openapi.js +0 -124
  444. package/dist/transactions/durableWriteStore.js +0 -30
  445. package/dist/utils/json.js +0 -88
  446. package/dist/wire/errorEnvelope.d.ts +0 -55
  447. package/dist/wire/frames.d.ts +0 -197
  448. package/dist/wire/frames.js +0 -49
  449. package/dist/wire/listEnvelope.js +0 -18
  450. /package/dist/{client → transaction/auth}/credentialEndpoint.d.ts +0 -0
  451. /package/dist/{client → transaction/auth}/credentialEndpoint.js +0 -0
  452. /package/dist/{auth → transaction/auth}/credentialPolicy.d.ts +0 -0
  453. /package/dist/{auth → transaction/auth}/credentialPolicy.js +0 -0
  454. /package/dist/{auth → transaction/auth}/credentialSource.js +0 -0
  455. /package/dist/{client → transaction/auth}/hostedEndpoints.d.ts +0 -0
  456. /package/dist/{client → transaction/auth}/hostedEndpoints.js +0 -0
  457. /package/dist/{client → transaction/coordination}/claimHeartbeatLoop.d.ts +0 -0
  458. /package/dist/{client → transaction/coordination}/claimHeartbeatLoop.js +0 -0
  459. /package/dist/{client → transaction}/persistence.d.ts +0 -0
  460. /package/dist/{client → transaction}/persistence.js +0 -0
  461. /package/dist/{client → transaction/resources}/functionalUpdate.d.ts +0 -0
  462. /package/dist/{client → transaction/resources}/functionalUpdate.js +0 -0
  463. /package/dist/{transactions → transaction/transactions/settlement}/idempotencyKey.d.ts +0 -0
  464. /package/dist/{transactions → transaction/transactions/settlement}/idempotencyKey.js +0 -0
  465. /package/dist/{client → transaction/transport}/httpTransport.d.ts +0 -0
  466. /package/dist/{types → transaction/types}/modelData.d.ts +0 -0
  467. /package/dist/{types → transaction/types}/modelData.js +0 -0
  468. /package/dist/{types → transaction/types}/participant.d.ts +0 -0
  469. /package/dist/{types → transaction/types}/participant.js +0 -0
  470. /package/dist/{types → transaction/types}/streams.js +0 -0
  471. /package/dist/{utils → transaction/utils}/asyncIterator.d.ts +0 -0
  472. /package/dist/{utils → transaction/utils}/asyncIterator.js +0 -0
  473. /package/dist/{utils → transaction/utils}/duration.d.ts +0 -0
  474. /package/dist/{utils → transaction/utils}/duration.js +0 -0
  475. /package/dist/{wire → transaction/wire}/bootstrapReason.d.ts +0 -0
  476. /package/dist/{wire → transaction/wire}/bootstrapReason.js +0 -0
  477. /package/dist/{wire → transaction/wire}/protocol.d.ts +0 -0
  478. /package/dist/{wire → transaction/wire}/protocol.js +0 -0
  479. /package/dist/{wire → transaction/wire}/protocolVersion.d.ts +0 -0
  480. /package/dist/{wire → transaction/wire}/protocolVersion.js +0 -0
  481. /package/dist/transactions/{UnconfirmedWrites.d.ts → mutations/UnconfirmedWrites.d.ts} +0 -0
  482. /package/dist/transactions/{UnconfirmedWrites.js → mutations/UnconfirmedWrites.js} +0 -0
  483. /package/dist/transactions/{optimisticApply.js → mutations/optimisticApply.js} +0 -0
@@ -1,12 +1,15 @@
1
1
  # Coordination Reference
2
2
 
3
+ > Claim mechanics and the API behind them: who holds a row, who is waiting, and how the line moves.
4
+
3
5
  > **Governing convention:** [`concurrency-convention.md`](./concurrency-convention.md)
4
6
  > — the non-coercion principle (surface state, let the actor decide), the full
5
- > `onStale` taxonomy, the read-set (`reads[]`), and the boundaries. Read that for
6
- > the *why* and the contract; this reference is the *how* (claim mechanics + API).
7
+ > `onStale` taxonomy, the batch premise (`reads[]`), and the boundaries. Read
8
+ > that for the *why* and the contract; this reference is the *how* (claim
9
+ > mechanics + API).
7
10
 
8
- Coordinate long-running work on a row so humans and agents don't clobber each
9
- other. Most writes need none of this — a plain `ablo.<model>.update({ id, data })`
11
+ Coordinate long-running work on a row so agents and the people watching them —
12
+ don't clobber each other. Most writes need none of this — a plain `ablo.<model>.update({ id, data })`
10
13
  is **last-write-wins** by default.
11
14
 
12
15
  > **Read-modify-write under contention? Use the functional update — it owns all
@@ -128,46 +131,53 @@ disposition once, in the schema, so every commit to that model is governed
128
131
  without per-call wiring. This is the third coordination axis — orthogonal to
129
132
  `policy` (who may read a row) and `groups` (which delta channels it fans into).
130
133
 
131
- Add a `conflict` map to `model(...)`, keyed by the **committer's** participant
132
- kind (`user` / `agent` / `system`), with the same `onStale` vocabulary as values:
133
-
134
- | value | meaning |
135
- |---|---|
136
- | `'overwrite'` | the write wins; that committer is never blocked. |
137
- | `'reject'` | the write is refused; that committer yields to a held claim / stale snapshot. |
138
- | `'notify'` | hold the write and hand back the current value so the committer re-reads and re-applies (stale writes only). |
134
+ Set a model's `conflict` stance with `coordination`, naming one rule per kind of
135
+ committer:
139
136
 
140
137
  ```ts
141
- import { model, field } from '@abloatai/ablo/schema';
142
-
143
- export const card = model('card', {
144
- title: field.string(),
145
- }, {
146
- // "a human's edit always wins (never blocked); an agent yields"
147
- conflict: { user: 'overwrite', agent: 'reject' },
148
- });
138
+ import { coordination, model, z } from '@abloatai/ablo/schema';
139
+
140
+ export const cards = model(
141
+ {
142
+ title: z.string(),
143
+ },
144
+ {
145
+ // "a human's edit always wins (never blocked); an agent yields"
146
+ conflict: coordination.humansOverwrite().agentsReject(),
147
+ }
148
+ );
149
149
  ```
150
150
 
151
- ### Composable helpers
151
+ Each rule pairs a committer with a disposition, drawn from the same `onStale`
152
+ vocabulary the write guards use:
152
153
 
153
- For the same map with an authoring surface that reads like the rest of the DSL,
154
- use the disposition helpers and the `coordination(...)` combinator (a `cn`/`cx`
155
- for conflict policy later rules win on key collisions):
154
+ | disposition | meaning |
155
+ |---|---|
156
+ | `overwrite` | the write wins; that committer is never blocked. |
157
+ | `reject` | the write is refused; that committer yields to a held claim / stale snapshot. |
158
+ | `notify` | hold the write and hand back the current value so the committer re-reads and re-applies (stale writes only). |
159
+
160
+ That gives nine rules — `humansOverwrite` / `humansReject` / `humansNotify`,
161
+ `agentsOverwrite` / `agentsReject` / `agentsNotify`, `systemOverwrite` /
162
+ `systemReject` / `systemNotify` — and a chain may name as many as it needs. A
163
+ kind left unnamed falls through to the engine default, and a kind named twice
164
+ takes the later rule.
165
+
166
+ When the rules are assembled at runtime rather than written out, each one is
167
+ also a standalone function, and `coordination()` merges them:
156
168
 
157
169
  ```ts
158
- import { model, field, coordination, humansOverwrite, agentsReject } from '@abloatai/ablo/schema';
170
+ import { coordination, humansOverwrite, agentsReject } from '@abloatai/ablo/schema';
159
171
 
160
- export const card = model('card', {
161
- title: field.string(),
162
- }, {
163
- conflict: coordination(humansOverwrite(), agentsReject()),
164
- // → { user: 'overwrite', agent: 'reject' }
165
- });
172
+ const stance = coordination(humansOverwrite(), agentsReject());
166
173
  ```
167
174
 
168
- Helpers, one per disposition: `humansOverwrite` / `humansReject` / `humansNotify`,
169
- `agentsOverwrite` / `agentsReject` / `agentsNotify`,
170
- `systemOverwrite` / `systemReject` / `systemNotify`.
175
+ Both forms produce the same thing: a map keyed by the committer's participant
176
+ kind, which is what travels to the server.
177
+
178
+ ```ts
179
+ { user: 'overwrite', agent: 'reject' }
180
+ ```
171
181
 
172
182
  ### How it relates to per-write coordination
173
183
 
@@ -293,7 +303,7 @@ equivalent for when you hold a claim without `await using`.
293
303
  ### Claim-gated reads
294
304
 
295
305
  `claim.state({ id })` always returns immediately. Model reads such as
296
- `ablo.<model>.get(id)` are local reads and stay available while a claim is
306
+ `ablo.<model>.local.retrieve(id)` are local reads and stay available while a claim is
297
307
  held. Server/model reads can choose a claimed policy:
298
308
 
299
309
  ```ts
@@ -546,11 +556,11 @@ snapshot.
546
556
 
547
557
  Reading or claiming a row auto-enrolls you in its sync group, which is enough for
548
558
  `claim.state`/`claim.queue` to observe co-participants. When you want to *hold*
549
- presence on a known set of rows — a deck's slides, a board's cards — and react to
559
+ presence on a known set of rows — a workspace's documents, a board's cards — and react to
550
560
  who joins or leaves, use `join`:
551
561
 
552
562
  ```ts
553
- await using room = await ablo.slides.join(slideIds, { ttl: '5m' });
563
+ await using room = await ablo.documents.join(slideIds, { ttl: '5m' });
554
564
  room.peers; // who else is here, live
555
565
  ```
556
566
 
@@ -627,7 +637,7 @@ inspect the `code`.
627
637
 
628
638
  `AbloStaleContextError.conflicts` lists the `(model, id, observedSyncId)` rows
629
639
  that moved during your generation window — use it for selective regeneration
630
- (re-think only the slides that changed, not the whole deck) and for metrics.
640
+ (re-think only the documents that changed, not the whole workspace) and for metrics.
631
641
 
632
642
  ```ts
633
643
  try {
@@ -1,5 +1,7 @@
1
1
  # Connect Your Database
2
2
 
3
+ > Keep the rows in your own Postgres while Ablo coordinates and confirms every write.
4
+
3
5
  You write through Ablo, and Ablo writes to your Postgres. A call to
4
6
  `ablo.<model>.create / update / delete` enters Ablo's commit chokepoint — where
5
7
  claims, ordering, and idempotency are enforced — and Ablo applies the change to
@@ -180,7 +182,7 @@ await ablo.weatherReports.update({ id: 'report_stockholm', data: { high: 21 } })
180
182
  await ablo.weatherReports.update({ id: 'report_stockholm', data: { high: 21 }, wait: 'confirmed' });
181
183
 
182
184
  // Reads are live off the same stream.
183
- const report = ablo.weatherReports.get('report_stockholm');
185
+ const report = ablo.weatherReports.local.retrieve('report_stockholm');
184
186
  ```
185
187
 
186
188
  A commit is accepted the moment Ablo takes it (`queued`); it becomes `confirmed`
package/docs/debugging.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Debugging & Logs
2
2
 
3
- By default the SDK is quiet — it logs only warnings and errors. When you're building a human + agent flow and want to *see* the coordination happen (who claimed what, who's waiting in line, who got preempted), turn on Ablo's diagnostic logging. Every line is prefixed `[Ablo]` so it's obvious which output is ours in a console full of other tools.
3
+ > Watch claims, queueing, and grants as they happen while you build.
4
+
5
+ By default the SDK is quiet — it logs only warnings and errors. When you're building a multi-agent flow and want to *see* the coordination happen (who claimed what, who's waiting in line, who got preempted), turn on Ablo's diagnostic logging. Every line is prefixed `[Ablo]` so it's obvious which output is ours in a console full of other tools.
4
6
 
5
7
  ## Turn it on
6
8
 
@@ -39,7 +41,7 @@ Precedence: an explicit `logLevel` wins, then `debug: true` (⇒ `debug`), then
39
41
 
40
42
  ## What you'll see — the coordination trace
41
43
 
42
- These lines (all at `info`) let you watch the human + agent handover you built:
44
+ These lines (all at `info`) let you watch the handover you built:
43
45
 
44
46
  ```
45
47
  [Ablo] claim: requesting documents:doc_42 for "editing" (will queue if contended)
@@ -61,7 +63,7 @@ Read it as the lifecycle of one claim:
61
63
 
62
64
  ## Where the logs run
63
65
 
64
- The coordination trace and the proactive credential refresh run **in the browser** (and any client that holds a live socket) — that's where the human + agent activity is. Server-side code that mints credentials or does one-shot reads won't emit the trace; it has no live session to narrate.
66
+ The coordination trace and the proactive credential refresh run **in the browser** (and any client that holds a live socket) — that's where the live coordination activity is. Server-side code that mints credentials or does one-shot reads won't emit the trace; it has no live session to narrate.
65
67
 
66
68
  ## Bring your own logger
67
69
 
@@ -0,0 +1,267 @@
1
+ # Deployment
2
+
3
+ > What production takes: a database Ablo can reach, a key minted for the plane you mean, and a schema push in the deploy.
4
+
5
+ One command answers the question this page exists for — would a write succeed
6
+ right now, and if not, why:
7
+
8
+ ```bash
9
+ ABLO_API_KEY=sk_live_… npx ablo status
10
+ ```
11
+
12
+ ```text
13
+ ablo status
14
+
15
+ key sk_live_51H8… (ABLO_API_KEY env — overrides stored)
16
+ mode production
17
+ org org_3nKq…
18
+ project checkout (prj_7Yb2…)
19
+ acts on production
20
+ ○ sandbox sk_test_9fJd… · expires in 71d
21
+ ● production — no key
22
+ push production with sk_live_51H8… (env)
23
+ api https://api.abloatai.com reachable
24
+ data ✓ database connected to this plane (direct)
25
+ schema 4 models pushed (rev 12) hash 3f9a2c81 @ 2026-07-18
26
+ • orders typename=orders
27
+ • lineItems typename=lineItems
28
+ • fulfilments typename=fulfilments
29
+ • reviews typename=reviews
30
+
31
+ ✓ ready — a write should succeed
32
+ ```
33
+
34
+ `status` asks the routing authority rather than sampling a read, because reads
35
+ resolve while writes are held — a plane with no database connected serves every
36
+ read and refuses every write. The verdict at the bottom is the whole page in one
37
+ line, and `--json` puts the same conclusion in a `blockers` array you can gate a
38
+ deploy on.
39
+
40
+ ## The three ingredients
41
+
42
+ There is no Ablo service for you to deploy. Ablo is hosted, your rows live in
43
+ your own Postgres, and your app runs where it already runs — so a deployment is
44
+ three pieces pointed at the same plane.
45
+
46
+ | Ingredient | Who runs it | What "deploying" means for it |
47
+ |---|---|---|
48
+ | **Your Postgres** | You (or your provider) | Registering it against your production plane, once, with a production key. |
49
+ | **Ablo** | Hosted at `api.abloatai.com` | Nothing to run. You choose a project, a plane, and the keys that reach them. |
50
+ | **Your app and agents** | You | Holding the right credential for the runtime, and pushing the schema in the deploy. |
51
+
52
+ Everything below is those three in order.
53
+
54
+ ### Planes: what a deployment targets
55
+
56
+ A **plane** is the isolation unit a credential acts on. `production` is the root
57
+ plane; every sandbox sits beside it. Three things are per-plane, and knowing
58
+ which three is most of what production readiness means:
59
+
60
+ - **Rows** — a sandbox write is invisible to production and to every other sandbox.
61
+ - **The registered database** — one per plane, so your production database and
62
+ your dev database are separate registrations.
63
+ - **The active schema artifact** — the model shapes the engine actually routes on.
64
+
65
+ A key's plane is fixed at mint and spelled in its prefix: `sk_live_` acts on
66
+ production, `sk_test_` on a sandbox. There is no runtime override — the
67
+ credential *is* the environment selector, which is why application code never
68
+ passes one.
69
+
70
+ One asymmetry is worth carrying into your deploy plan. A sandbox with no schema
71
+ artifact of its own reads **production's**, so a schema pushed to production
72
+ reaches your sandboxes automatically. The reverse does not hold: a push from a
73
+ sandbox key creates a sandbox artifact that shadows production **for that
74
+ sandbox's readers only**, and production keeps running the schema it was last
75
+ pushed. Production gets its models when you push to production.
76
+
77
+ ## 1. The database production writes to
78
+
79
+ Your production database joins Ablo the same way your dev database did — logical
80
+ replication so Ablo can read and confirm, a scoped writer role so Ablo can land
81
+ rows — run once, with a production key so the registration attaches to the
82
+ production plane:
83
+
84
+ ```bash
85
+ ABLO_API_KEY=sk_live_… npx ablo connect apply --url postgres://admin:…@host:5432/db
86
+ ABLO_API_KEY=sk_live_… npx ablo connect check
87
+ ```
88
+
89
+ [Connect Your Database](./data-sources.md) is the full walkthrough — the SQL, the
90
+ two roles, and the complete list of what Ablo touches. Five things about it are
91
+ specifically production concerns:
92
+
93
+ **Your agents do not each hold a connection.** Every agent, worker, and function
94
+ talks to Ablo, and Ablo holds the database connections — at most 4 connections
95
+ per plane, the same 4 whether one caller is writing behind them or ten thousand
96
+ are. They identify themselves as `ablo-direct-writer`, so `pg_stat_activity`
97
+ accounts for everything Ablo has open at any moment. Size the database for that
98
+ number rather than for your agent count.
99
+
100
+ **Register the direct host, not the pooler.** A pooler terminates the session
101
+ that replication needs, and it refuses the connection in the same words a wrong
102
+ password would — so a pooled host reads as a credentials problem for as long as
103
+ you let it. `ablo status` names a pooled host when it sees one, with the direct
104
+ host to use instead.
105
+
106
+ **Reachability is measured from Ablo's network, not yours.** `connect check`
107
+ runs from the infrastructure replication runs on, so an IPv6-only,
108
+ IP-allowlisted, or VPC-private database still verifies — and a database your
109
+ laptop can reach but Ablo cannot fails here rather than at the first write.
110
+
111
+ **`wal_level = logical` needs a restart.** It is server-wide and not reloadable.
112
+ On RDS and Aurora it is a parameter-group change plus a reboot. Schedule it;
113
+ it is the one setup step with downtime in it.
114
+
115
+ **A replication slot retains WAL.** While Ablo is connected the slot holds what
116
+ it has not yet acknowledged, so a long disconnection accumulates disk. Ablo
117
+ monitors slot lag and retention and surfaces it, and drops an abandoned slot
118
+ rather than letting it grow without bound.
119
+
120
+ A database that cannot grant a `REPLICATION` role connects through the signed
121
+ [Data Source endpoint](./data-sources.md) instead. Same model surface, same
122
+ commit chokepoint — it is the marked fallback, so reach for it when replication
123
+ is genuinely unavailable.
124
+
125
+ ## 2. The credential each runtime holds
126
+
127
+ There is one field, `apiKey`, and what goes in it follows from where the code
128
+ runs. In production that resolves to four rows:
129
+
130
+ | Runtime | Credential | Notes |
131
+ |---|---|---|
132
+ | Server, worker, agent, cron | `sk_live_` in `ABLO_API_KEY` | Defaults from the environment, so most code passes nothing. |
133
+ | Serverless function | `sk_live_` in `ABLO_API_KEY`, with `transport: 'http'` | Stateless request/response; nothing held open across invocations. |
134
+ | Browser, read-only | `pk_live_` | Publishable and safe to ship, like a Stripe `pk_`. Reads only. |
135
+ | Browser, writing as the signed-in user | `authEndpoint` | A route on your backend mints a short-lived `ek_` per user. |
136
+
137
+ [API Keys](./api-keys.md) covers the model; [Sessions](./sessions.md) covers
138
+ minting. Two things bite specifically at deploy time.
139
+
140
+ **The live key `ablo login` gives you cannot push schema.** It is a restricted,
141
+ observe-only `rk_live_` by design, so a stolen CLI config cannot write to
142
+ production. A production deploy needs a **secret** `sk_live_` from the dashboard,
143
+ supplied as `ABLO_API_KEY`. You do not have to discover this from a failed
144
+ deploy: `ablo login`, `ablo mode production`, and `ablo status` each name what
145
+ the key in hand does, and `ablo status --json` reports it as `effectiveKey.kind`
146
+ for a pipeline to check before it pushes.
147
+
148
+ **An explicit key always wins.** The CLI resolves `ABLO_API_KEY`, then
149
+ `.env.local`, then `.env`, then the stored login — and `ablo status` prints which
150
+ one it found under `key`, with its source. When a deploy lands somewhere
151
+ surprising, that line is usually the answer.
152
+
153
+ ## 3. Pushing the schema is a deploy step
154
+
155
+ The server keeps its own copy of your schema and routes on that copy. Until it
156
+ has yours, a write to a new model fails with `server_execute_unknown_model` — so
157
+ `ablo push` belongs in your deploy pipeline, ordered **before** the code that
158
+ depends on the new models goes live.
159
+
160
+ ```bash
161
+ ABLO_API_KEY=sk_live_… npx ablo push --yes
162
+ ```
163
+
164
+ Production requires confirmation: interactively you type the destination
165
+ project's name, which is what makes a wrong-project deploy impossible to do by
166
+ reflex. In CI there is no TTY, so `--yes` is the confirmation and a push without
167
+ it stops rather than proceeding unattended.
168
+
169
+ **Additive changes pass; destructive ones ask.** Adding a model or an optional
170
+ field applies cleanly. Dropping a model or a field, narrowing an enum, or a lossy
171
+ cast is classified as data loss and needs `--force`; adding a required field to a
172
+ populated table needs a `--backfill`. A push that fails is recorded `failed` and
173
+ never activated, so a broken migration cannot leave clients gated against tables
174
+ that do not match.
175
+
176
+ This is the same expand-and-contract shape any online migration has, and it
177
+ sequences the same way: push the additive change, deploy the code that writes
178
+ both shapes, backfill, then push the removal in a later deploy once nothing reads
179
+ the old field.
180
+
181
+ **Drift is a connect-time rejection, not a runtime surprise.** A client built
182
+ against a schema the server is no longer running is turned away when it connects.
183
+ `ablo status` prints the local hash beside the deployed one, and the running
184
+ client reports the same `serverSchemaHash` value, so the two can be matched at a
185
+ glance.
186
+
187
+ ## Gate the deploy on the verdict
188
+
189
+ `ablo status --json` reports the same conclusion the human output ends with, in a
190
+ form a pipeline can act on. An empty `blockers` array is the machine-readable
191
+ form of "ready":
192
+
193
+ ```bash
194
+ blockers=$(ABLO_API_KEY=$ABLO_API_KEY npx ablo status --json | jq '.blockers | length')
195
+ [ "$blockers" -eq 0 ] || { npx ablo status; exit 1; }
196
+ ```
197
+
198
+ Each blocker carries a `problem` and the single `fix` that resolves it, in the
199
+ order you should act on them: an unreachable API makes every other finding
200
+ unverifiable, and a plane with nothing connected makes a schema question
201
+ academic. The JSON also carries `confirmedTarget` — the org, project, and
202
+ environment the server says this key resolves to — which is the authoritative
203
+ answer to where a push would land.
204
+
205
+ ## Webhooks point at the deployed URL
206
+
207
+ `npx ablo dev` forwards commits to your machine while you build, the way
208
+ `stripe listen` does. A deployed endpoint is registered once, and Ablo returns
209
+ the signing secret a single time:
210
+
211
+ ```bash
212
+ ABLO_API_KEY=sk_live_… npx ablo webhooks create https://yourapp.com/api/ablo/[...all]
213
+ ABLO_API_KEY=sk_live_… npx ablo webhooks list # endpoints + delivery health
214
+ ```
215
+
216
+ `webhooks list` reports each endpoint's status, cursor, and last error — the
217
+ place to look when a mirror falls behind. [Webhooks](./webhooks.md) covers the
218
+ handler, the Standard Webhooks signature, and rolling a secret.
219
+
220
+ ## What to watch once it is live
221
+
222
+ - **`ablo logs`** — commit activity as it happens, scoped by the key, so a live
223
+ key streams the org and a test key streams only its sandbox. `--json` emits
224
+ NDJSON for piping.
225
+ - **`ablo status`** — the readiness verdict. Cheap enough to run from a health
226
+ check on your own side.
227
+ - **The [audit log](./audit.md)** — every confirmed write traced back to the key
228
+ that made it and the person who authorized that key.
229
+ - **Your own logger** — pass `logger` to the client and SDK lifecycle, sync,
230
+ retry, and rollback events join your existing pipeline.
231
+
232
+ Writes carry receipts rather than being fire-and-forget: a commit is accepted the
233
+ moment Ablo takes it (`queued`) and becomes `confirmed` once the row appears on
234
+ your database's WAL. [Guarantees](./guarantees.md) covers which state to wait for
235
+ and what each promises.
236
+
237
+ ## When something is wrong
238
+
239
+ | What you see | What it means | The fix |
240
+ |---|---|---|
241
+ | `no database is connected to this plane` | Writes are held rather than routed. Reads still resolve, which is why a read probe stays quiet. | `ablo connect apply` with a key for that plane. |
242
+ | `password authentication failed` during connect | Often a pooled host refusing a session it cannot serve, in the words of a wrong password. | Register the direct database host. |
243
+ | `server_execute_unknown_model` | The plane's active schema does not carry that model. | `ablo push` with a key for that plane. |
244
+ | Clients rejected at connect | The deployed schema and the client's schema disagree. | Push this tree, or deploy the revision the server is running. |
245
+ | `project_scope_denied` (403) | The model belongs to another project in your org. | Use a key minted for that project — a push cannot cross projects. |
246
+ | 403 on `ablo push` | The key authenticated but cannot author schema. | A secret `sk_live_`; the `ablo login` live key is observe-only. |
247
+
248
+ ## The checklist
249
+
250
+ 1. Production database registered against the production plane, direct host, and
251
+ `ablo connect check` all green.
252
+ 2. A secret `sk_live_` in the deploy environment as `ABLO_API_KEY` — never in a
253
+ browser bundle.
254
+ 3. `ablo push --yes` in the pipeline, ahead of the code that needs the new models.
255
+ 4. `ablo status --json` gating the deploy on an empty `blockers` array.
256
+ 5. Browser clients on a `pk_live_` or an `authEndpoint`, not a secret key.
257
+ 6. Webhook endpoints registered at their deployed URLs, with the signing secret
258
+ in your environment.
259
+
260
+ ## Next steps
261
+
262
+ - [Connect Your Database](./data-sources.md) — the setup this page registers, in full.
263
+ - [Projects](./projects.md) — one org, many apps, each with its own planes and keys.
264
+ - [API Keys](./api-keys.md) — which credential each runtime holds, and what it may do.
265
+ - [CLI](./cli.md) — every command, its flags, and the environment variables.
266
+ - [Operating on Your Database](./operating-on-your-database.md) — which actions run freely and which belong to a human.
267
+ - [Debugging & Logs](./debugging.md) — watching claims, queueing, and grants while you build.
@@ -1,15 +1,18 @@
1
1
  # Agent + Human
2
2
 
3
- A report-writing agent that yields when a human is editing the same report.
3
+ > An agent that yields the row when a person is already holding it.
4
+
5
+ A task-writing agent that yields when a person is editing the same task.
4
6
 
5
7
  ## Scenario
6
8
 
7
- The same reports are edited by both humans and agents. They must not collide:
9
+ The same tasks are edited by agents and by the people watching them. They must
10
+ not collide:
8
11
 
9
- - If a human already holds the row, the agent yields instead of fighting for it.
12
+ - If a person already holds the row, the agent yields instead of fighting for it.
10
13
  - While the agent is updating, the UI can show who is active.
11
- - If the report changes mid-run, the commit is rejected instead of overwriting
12
- the human's newer edit.
14
+ - If the task changes mid-run, the commit is rejected instead of overwriting the
15
+ newer edit.
13
16
 
14
17
  A **claim** does both jobs. Claims don't lock — if another writer holds the row,
15
18
  `claim` waits for them, re-reads the fresh row, then hands it back to you on
@@ -21,70 +24,74 @@ a typed error if the row moved underneath you while the agent was busy.
21
24
 
22
25
  ## Schema-Backed Worker
23
26
 
24
- The worker uses the same schema client the app uses. It reads the report from
25
- the server with `retrieve({ id })`, claims the row, and writes through
26
- `ablo.weatherReports.update(...)` with a stale-check so a human's concurrent edit
27
- can't be overwritten.
27
+ The worker uses the same schema client the app uses. It reads the task from the
28
+ server with `retrieve({ id })`, claims the row, and writes through
29
+ `ablo.tasks.update(...)` with a stale-check so a concurrent edit can't be
30
+ overwritten.
28
31
 
29
32
  ```ts
30
33
  import Ablo, { AbloClaimedError, AbloStaleContextError } from '@abloatai/ablo';
31
34
  import { defineSchema, model, z } from '@abloatai/ablo/schema';
32
35
 
33
36
  const schema = defineSchema({
34
- weatherReports: model({
35
- location: z.string(),
36
- status: z.enum(['pending', 'ready']),
37
+ tasks: model({
38
+ title: z.string(),
39
+ status: z.enum(['todo', 'doing', 'done']),
37
40
  }),
38
41
  });
39
42
 
40
- const ablo = Ablo({ schema, apiKey: process.env.ABLO_API_KEY });
43
+ const ablo = Ablo({
44
+ schema,
45
+ apiKey: process.env.ABLO_API_KEY,
46
+ transport: 'http',
47
+ });
41
48
 
42
- export async function markReady(reportId: string) {
49
+ export async function markDone(taskId: string) {
43
50
  await ablo.ready();
44
51
 
45
52
  // retrieve({ id }) is an async server read — await it.
46
- const report = await ablo.weatherReports.retrieve({ id: reportId });
47
- if (!report) return { status: 'not_found' };
53
+ const task = await ablo.tasks.retrieve({ id: taskId });
54
+ if (!task) return { status: 'not_found' };
48
55
 
49
56
  try {
50
- // queue: false → don't queue behind a current holder. If a human already
57
+ // queue: false → don't queue behind a current holder. If someone already
51
58
  // holds the row, claim rejects with AbloClaimedError (caught below), so the
52
59
  // agent yields instead of waiting. Omit it, or pass queue: true, to queue
53
60
  // behind them. description → the label observers see while we work.
54
- await using claim = await ablo.weatherReports.claim({
55
- id: reportId,
61
+ await using claim = await ablo.tasks.claim({
62
+ id: taskId,
56
63
  queue: false,
57
- description: 'marking_ready',
64
+ description: 'marking_done',
58
65
  });
59
- const claimed = claim.data;
66
+ if (claim.data.status === 'done') return { status: 'noop' };
60
67
 
61
68
  // Inside an active claim, `update` is stale-checked automatically: the SDK
62
69
  // attaches the claim's snapshot version as `readAt` and sets
63
70
  // `onStale: 'reject'`. The write below is therefore equivalent to passing
64
71
  // those options yourself:
65
72
  //
66
- // ablo.weatherReports.update({
67
- // id: claimed.id,
68
- // data: { status: 'ready' },
73
+ // ablo.tasks.update({
74
+ // id: claim.data.id,
75
+ // data: { status: 'done' },
69
76
  // wait: 'confirmed',
70
77
  // readAt: <claim snapshot version>,
71
78
  // onStale: 'reject',
72
79
  // });
73
80
  //
74
- // If a human saved a newer version mid-run, the row no longer matches
75
- // `readAt`, so the server rejects this commit with AbloStaleContextError
76
- // (caught below) instead of clobbering their edit.
77
- const updated = await ablo.weatherReports.update({
78
- id: claimed.id,
79
- data: { status: 'ready' },
81
+ // If a newer version landed mid-run, the row no longer matches `readAt`, so
82
+ // the server rejects this commit with AbloStaleContextError (caught below)
83
+ // instead of clobbering that edit.
84
+ const updated = await ablo.tasks.update({
85
+ id: claim.data.id,
86
+ data: { status: 'done' },
80
87
  wait: 'confirmed',
81
88
  });
82
89
 
83
- return { status: 'ready', report: updated };
90
+ return { status: 'done', task: updated };
84
91
  } catch (err) {
85
- // A human already holds the row — yield this run and let them finish.
92
+ // Someone already holds the row — yield this run and let them finish.
86
93
  if (err instanceof AbloClaimedError) return { status: 'yielded' };
87
- // A human saved a newer version while we held the claim. The stale-check
94
+ // A newer version was saved while we held the claim. The stale-check
88
95
  // rejected our commit, so nothing was overwritten — re-run on fresh data.
89
96
  if (err instanceof AbloStaleContextError) return { status: 'stale' };
90
97
  throw err;
@@ -101,14 +108,14 @@ Keep workers on the same schema-backed client as the app.
101
108
 
102
109
  import { useAblo } from '@abloatai/ablo/react';
103
110
 
104
- export function ReportRow({ report: serverReport }: Props) {
105
- const data = useAblo((ablo) => ablo.weatherReports.get(serverReport.id)) ?? serverReport;
106
- const active = useAblo((ablo) => ablo.weatherReports.claim.state({ id: serverReport.id }));
107
- const agentActive = active?.participantKind === 'agent';
111
+ export function TaskRow({ task: serverTask }: Props) {
112
+ const data = useAblo((ablo) => ablo.tasks.local.retrieve(serverTask.id)) ?? serverTask;
113
+ const holder = useAblo((ablo) => ablo.tasks.claim.state({ id: serverTask.id }));
114
+ const agentActive = holder?.participantKind === 'agent';
108
115
 
109
116
  return (
110
117
  <div>
111
- <span>{data.location}</span>
118
+ <span>{data.title}</span>
112
119
  {agentActive ? <span>Agent is updating...</span> : null}
113
120
  </div>
114
121
  );
@@ -120,9 +127,9 @@ export function ReportRow({ report: serverReport }: Props) {
120
127
  - The claim is visible to everyone: the UI reads it synchronously with
121
128
  `claim.state({ id })`, and it also arrives over the live stream.
122
129
  - `claim({ id })` makes writers take turns instead of racing — with
123
- `queue: false`, the agent simply yields when a human already holds the row.
124
- - The `update` made while the claim is held is stale-checked automatically, so a human's
130
+ `queue: false`, the agent simply yields when someone already holds the row.
131
+ - The `update` made while the claim is held is stale-checked automatically, so an
125
132
  edit landing mid-run rejects the agent's write with a typed
126
133
  `AbloStaleContextError` instead of overwriting it.
127
- - That same write carries the claim, so each accepted change is attributed to
128
- the run that made it.
134
+ - That same write carries the claim, so each accepted change is attributed to the
135
+ run that made it.