@abloatai/ablo 0.34.1 → 0.36.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 (536) hide show
  1. package/AGENTS.md +2 -1
  2. package/CHANGELOG.md +758 -5
  3. package/README.md +56 -502
  4. package/bin/ablo.cjs +39 -0
  5. package/dist/BaseSyncedStore.d.ts +176 -48
  6. package/dist/BaseSyncedStore.js +346 -214
  7. package/dist/Database.d.ts +17 -44
  8. package/dist/Database.js +96 -79
  9. package/dist/InstanceCache.d.ts +31 -6
  10. package/dist/InstanceCache.js +65 -30
  11. package/dist/LazyReferenceCollection.d.ts +3 -3
  12. package/dist/LazyReferenceCollection.js +4 -4
  13. package/dist/Model.d.ts +23 -13
  14. package/dist/Model.js +27 -17
  15. package/dist/ModelRegistry.d.ts +8 -4
  16. package/dist/ModelRegistry.js +20 -18
  17. package/dist/NetworkMonitor.d.ts +3 -1
  18. package/dist/NetworkMonitor.js +7 -5
  19. package/dist/{SyncEngineContext.d.ts → RuntimeContext.d.ts} +20 -13
  20. package/dist/{SyncEngineContext.js → RuntimeContext.js} +11 -12
  21. package/dist/SyncClient.d.ts +47 -47
  22. package/dist/SyncClient.js +215 -156
  23. package/dist/ai-sdk/coordinatedTool.d.ts +2 -2
  24. package/dist/ai-sdk/coordinatedTool.js +1 -1
  25. package/dist/ai-sdk/coordinationContext.d.ts +2 -2
  26. package/dist/ai-sdk/coordinationContext.js +1 -1
  27. package/dist/ai-sdk/wrap.d.ts +3 -3
  28. package/dist/ai-sdk/wrap.js +2 -2
  29. package/dist/auth/index.d.ts +1 -156
  30. package/dist/auth/index.js +8 -301
  31. package/dist/client/Ablo.d.ts +42 -287
  32. package/dist/client/Ablo.js +129 -963
  33. package/dist/client/abloClient.d.ts +309 -0
  34. package/dist/client/abloClient.js +13 -0
  35. package/dist/client/clientPrelude.d.ts +52 -0
  36. package/dist/client/clientPrelude.js +60 -0
  37. package/dist/client/consoleLogger.d.ts +2 -2
  38. package/dist/client/coreClient.d.ts +60 -0
  39. package/dist/client/coreClient.js +118 -0
  40. package/dist/client/createInternalComponents.d.ts +8 -4
  41. package/dist/client/createInternalComponents.js +17 -10
  42. package/dist/client/createModelProxy.d.ts +98 -373
  43. package/dist/client/createModelProxy.js +233 -139
  44. package/dist/client/humans.d.ts +69 -0
  45. package/dist/client/humans.js +78 -0
  46. package/dist/client/modelRegistration.d.ts +1 -1
  47. package/dist/client/modelRegistration.js +9 -9
  48. package/dist/client/options.d.ts +73 -17
  49. package/dist/client/reactiveEngine.d.ts +53 -0
  50. package/dist/client/reactiveEngine.js +688 -0
  51. package/dist/client/resourceTypes.d.ts +9 -250
  52. package/dist/client/resourceTypes.js +8 -5
  53. package/dist/client/schemaConfig.d.ts +4 -4
  54. package/dist/client/schemaConfig.js +6 -2
  55. package/dist/client/storeCluster.d.ts +47 -0
  56. package/dist/client/storeCluster.js +118 -0
  57. package/dist/client/storeLifecycle.d.ts +61 -0
  58. package/dist/client/storeLifecycle.js +231 -0
  59. package/dist/client/validateAbloOptions.d.ts +3 -2
  60. package/dist/client/validateAbloOptions.js +1 -1
  61. package/dist/client/wsMutationExecutor.d.ts +3 -3
  62. package/dist/client/wsMutationExecutor.js +3 -3
  63. package/dist/context.d.ts +22 -9
  64. package/dist/context.js +33 -9
  65. package/dist/coordination/ClaimLog.d.ts +26 -0
  66. package/dist/coordination/ClaimLog.js +32 -0
  67. package/dist/coordination/index.d.ts +1 -15
  68. package/dist/coordination/index.js +8 -31
  69. package/dist/core/index.d.ts +3 -3
  70. package/dist/core/index.js +2 -2
  71. package/dist/docs/catalog.d.ts +72 -0
  72. package/dist/docs/catalog.js +230 -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 +44 -36
  78. package/dist/index.js +30 -22
  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 +5 -2
  99. package/dist/query/client.js +10 -9
  100. package/dist/query/types.d.ts +6 -41
  101. package/dist/query/types.js +2 -2
  102. package/dist/react/AbloProvider.d.ts +18 -8
  103. package/dist/react/AbloProvider.js +10 -9
  104. package/dist/react/context.d.ts +3 -3
  105. package/dist/react/context.js +1 -1
  106. package/dist/react/createAbloReact.d.ts +56 -0
  107. package/dist/react/createAbloReact.js +51 -0
  108. package/dist/react/index.d.ts +6 -5
  109. package/dist/react/index.js +6 -3
  110. package/dist/react/internalContext.d.ts +1 -1
  111. package/dist/react/useAblo.d.ts +12 -5
  112. package/dist/react/useAblo.js +26 -8
  113. package/dist/react/useCurrentUserId.js +1 -1
  114. package/dist/react/useErrorListener.js +1 -1
  115. package/dist/react/useMutationFailureListener.d.ts +2 -2
  116. package/dist/react/useMutationFailureListener.js +1 -1
  117. package/dist/react/useMutators.d.ts +3 -3
  118. package/dist/react/useMutators.js +3 -3
  119. package/dist/react/useUndoScope.d.ts +5 -5
  120. package/dist/react/useUndoScope.js +1 -1
  121. package/dist/schema/coordination.d.ts +69 -10
  122. package/dist/schema/coordination.js +90 -9
  123. package/dist/schema/ddl.js +2 -2
  124. package/dist/schema/diff.d.ts +1 -1
  125. package/dist/schema/generate.js +1 -1
  126. package/dist/schema/index.d.ts +11 -10
  127. package/dist/schema/index.js +22 -18
  128. package/dist/schema/queries.d.ts +27 -27
  129. package/dist/schema/queries.js +23 -23
  130. package/dist/schema/select.d.ts +3 -3
  131. package/dist/schema/select.js +6 -3
  132. package/dist/schema/serialize.d.ts +15 -6
  133. package/dist/schema/serialize.js +20 -3
  134. package/dist/schema/sugar.d.ts +6 -7
  135. package/dist/schema/sugar.js +9 -12
  136. package/dist/schema/syncDeltaRow.d.ts +4 -152
  137. package/dist/schema/syncDeltaRow.js +4 -105
  138. package/dist/server/adapter.d.ts +18 -1
  139. package/dist/server/commit.d.ts +10 -16
  140. package/dist/server/index.d.ts +1 -1
  141. package/dist/server/index.js +1 -1
  142. package/dist/server/readConfig.d.ts +1 -1
  143. package/dist/source/adapter.d.ts +7 -5
  144. package/dist/source/adapter.js +7 -5
  145. package/dist/source/adapters/drizzle.d.ts +1 -1
  146. package/dist/source/adapters/drizzle.js +2 -2
  147. package/dist/source/adapters/kysely.d.ts +1 -1
  148. package/dist/source/adapters/kysely.js +1 -1
  149. package/dist/source/adapters/kyselyMutationCore.d.ts +1 -1
  150. package/dist/source/adapters/kyselyMutationCore.js +2 -2
  151. package/dist/source/adapters/memory.js +1 -1
  152. package/dist/source/adapters/prisma.d.ts +8 -3
  153. package/dist/source/adapters/prisma.js +1 -1
  154. package/dist/source/connector.js +1 -1
  155. package/dist/source/connectorProtocol.d.ts +2 -8
  156. package/dist/source/connectorProtocol.js +3 -2
  157. package/dist/source/contract.d.ts +29 -17
  158. package/dist/source/contract.js +27 -22
  159. package/dist/source/factory.d.ts +1 -1
  160. package/dist/source/idempotency.js +2 -2
  161. package/dist/source/index.d.ts +1 -0
  162. package/dist/source/index.js +3 -0
  163. package/dist/source/next.d.ts +1 -1
  164. package/dist/source/signing.d.ts +9 -2
  165. package/dist/source/signing.js +4 -1
  166. package/dist/source/types.d.ts +6 -4
  167. package/dist/source/types.js +1 -1
  168. package/dist/{core/storeContract.d.ts → storeContract.d.ts} +6 -6
  169. package/dist/{core → stores}/DatabaseManager.d.ts +3 -1
  170. package/dist/{core → stores}/DatabaseManager.js +14 -13
  171. package/dist/stores/ObjectStore.d.ts +1 -1
  172. package/dist/{core → stores}/StoreManager.d.ts +9 -26
  173. package/dist/{core → stores}/StoreManager.js +29 -77
  174. package/dist/stores/SyncActionStore.d.ts +4 -2
  175. package/dist/stores/SyncActionStore.js +11 -17
  176. package/dist/stores/syncAction.d.ts +26 -0
  177. package/dist/stores/syncAction.js +16 -0
  178. package/dist/surface.d.ts +3 -3
  179. package/dist/surface.js +6 -4
  180. package/dist/sync/BootstrapFetcher.d.ts +127 -6
  181. package/dist/sync/BootstrapFetcher.js +511 -83
  182. package/dist/sync/ConnectionManager.d.ts +6 -198
  183. package/dist/sync/ConnectionManager.js +6 -677
  184. package/dist/sync/OnDemandLoader.d.ts +5 -2
  185. package/dist/sync/OnDemandLoader.js +61 -21
  186. package/dist/sync/SubscriptionManager.d.ts +13 -2
  187. package/dist/sync/SubscriptionManager.js +23 -5
  188. package/dist/sync/SyncWebSocket.d.ts +27 -510
  189. package/dist/sync/SyncWebSocket.js +76 -954
  190. package/dist/sync/awaitClaimGrant.d.ts +4 -44
  191. package/dist/sync/awaitClaimGrant.js +4 -109
  192. package/dist/sync/bootstrapApply.d.ts +3 -0
  193. package/dist/sync/bootstrapApply.js +2 -2
  194. package/dist/sync/commitFrames.d.ts +6 -40
  195. package/dist/sync/commitFrames.js +6 -97
  196. package/dist/sync/contextPorts.d.ts +18 -0
  197. package/dist/sync/contextPorts.js +31 -0
  198. package/dist/sync/createClaimStream.d.ts +5 -49
  199. package/dist/sync/createClaimStream.js +5 -469
  200. package/dist/sync/createPresenceStream.d.ts +26 -4
  201. package/dist/sync/createPresenceStream.js +28 -20
  202. package/dist/sync/createSnapshot.d.ts +2 -2
  203. package/dist/sync/createSnapshot.js +1 -1
  204. package/dist/sync/credentialLifecycle.d.ts +5 -173
  205. package/dist/sync/credentialLifecycle.js +5 -320
  206. package/dist/sync/deltaPipeline.d.ts +13 -12
  207. package/dist/sync/deltaPipeline.js +21 -4
  208. package/dist/sync/groupChange.d.ts +3 -0
  209. package/dist/sync/groupChange.js +16 -14
  210. package/dist/sync/participants.d.ts +24 -6
  211. package/dist/sync/participants.js +32 -23
  212. package/dist/sync/schemaDrift.d.ts +55 -0
  213. package/dist/sync/schemaDrift.js +53 -0
  214. package/dist/sync/schemas.d.ts +23 -33
  215. package/dist/sync/schemas.js +29 -20
  216. package/dist/sync/syncPlan.d.ts +3 -3
  217. package/dist/sync/wsFrameHandlers.d.ts +6 -114
  218. package/dist/sync/wsFrameHandlers.js +6 -392
  219. package/dist/syncLog/contract.d.ts +20 -0
  220. package/dist/syncLog/contract.js +19 -0
  221. package/dist/syncLog/index.d.ts +1 -0
  222. package/dist/syncLog/index.js +1 -0
  223. package/dist/transaction/ablo.d.ts +88 -0
  224. package/dist/transaction/ablo.js +33 -0
  225. package/dist/{client/auth.d.ts → transaction/auth/apiKey.d.ts} +43 -8
  226. package/dist/{client/auth.js → transaction/auth/apiKey.js} +19 -0
  227. package/dist/transaction/auth/bootstrapScope.d.ts +15 -0
  228. package/dist/transaction/auth/bootstrapScope.js +1 -0
  229. package/dist/transaction/auth/capability.d.ts +212 -0
  230. package/dist/transaction/auth/capability.js +224 -0
  231. package/dist/{auth → transaction/auth}/credentialSource.d.ts +8 -1
  232. package/dist/{client → transaction/auth}/identity.d.ts +8 -7
  233. package/dist/{client → transaction/auth}/identity.js +1 -1
  234. package/dist/transaction/auth/index.d.ts +162 -0
  235. package/dist/transaction/auth/index.js +304 -0
  236. package/dist/{auth → transaction/auth}/schemas.d.ts +1 -1
  237. package/dist/{auth → transaction/auth}/schemas.js +13 -13
  238. package/dist/{client → transaction/auth}/sessionMint.d.ts +8 -8
  239. package/dist/{client → transaction/auth}/sessionMint.js +4 -7
  240. package/dist/transaction/coordination/awaitClaimGrant.d.ts +56 -0
  241. package/dist/transaction/coordination/awaitClaimGrant.js +124 -0
  242. package/dist/{client → transaction/coordination}/claimHeartbeatLoop.d.ts +34 -0
  243. package/dist/{client → transaction/coordination}/claimHeartbeatLoop.js +20 -0
  244. package/dist/transaction/coordination/claimMeta.d.ts +49 -0
  245. package/dist/transaction/coordination/claimMeta.js +52 -0
  246. package/dist/transaction/coordination/createClaimStream.d.ts +64 -0
  247. package/dist/transaction/coordination/createClaimStream.js +475 -0
  248. package/dist/transaction/coordination/events.d.ts +74 -0
  249. package/dist/transaction/coordination/events.js +7 -0
  250. package/dist/transaction/coordination/index.d.ts +19 -0
  251. package/dist/transaction/coordination/index.js +45 -0
  252. package/dist/transaction/coordination/locator.d.ts +104 -0
  253. package/dist/transaction/coordination/locator.js +102 -0
  254. package/dist/transaction/coordination/schema.d.ts +1536 -0
  255. package/dist/transaction/coordination/schema.js +1177 -0
  256. package/dist/transaction/coordination/targetConflict.d.ts +2 -0
  257. package/dist/transaction/coordination/targetConflict.js +107 -0
  258. package/dist/{coordination → transaction/coordination}/trace.d.ts +7 -18
  259. package/dist/{coordination → transaction/coordination}/trace.js +18 -25
  260. package/dist/transaction/durableWrites.d.ts +62 -0
  261. package/dist/{client → transaction}/durableWrites.js +28 -3
  262. package/dist/transaction/environment.d.ts +105 -0
  263. package/dist/transaction/environment.js +108 -0
  264. package/dist/{errorCodes.d.ts → transaction/errorCodes.d.ts} +12 -12
  265. package/dist/{errorCodes.js → transaction/errorCodes.js} +45 -18
  266. package/dist/{errors.d.ts → transaction/errors.d.ts} +37 -13
  267. package/dist/{errors.js → transaction/errors.js} +85 -16
  268. package/dist/transaction/footprint.d.ts +111 -0
  269. package/dist/transaction/footprint.js +0 -0
  270. package/dist/transaction/index.d.ts +20 -0
  271. package/dist/transaction/index.js +20 -0
  272. package/dist/transaction/keys/index.d.ts +87 -0
  273. package/dist/transaction/keys/index.js +207 -0
  274. package/dist/transaction/log/syncDeltaRow.d.ts +158 -0
  275. package/dist/transaction/log/syncDeltaRow.js +95 -0
  276. package/dist/{sync/syncPosition.d.ts → transaction/logPosition.d.ts} +22 -8
  277. package/dist/{sync/syncPosition.js → transaction/logPosition.js} +15 -6
  278. package/dist/transaction/logger.d.ts +16 -0
  279. package/dist/transaction/logger.js +7 -0
  280. package/dist/transaction/observability.d.ts +53 -0
  281. package/dist/transaction/observability.js +19 -0
  282. package/dist/transaction/plugin.d.ts +285 -0
  283. package/dist/transaction/plugin.js +106 -0
  284. package/dist/{policy → transaction/policy}/types.d.ts +3 -3
  285. package/dist/{policy → transaction/policy}/types.js +2 -0
  286. package/dist/transaction/resources/httpResources.d.ts +321 -0
  287. package/dist/transaction/resources/httpResources.js +7 -0
  288. package/dist/transaction/resources/modelOperations.d.ts +427 -0
  289. package/dist/transaction/resources/modelOperations.js +12 -0
  290. package/dist/transaction/resources/mutationOptions.d.ts +66 -0
  291. package/dist/transaction/resources/mutationOptions.js +9 -0
  292. package/dist/transaction/resources/where.d.ts +101 -0
  293. package/dist/transaction/resources/where.js +115 -0
  294. package/dist/{client → transaction/resources}/writeOptionsSchema.d.ts +2 -6
  295. package/dist/{client → transaction/resources}/writeOptionsSchema.js +9 -5
  296. package/dist/{schema → transaction/schema}/field.d.ts +17 -23
  297. package/dist/{schema → transaction/schema}/field.js +5 -5
  298. package/dist/transaction/schema/fieldRef.d.ts +38 -0
  299. package/dist/transaction/schema/fieldRef.js +11 -0
  300. package/dist/transaction/schema/loadStrategy.d.ts +45 -0
  301. package/dist/transaction/schema/loadStrategy.js +46 -0
  302. package/dist/{schema → transaction/schema}/model.d.ts +50 -35
  303. package/dist/{schema → transaction/schema}/model.js +30 -20
  304. package/dist/transaction/schema/openapi.d.ts +58 -0
  305. package/dist/transaction/schema/openapi.js +501 -0
  306. package/dist/{schema → transaction/schema}/relation.d.ts +21 -16
  307. package/dist/{schema → transaction/schema}/relation.js +7 -7
  308. package/dist/{schema → transaction/schema}/residency.d.ts +0 -9
  309. package/dist/{schema → transaction/schema}/residency.js +0 -5
  310. package/dist/{schema → transaction/schema}/roles.d.ts +5 -5
  311. package/dist/{schema → transaction/schema}/roles.js +5 -5
  312. package/dist/{schema → transaction/schema}/schema.d.ts +39 -10
  313. package/dist/{schema → transaction/schema}/schema.js +24 -3
  314. package/dist/{schema → transaction/schema}/tenancy.d.ts +1 -1
  315. package/dist/{schema → transaction/schema}/tenancy.js +7 -4
  316. package/dist/transaction/transactionLayer.d.ts +82 -0
  317. package/dist/transaction/transactionLayer.js +24 -0
  318. package/dist/{transactions → transaction/transactions/settlement}/commitEnvelope.d.ts +5 -6
  319. package/dist/{transactions → transaction/transactions/settlement}/commitEnvelope.js +9 -13
  320. package/dist/{transactions → transaction/transactions/settlement}/httpCommitEnvelope.d.ts +9 -2
  321. package/dist/{transactions → transaction/transactions/settlement}/httpCommitEnvelope.js +5 -9
  322. package/dist/{transactions/durableWriteStore.d.ts → transaction/transactions/settlement/pendingWrite.d.ts} +11 -37
  323. package/dist/transaction/transactions/settlement/pendingWrite.js +20 -0
  324. package/dist/transaction/transport/commitFrames.d.ts +90 -0
  325. package/dist/transaction/transport/commitFrames.js +134 -0
  326. package/dist/transaction/transport/connectionManager.d.ts +215 -0
  327. package/dist/transaction/transport/connectionManager.js +673 -0
  328. package/dist/transaction/transport/credentialLifecycle.d.ts +177 -0
  329. package/dist/transaction/transport/credentialLifecycle.js +324 -0
  330. package/dist/{sync → transaction/transport}/heartbeat.d.ts +3 -1
  331. package/dist/{sync → transaction/transport}/heartbeat.js +6 -4
  332. package/dist/transaction/transport/httpClient.d.ts +131 -0
  333. package/dist/{client → transaction/transport}/httpClient.js +6 -5
  334. package/dist/transaction/transport/httpOptions.d.ts +33 -0
  335. package/dist/transaction/transport/httpOptions.js +12 -0
  336. package/dist/{client → transaction/transport}/httpTransport.js +295 -97
  337. package/dist/{sync/NetworkProbe.d.ts → transaction/transport/networkProbe.d.ts} +7 -4
  338. package/dist/{sync/NetworkProbe.js → transaction/transport/networkProbe.js} +14 -13
  339. package/dist/transaction/transport/wsFrameHandlers.d.ts +128 -0
  340. package/dist/transaction/transport/wsFrameHandlers.js +429 -0
  341. package/dist/transaction/transport/wsTransport.d.ts +574 -0
  342. package/dist/transaction/transport/wsTransport.js +1023 -0
  343. package/dist/transaction/types/assertExact.d.ts +17 -0
  344. package/dist/transaction/types/assertExact.js +1 -0
  345. package/dist/{types → transaction/types}/global.d.ts +17 -2
  346. package/dist/{types → transaction/types}/global.js +2 -1
  347. package/dist/{types → transaction/types}/index.d.ts +14 -46
  348. package/dist/{types → transaction/types}/index.js +7 -16
  349. package/dist/{types → transaction/types}/streams.d.ts +73 -45
  350. package/dist/transaction/utils/duration.d.ts +50 -0
  351. package/dist/{utils → transaction/utils}/duration.js +32 -0
  352. package/dist/{utils → transaction/utils}/json.d.ts +18 -0
  353. package/dist/transaction/utils/json.js +276 -0
  354. package/dist/transaction/wire/accountResponses.d.ts +420 -0
  355. package/dist/transaction/wire/accountResponses.js +290 -0
  356. package/dist/transaction/wire/auth.d.ts +56 -0
  357. package/dist/transaction/wire/auth.js +63 -0
  358. package/dist/transaction/wire/claimEvent.d.ts +76 -0
  359. package/dist/transaction/wire/claimEvent.js +73 -0
  360. package/dist/transaction/wire/claims.d.ts +530 -0
  361. package/dist/transaction/wire/claims.js +327 -0
  362. package/dist/{wire → transaction/wire}/commit.d.ts +125 -193
  363. package/dist/{wire → transaction/wire}/commit.js +68 -47
  364. package/dist/{wire → transaction/wire}/delta.d.ts +66 -17
  365. package/dist/{wire → transaction/wire}/delta.js +37 -13
  366. package/dist/transaction/wire/errorEnvelope.d.ts +72 -0
  367. package/dist/{wire → transaction/wire}/errorEnvelope.js +36 -5
  368. package/dist/transaction/wire/feedCursor.d.ts +60 -0
  369. package/dist/transaction/wire/feedCursor.js +82 -0
  370. package/dist/transaction/wire/feedEvent.d.ts +204 -0
  371. package/dist/transaction/wire/feedEvent.js +65 -0
  372. package/dist/transaction/wire/frames.d.ts +194 -0
  373. package/dist/transaction/wire/frames.js +50 -0
  374. package/dist/transaction/wire/inboundFrames.d.ts +562 -0
  375. package/dist/transaction/wire/inboundFrames.js +116 -0
  376. package/dist/transaction/wire/index.d.ts +54 -0
  377. package/dist/transaction/wire/index.js +83 -0
  378. package/dist/{wire → transaction/wire}/listEnvelope.d.ts +13 -14
  379. package/dist/transaction/wire/listEnvelope.js +42 -0
  380. package/dist/transaction/wire/modelMutations.d.ts +31 -0
  381. package/dist/transaction/wire/modelMutations.js +52 -0
  382. package/dist/transaction/wire/modelResponses.d.ts +85 -0
  383. package/dist/transaction/wire/modelResponses.js +43 -0
  384. package/dist/transaction/wire/modelShape.d.ts +78 -0
  385. package/dist/transaction/wire/modelShape.js +74 -0
  386. package/dist/transactions/{TransactionQueue.d.ts → mutations/MutationQueue.d.ts} +85 -38
  387. package/dist/transactions/{TransactionQueue.js → mutations/MutationQueue.js} +141 -80
  388. package/dist/transactions/{TransactionStore.d.ts → mutations/MutationStore.d.ts} +8 -8
  389. package/dist/transactions/{TransactionStore.js → mutations/MutationStore.js} +2 -2
  390. package/dist/transactions/{coalesceRules.d.ts → mutations/coalesceRules.d.ts} +10 -10
  391. package/dist/transactions/{coalesceRules.js → mutations/coalesceRules.js} +1 -1
  392. package/dist/transactions/mutations/commitLatency.d.ts +52 -0
  393. package/dist/transactions/mutations/commitLatency.js +130 -0
  394. package/dist/transactions/{commitOutboxStore.d.ts → mutations/commitOutboxStore.d.ts} +1 -5
  395. package/dist/transactions/{commitOutboxStore.js → mutations/commitOutboxStore.js} +1 -1
  396. package/dist/transactions/{commitPayload.d.ts → mutations/commitPayload.d.ts} +18 -16
  397. package/dist/transactions/{commitPayload.js → mutations/commitPayload.js} +15 -15
  398. package/dist/transactions/{deltaConfirmation.d.ts → mutations/deltaConfirmation.d.ts} +15 -11
  399. package/dist/transactions/{deltaConfirmation.js → mutations/deltaConfirmation.js} +14 -12
  400. package/dist/transactions/mutations/durableWriteStore.d.ts +14 -0
  401. package/dist/transactions/mutations/durableWriteStore.js +12 -0
  402. package/dist/transactions/{optimisticApply.d.ts → mutations/optimisticApply.d.ts} +7 -7
  403. package/dist/transactions/{replayValidation.d.ts → mutations/replayValidation.d.ts} +4 -3
  404. package/dist/transactions/{replayValidation.js → mutations/replayValidation.js} +7 -5
  405. package/dist/utils/mobxSetup.d.ts +1 -1
  406. package/dist/utils/mobxSetup.js +5 -2
  407. package/dist/{core → views}/QueryView.d.ts +2 -2
  408. package/dist/{core → views}/QueryView.js +2 -2
  409. package/dist/{core → views}/ViewRegistry.d.ts +1 -1
  410. package/dist/{core/queryUtils.d.ts → views/incrementalView.d.ts} +6 -6
  411. package/dist/{core/queryUtils.js → views/incrementalView.js} +6 -6
  412. package/dist/webhooks/events.d.ts +2 -2
  413. package/dist/wire/index.d.ts +1 -34
  414. package/dist/wire/index.js +8 -49
  415. package/docs/agent-messaging.md +3 -3
  416. package/docs/agents.md +20 -13
  417. package/docs/api-keys.md +14 -10
  418. package/docs/api.md +27 -61
  419. package/docs/audit.md +6 -3
  420. package/docs/cli.md +41 -13
  421. package/docs/client-behavior.md +11 -9
  422. package/docs/concurrency-convention.md +49 -57
  423. package/docs/coordination.md +283 -121
  424. package/docs/data-sources.md +7 -5
  425. package/docs/debugging.md +39 -15
  426. package/docs/deployment.md +267 -0
  427. package/docs/examples/agent-human.md +49 -42
  428. package/docs/examples/ai-sdk-tool.md +69 -44
  429. package/docs/examples/existing-python-backend.md +8 -6
  430. package/docs/examples/nextjs.md +129 -47
  431. package/docs/examples/scoped-agent.md +46 -45
  432. package/docs/examples/server-agent.md +46 -26
  433. package/docs/groups.md +87 -30
  434. package/docs/guarantees.md +41 -12
  435. package/docs/how-it-works.md +38 -12
  436. package/docs/idempotency.md +126 -0
  437. package/docs/identity.md +77 -74
  438. package/docs/index.md +172 -86
  439. package/docs/integration-guide.md +31 -19
  440. package/docs/mcp.md +46 -21
  441. package/docs/migration.md +95 -18
  442. package/docs/operating-on-your-database.md +3 -1
  443. package/docs/projects.md +3 -1
  444. package/docs/quickstart.md +22 -5
  445. package/docs/react.md +31 -18
  446. package/docs/schema-contract.md +5 -3
  447. package/docs/session-settings.md +108 -0
  448. package/docs/sessions.md +4 -2
  449. package/docs/webhooks.md +12 -10
  450. package/llms.txt +48 -18
  451. package/package.json +21 -26
  452. package/dist/agent/Agent.d.ts +0 -366
  453. package/dist/agent/Agent.js +0 -514
  454. package/dist/agent/index.d.ts +0 -115
  455. package/dist/agent/index.js +0 -128
  456. package/dist/agent/session.d.ts +0 -93
  457. package/dist/agent/session.js +0 -149
  458. package/dist/agent/types.d.ts +0 -68
  459. package/dist/agent/types.js +0 -9
  460. package/dist/cli.cjs +0 -286329
  461. package/dist/client/durableWrites.d.ts +0 -21
  462. package/dist/client/httpClient.d.ts +0 -80
  463. package/dist/coordination/schema.d.ts +0 -722
  464. package/dist/coordination/schema.js +0 -578
  465. package/dist/schema/openapi.d.ts +0 -29
  466. package/dist/schema/openapi.js +0 -124
  467. package/dist/testing/fixtures/bootstrap.d.ts +0 -49
  468. package/dist/testing/fixtures/bootstrap.js +0 -59
  469. package/dist/testing/fixtures/deltas.d.ts +0 -83
  470. package/dist/testing/fixtures/deltas.js +0 -136
  471. package/dist/testing/fixtures/models.d.ts +0 -83
  472. package/dist/testing/fixtures/models.js +0 -272
  473. package/dist/testing/helpers/reactWrapper.d.ts +0 -69
  474. package/dist/testing/helpers/reactWrapper.js +0 -67
  475. package/dist/testing/helpers/syncEngineHarness.d.ts +0 -54
  476. package/dist/testing/helpers/syncEngineHarness.js +0 -73
  477. package/dist/testing/helpers/wait.d.ts +0 -30
  478. package/dist/testing/helpers/wait.js +0 -49
  479. package/dist/testing/index.d.ts +0 -23
  480. package/dist/testing/index.js +0 -33
  481. package/dist/testing/mocks/FakeDatabase.d.ts +0 -18
  482. package/dist/testing/mocks/FakeDatabase.js +0 -10
  483. package/dist/testing/mocks/MockMutationExecutor.d.ts +0 -87
  484. package/dist/testing/mocks/MockMutationExecutor.js +0 -192
  485. package/dist/testing/mocks/MockNetworkMonitor.d.ts +0 -20
  486. package/dist/testing/mocks/MockNetworkMonitor.js +0 -46
  487. package/dist/testing/mocks/MockSyncContext.d.ts +0 -51
  488. package/dist/testing/mocks/MockSyncContext.js +0 -71
  489. package/dist/testing/mocks/MockSyncStore.d.ts +0 -88
  490. package/dist/testing/mocks/MockSyncStore.js +0 -171
  491. package/dist/testing/mocks/MockWebSocket.d.ts +0 -71
  492. package/dist/testing/mocks/MockWebSocket.js +0 -118
  493. package/dist/transactions/durableWriteStore.js +0 -30
  494. package/dist/utils/duration.d.ts +0 -25
  495. package/dist/utils/json.js +0 -88
  496. package/dist/wire/errorEnvelope.d.ts +0 -55
  497. package/dist/wire/frames.d.ts +0 -197
  498. package/dist/wire/frames.js +0 -49
  499. package/dist/wire/listEnvelope.js +0 -18
  500. package/docs/interaction-model.md +0 -97
  501. /package/dist/{core → query}/QueryProcessor.d.ts +0 -0
  502. /package/dist/{core → query}/QueryProcessor.js +0 -0
  503. /package/dist/{core/storeContract.js → storeContract.js} +0 -0
  504. /package/dist/{core → stores}/openIDBWithTimeout.d.ts +0 -0
  505. /package/dist/{core → stores}/openIDBWithTimeout.js +0 -0
  506. /package/dist/{client → transaction/auth}/credentialEndpoint.d.ts +0 -0
  507. /package/dist/{client → transaction/auth}/credentialEndpoint.js +0 -0
  508. /package/dist/{auth → transaction/auth}/credentialPolicy.d.ts +0 -0
  509. /package/dist/{auth → transaction/auth}/credentialPolicy.js +0 -0
  510. /package/dist/{auth → transaction/auth}/credentialSource.js +0 -0
  511. /package/dist/{client → transaction/auth}/hostedEndpoints.d.ts +0 -0
  512. /package/dist/{client → transaction/auth}/hostedEndpoints.js +0 -0
  513. /package/dist/{client → transaction}/persistence.d.ts +0 -0
  514. /package/dist/{client → transaction}/persistence.js +0 -0
  515. /package/dist/{client → transaction/resources}/functionalUpdate.d.ts +0 -0
  516. /package/dist/{client → transaction/resources}/functionalUpdate.js +0 -0
  517. /package/dist/{transactions → transaction/transactions/settlement}/idempotencyKey.d.ts +0 -0
  518. /package/dist/{transactions → transaction/transactions/settlement}/idempotencyKey.js +0 -0
  519. /package/dist/{client → transaction/transport}/httpTransport.d.ts +0 -0
  520. /package/dist/{types → transaction/types}/modelData.d.ts +0 -0
  521. /package/dist/{types → transaction/types}/modelData.js +0 -0
  522. /package/dist/{types → transaction/types}/participant.d.ts +0 -0
  523. /package/dist/{types → transaction/types}/participant.js +0 -0
  524. /package/dist/{types → transaction/types}/streams.js +0 -0
  525. /package/dist/{utils → transaction/utils}/asyncIterator.d.ts +0 -0
  526. /package/dist/{utils → transaction/utils}/asyncIterator.js +0 -0
  527. /package/dist/{wire → transaction/wire}/bootstrapReason.d.ts +0 -0
  528. /package/dist/{wire → transaction/wire}/bootstrapReason.js +0 -0
  529. /package/dist/{wire → transaction/wire}/protocol.d.ts +0 -0
  530. /package/dist/{wire → transaction/wire}/protocol.js +0 -0
  531. /package/dist/{wire → transaction/wire}/protocolVersion.d.ts +0 -0
  532. /package/dist/{wire → transaction/wire}/protocolVersion.js +0 -0
  533. /package/dist/transactions/{UnconfirmedWrites.d.ts → mutations/UnconfirmedWrites.d.ts} +0 -0
  534. /package/dist/transactions/{UnconfirmedWrites.js → mutations/UnconfirmedWrites.js} +0 -0
  535. /package/dist/transactions/{optimisticApply.js → mutations/optimisticApply.js} +0 -0
  536. /package/dist/{core → views}/ViewRegistry.js +0 -0
@@ -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
@@ -73,7 +75,7 @@ Run it against your database as a superuser or the DB owner. It creates:
73
75
 
74
76
  Scope it to a subset with `npx ablo connect --tables a,b,c`.
75
77
 
76
- - **A replication role** it streams the WAL and `SELECT`s, nothing more. This is
78
+ - **A replication role:** it streams the WAL and `SELECT`s, nothing more. This is
77
79
  the role Ablo reads and confirms through. You choose the password; it never
78
80
  passes through Ablo's CLI or servers:
79
81
 
@@ -85,7 +87,7 @@ Run it against your database as a superuser or the DB owner. It creates:
85
87
  On Amazon RDS the `REPLICATION` attribute is granted, not set directly:
86
88
  `GRANT rds_replication TO "ablo_replicator";`.
87
89
 
88
- - **A scoped writer role** the role Ablo writes your rows through. It gets row
90
+ - **A scoped writer role:** the role Ablo writes your rows through. It gets row
89
91
  DML (`SELECT, INSERT, UPDATE, DELETE`) and the sync ledger, and nothing else: no
90
92
  `REPLICATION`, no schema `CREATE`, `NOSUPERUSER NOBYPASSRLS`, row security on. It
91
93
  can change rows in your tables; it cannot change your database:
@@ -180,14 +182,14 @@ 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`
187
189
  once the row appears on your WAL. See [Guarantees](./guarantees.md) for what each
188
190
  state means and when to wait.
189
191
 
190
- ## What Ablo touches in your database the honest footprint
192
+ ## What Ablo touches in your database: the honest footprint
191
193
 
192
194
  This is the complete list. Nothing else.
193
195
 
@@ -195,7 +197,7 @@ This is the complete list. Nothing else.
195
197
  |---|---|---|
196
198
  | `ablo_publication` | A publication naming the tables Ablo reads and confirms against. | You create it (step 2). |
197
199
  | `ablo_replicator` role | A `REPLICATION` + `SELECT` role Ablo reads and confirms through. | You create it (step 2). |
198
- | `ablo_writer` role | A scoped DML role Ablo writes your rows through row DML + ledger, nothing more. | You create it (step 2). |
200
+ | `ablo_writer` role | A scoped DML role Ablo writes your rows through: row DML + ledger, nothing more. | You create it (step 2). |
199
201
  | Replication slot | A logical slot Ablo subscribes through to track its WAL position. | Ablo's runtime creates it on first connect. |
200
202
  | `wal_level = logical` | A server setting that **requires a restart**. | You set it (step 1). |
201
203
 
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
 
@@ -11,6 +13,17 @@ import { schema } from './ablo/schema';
11
13
  const ablo = Ablo({ schema, apiKey: process.env.ABLO_API_KEY, debug: true });
12
14
  ```
13
15
 
16
+ ## CLI environment and target
17
+
18
+ The CLI checks an explicit credential in this order: exported `ABLO_API_KEY`,
19
+ `.env.local`, `.env`, then the key saved by `ablo login`. An exported value wins
20
+ over project files. If a stale shell export (for example `OPENAI_API_KEY`) is
21
+ shadowing a value in `.env.local`, restart the shell or unset the stale variable.
22
+
23
+ When a command appears to use the wrong plane or project, run `ablo status`.
24
+ It reports the credential source and, when reachable, the server-confirmed
25
+ project and environment; that confirmed target is authoritative.
26
+
14
27
  `debug: true` is the simple switch. For finer control use `logLevel`, or set it without touching code via the `ABLO_LOG_LEVEL` environment variable.
15
28
 
16
29
  ```ts
@@ -29,17 +42,17 @@ ABLO_LOG_LEVEL=debug npm run dev # same, from the environment
29
42
  |---|---|
30
43
  | `silent` | nothing |
31
44
  | `error` | failures only |
32
- | `warn` | **default** warnings + errors |
45
+ | `warn` | **default**: warnings + errors |
33
46
  | `info` | the above + the **coordination trace** (claims, grants, queueing) + connection state |
34
- | `debug` | the above + internal lifecycle (per-model registration, store hydration) the full firehose |
47
+ | `debug` | the above + internal lifecycle (per-model registration, store hydration): the full firehose |
35
48
 
36
49
  Precedence: an explicit `logLevel` wins, then `debug: true` (⇒ `debug`), then `ABLO_LOG_LEVEL`, then the `warn` default. `debug: false` (or omitting it) just means "don't raise the level."
37
50
 
38
51
  > For watching coordination, **`logLevel: 'info'` is the sweet spot** — you get the claim trace without the per-model registration chatter that `debug` adds.
39
52
 
40
- ## What you'll see the coordination trace
53
+ ## What you'll see: the coordination trace
41
54
 
42
- These lines (all at `info`) let you watch the human + agent handover you built:
55
+ These lines (all at `info`) let you watch the handover you built:
43
56
 
44
57
  ```
45
58
  [Ablo] claim: requesting documents:doc_42 for "editing" (will queue if contended)
@@ -52,16 +65,16 @@ These lines (all at `info`) let you watch the human + agent handover you built:
52
65
 
53
66
  Read it as the lifecycle of one claim:
54
67
 
55
- - **`requesting`** your code (or an agent) called `ablo.<model>.claim(...)`. `(will queue if contended)` appears when you passed `{ queue: true }`.
56
- - **`queued … position N of M`** the row was held, so you're waiting in the FIFO line. This is the "an agent is waiting behind a claim" moment; it re-logs only when your position changes, so you can watch it advance.
57
- - **`granted … your turn`** you reached the head of the line; the lease is now yours and the row may have changed while you waited.
58
- - **`rejected … held by <who>`** your claim was refused because someone else holds it (and the model's policy didn't let you in).
59
- - **`lost`** you held the lease and it was taken (preempted by a higher-priority writer, or it expired).
60
- - **`released`** you (or `await using`'s scope exit) gave the lease back.
68
+ - **`requesting`:** your code (or an agent) called `ablo.<model>.claim(...)`. `(will queue if contended)` appears when you passed `{ queue: true }`.
69
+ - **`queued … position N of M`:** the row was held, so you're waiting in the FIFO line. This is the "an agent is waiting behind a claim" moment; it re-logs only when your position changes, so you can watch it advance.
70
+ - **`granted … your turn`:** you reached the head of the line; the lease is now yours and the row may have changed while you waited.
71
+ - **`rejected … held by <who>`:** your claim was refused because someone else holds it (and the model's policy didn't let you in).
72
+ - **`lost`:** you held the lease and it was taken (preempted by a higher-priority writer, or it expired).
73
+ - **`released`:** you (or `await using`'s scope exit) gave the lease back.
61
74
 
62
75
  ## Where the logs run
63
76
 
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.
77
+ 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
78
 
66
79
  ## Bring your own logger
67
80
 
@@ -80,7 +93,7 @@ Ablo({
80
93
  });
81
94
  ```
82
95
 
83
- ## Read the coordination in code the activity log
96
+ ## Read the coordination in code: the activity log
84
97
 
85
98
  The console trace above is for *you*, at a terminal. To put the same activity **inside your app** — an activity feed, a "who's editing" badge, a Sentry breadcrumb trail — read it programmatically. Same events, three layers; pick by audience:
86
99
 
@@ -112,7 +125,7 @@ interface ConflictEvent {
112
125
 
113
126
  `phase` is past-tense — the state the claim just entered — and maps one-to-one to what arrives on the wire.
114
127
 
115
- ### Collect them `ClaimLog`
128
+ ### Collect them: `ClaimLog`
116
129
 
117
130
  `ClaimLog` records both into an ordered list. Hand it to `observability`, then read it back:
118
131
 
@@ -134,7 +147,7 @@ It's also the simplest way to **assert** coordination in a test — no log scrap
134
147
  expect(log.collisions()).toHaveLength(0); // no one stepped on anyone
135
148
  ```
136
149
 
137
- ### Show it on a page reactive
150
+ ### Show it on a page: reactive
138
151
 
139
152
  `ClaimLog.onChange` fires on every event and returns an unsubscribe — the exact shape `useSyncExternalStore` wants, so a live feed is a few lines:
140
153
 
@@ -183,6 +196,17 @@ const ablo = Ablo({
183
196
  });
184
197
  ```
185
198
 
199
+ `ClaimLog` implements the full `SyncObservabilityProvider`, so it drops straight
200
+ into the `observability` slot. The surface exports `ClaimLog`, `formatClaim`,
201
+ `formatConflict`, and `noopObservability`, plus the types `ClaimEvent`,
202
+ `ConflictEvent`, `ClaimLogEntry`, and `SyncObservabilityProvider`.
203
+
204
+ > **Both transports, from 0.21.0.** Observability fires on the WebSocket and on
205
+ > the stateless HTTP transport (claim acquired, plus coordination-conflict
206
+ > rejections on every write door). Before 0.21.0 only WebSocket emitted, so a
207
+ > `ClaimLog` on an HTTP client, such as a headless server-agent eval, stayed
208
+ > silent even though coordination still worked.
209
+
186
210
  ## Errors
187
211
 
188
212
  Ablo's thrown errors are typed and self-describing — `String(err)` (or logging it) yields one clean line, never a stack dump:
@@ -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.