@abloatai/ablo 0.34.0 → 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 +4 -1
  2. package/CHANGELOG.md +684 -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 +3459 -1126
  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 -84
  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 +111 -0
  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,8 +1,10 @@
1
1
  # Interaction Model
2
2
 
3
- When a person, a server action, and an AI agent can all write to the same row,
4
- you need one write path that stops them from clobbering each other. Ablo gives
5
- you exactly one: load the row, claim it while you work, update it, and wait for
3
+ > The one write path every actor shares: load, claim, update, confirm.
4
+
5
+ When two agents, a server action, and a person can all write to the same row, you
6
+ need one write path that stops them from clobbering each other. Ablo gives you
7
+ exactly one: load the row, claim it while you work, update it, and wait for
6
8
  confirmation. This page walks through that path and the few primitives behind it.
7
9
 
8
10
  Here's the whole path in one block — claim a row, update it inside the claim, and
@@ -24,7 +26,7 @@ of clobbering.
24
26
  | Primitive | Plane | Purpose |
25
27
  |---|---|---|
26
28
  | `Schema` | State | Declares typed models the app and agents can read and write. |
27
- | `Model` | State | The generated `ablo.<model>` model. Use `retrieve`/`list` (async server reads), `get`/`getAll`/`getCount` (synchronous local reads), `create`, `update`, and `delete`. |
29
+ | `Model` | State | The generated `ablo.<model>` model. Use `retrieve`/`list` (async reads), `local.retrieve`/`local.list`/`local.count` (the same verbs, synchronous and local-only), `create`, `update`, and `delete`. |
28
30
  | `Claim` | Coordination | Who is working on a target. Taken via `ablo.<model>.claim({ id })` and read via `ablo.<model>.claim.state({ id })`. Ephemeral — never persisted. |
29
31
  | `Commit` | Protocol | The durable write underneath model updates. Most users do not call it directly. |
30
32
  | `Receipt` | Protocol | The lower-level durable result for custom runtimes. Schema writes use `wait: 'confirmed'`. |
package/docs/mcp.md CHANGED
@@ -1,38 +1,64 @@
1
1
  # Model Context Protocol
2
2
 
3
+ > Two MCP servers for two different jobs — one of them is a data plane, one is not.
4
+
3
5
  Ablo publishes **two** MCP servers for two different jobs. Don't confuse them:
4
6
 
5
7
  | Server | Purpose | Auth | Tools |
6
8
  |---|---|---|---|
7
- | **Coordination** (`@ablo/mcp`) | Let an agent safely read & mutate your application data | API key (`sk_…` / `rk_…`) | per-model `get` / `list` / `create` / `update` / `delete` / `claim` / `release` |
9
+ | **Coordination** (`@abloatai/mcp`) | Manage your Ablo the way the CLI does, and let an agent safely read & mutate application data | API key (`sk_…` / `rk_…`) | projects, schema, logs, usage — plus `get` / `list` / `create` / `update` / `delete` / `claim` / `release` over your rows |
8
10
  | **Integration-helper** (hosted `/api/mcp`) | Help an AI coding assistant write SDK integration code that compiles | none (public docs) | doc search, export surface, schema lint, scaffold |
9
11
 
10
- The coordination server **is the data plane** — it is how an agent changes
11
- state. The integration-helper server only serves docs, schema lint, and
12
- scaffolds; it does **not** read or write application data (there are no
12
+ The coordination server manages your account **and is the data plane** — it is
13
+ how an agent changes state. The integration-helper server only serves docs,
14
+ schema lint, and scaffolds; it does **not** read or write application data (there are no
13
15
  per-model data tools on it). Pick by what you're doing: shipping an agent that
14
16
  edits rows → coordination; teaching your IDE assistant the SDK → helper.
15
17
 
16
- ## Coordination server (`@ablo/mcp`)
18
+ ## Coordination server (`@abloatai/mcp`)
17
19
 
18
- The coordination server is the MCP projection of the model-scoped API
19
- (`/api/v1/models/...`) — the same surface as `ablo.<model>.create/update/claim` and
20
- the REST routes, rendered as tools. An agent connects with your API key and
21
- gets one safe loop: **claim → read → commit → release.**
20
+ The coordination server does two jobs: it manages your Ablo the way the `ablo`
21
+ CLI does, and it renders the model-scoped API (`/api/v1/models/...`) as tools
22
+ the same surface as `ablo.<model>.create/update/claim`. An agent connects with
23
+ your API key and gets one safe loop: **claim → read → commit → release.**
22
24
 
23
25
  Install over stdio; set your key in the host's MCP env:
24
26
 
25
27
  ```bash
26
- claude mcp add ablo -- npx -y @ablo/mcp
28
+ claude mcp add ablo -- npx -y @abloatai/mcp
27
29
  # env: ABLO_API_KEY=sk_… (ABLO_API_URL optional; defaults to the hosted API)
28
30
  ```
29
31
 
30
- Each tool mirrors an SDK verb, scoped to a model + id:
32
+ ### Managing your Ablo
33
+
34
+ | Tool | Mirrors | Does |
35
+ |---|---|---|
36
+ | `get_schema` | `ablo status` | the models this key can address, and its environment + project |
37
+ | `list_projects` | `ablo projects list` | the org's projects (needs `sk_`) |
38
+ | `create_project` | `ablo projects create` | create one (needs `sk_`) |
39
+ | `tail_logs` | `ablo logs` | recent commits and the actor behind each |
40
+ | `get_usage` | — | usage in daily buckets |
41
+
42
+ There are no key-management tools. A mint returns the plaintext once — only a
43
+ hash is kept — so no tool can hand it back later, and returning it at mint time
44
+ would write a live secret into the agent's context and the conversation
45
+ transcript, where it outlives any revocation. Listing and revoking will arrive
46
+ once a grant identifies the caller as a person rather than a key. Manage keys
47
+ with `ablo login` or the dashboard.
48
+
49
+ `ablo init`, `push`, `pull`, and `generate` have no tools: they read and write
50
+ files in your repo, which the server cannot see. Run those in a shell — then
51
+ call `get_schema` to see the result.
52
+
53
+ ### Reading and changing rows
54
+
55
+ Each tool mirrors an SDK verb, scoped to a model + id. Model names come from
56
+ `get_schema`:
31
57
 
32
58
  | Tool | Mirrors | Does |
33
59
  |---|---|---|
34
- | `get_model` | `ablo.<model>.get(id)` | read latest state + active claims |
35
- | `list_models` | `ablo.<model>.list({…})` | cursor-paginated list with filters |
60
+ | `get_model` | `ablo.<model>.local.retrieve(id)` | read latest state + active claims |
61
+ | `list_records` | `ablo.<model>.list({…})` | cursor-paginated list with filters |
36
62
  | `create_model` | `ablo.<model>.create({ data })` | guarded create |
37
63
  | `update_model` | `ablo.<model>.update({ id, … })` | guarded update |
38
64
  | `delete_model` | `ablo.<model>.delete({ id })` | guarded delete |
@@ -41,8 +67,7 @@ Each tool mirrors an SDK verb, scoped to a model + id:
41
67
 
42
68
  The agent-facing contract — the safe loop, the "derive idempotency keys from
43
69
  the business event" rule, and the error-code playbook — ships as a loadable
44
- skill at `@ablo/mcp/skill.md`. Lives in `packages/mcp/`
45
- (`createCoordinationMcpServer`, `src/tools.ts`).
70
+ skill at `@abloatai/mcp/skill.md`.
46
71
 
47
72
  ## Integration-helper server
48
73
 
@@ -57,7 +82,7 @@ server above, never here.
57
82
  > The `@abloatai/ablo` npm package itself bundles neither server — it has
58
83
  > no `@modelcontextprotocol/sdk` dependency. The helper is a feature of Ablo's
59
84
  > hosted app, mounted at `/api/mcp`; the coordination server is the separate
60
- > `@ablo/mcp` package.
85
+ > `@abloatai/mcp` package.
61
86
 
62
87
  ### Install
63
88
 
package/docs/migration.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Version History & Migration Guide
2
2
 
3
+ > Every breaking change and the edit it requires, newest first.
4
+
3
5
  The breaking-changes-first companion to the [Changelog](../CHANGELOG.md). The
4
6
  changelog tells the story of each release; this page tells you exactly what to
5
7
  change when you upgrade.
@@ -11,6 +13,8 @@ change when you upgrade.
11
13
 
12
14
  | Version | What changed | What to do |
13
15
  |---|---|---|
16
+ | **0.35.0** | Synchronous reads moved under `local`, mirroring the async verbs | `get(id)` → `local.retrieve(id)`; `getAll(options)` → `local.list(options)`; `getCount(options)` → `local.count(options)` |
17
+ | **0.35.0** | `causedByTaskId` write option + seven `turn_*` error codes removed | Delete the `causedByTaskId` argument from writes; a branch on `turn_validation_failed` was unreachable and can go with it |
14
18
  | **0.34.0** | Presence verb renamed `watch` → `join` | `ablo.<model>.watch(ids)` → `ablo.<model>.join(ids)`; `useWatch` → `useJoin`; the `WatchOptions` / `UseWatchOptions` / `UseWatchReturn` types → `JoinOptions` / `UseJoinOptions` / `UseJoinReturn`; error code `model_watch_not_configured` → `model_join_not_configured` |
15
19
  | **0.28.0** | Removed React placeholders that had no working runtime | `usePresence` → `usePeers` or `useJoin`; `useClaim` → `ablo.<model>.claim`; `SyncGroupProvider` / `useSyncGroup` → `useJoin({ scope })` |
16
20
  | **0.11.0** | Historical `intent` → `claim` rename | The hook renamed in that release was later removed in 0.28.0. Current code uses `ablo.<model>.claim` or `useJoin` |
@@ -27,6 +31,60 @@ change when you upgrade.
27
31
 
28
32
  ---
29
33
 
34
+ ## 0.35.0 — the synchronous reads move under `local`
35
+
36
+ ```diff
37
+ - const task = ablo.tasks.get(id);
38
+ - const open = ablo.tasks.getAll({ where: { status: 'open' } });
39
+ - const count = ablo.tasks.getCount({ where: { status: 'open' } });
40
+ + const task = ablo.tasks.local.retrieve(id);
41
+ + const open = ablo.tasks.local.list({ where: { status: 'open' } });
42
+ + const count = ablo.tasks.local.count({ where: { status: 'open' } });
43
+ ```
44
+
45
+ Options, return types, and reactivity inside `useAblo` selectors are unchanged.
46
+ Every verb now matches its asynchronous sibling, and `local` narrows the read to
47
+ what has already synced — which is what lets it return a value rather than a
48
+ promise.
49
+
50
+ `getAll` and `getCount` are distinctive enough to rename by search. `get` is not:
51
+ in most codebases it is outnumbered many times over by `Map.get` and
52
+ `headers.get`, and no search separates them. Upgrade the package first and let
53
+ the compiler name the sites — each one is a type error at exactly the call that
54
+ has to move.
55
+
56
+ ## 0.35.0 — `causedByTaskId` and the `turn_*` error codes removed
57
+
58
+ 0.9.2 retired the `turn` primitive but left one field standing: `causedByTaskId`
59
+ on the write options bag. It was never usable. The server validated it against a
60
+ task record that nothing in the system has ever created, so supplying it had the
61
+ whole batch rejected with `turn_validation_failed`, while leaving it null passed
62
+ straight through. The safe way to use the option was to not use it.
63
+
64
+ **Removed:** `MutationOptions.causedByTaskId`, the seven `turn_*` error codes
65
+ (`turn_validation_failed`, `turn_open_failed`, `turn_close_failed`,
66
+ `turn_not_found`, `turn_foreign_agent`, `parent_turn_not_found`,
67
+ `parent_turn_foreign_agent`), and the stored row's provenance slice
68
+ (`deltaProvenanceSchema` and the `DeltaProvenance` type). `syncDeltaRowSchema` is
69
+ now the core and attribution slices composed.
70
+
71
+ ```diff
72
+ - await ablo.documents.update({ id, data, causedByTaskId: turnId });
73
+ + await ablo.documents.update({ id, data });
74
+ ```
75
+
76
+ Attribution is unaffected. A delta still records the actor, the `onBehalfOf`
77
+ principal behind a delegated write, the capability that authorized it, and the
78
+ claim it was made under — which is what answers "who did this, and by what
79
+ right." On the wire the field was optional and nullable, so a client that still
80
+ sends it is accepted and ignored.
81
+
82
+ The `caused_by_task_id` column stays, for the reason 0.9.2 gave when it kept it:
83
+ the audit hash-chain signs its value into every row. Dropping it is a versioned
84
+ migration of its own.
85
+
86
+ ---
87
+
30
88
  ## 0.34.0 — presence verb renamed `watch` → `join`
31
89
 
32
90
  The model-level presence verb read like a data subscription but delivered
@@ -35,13 +93,13 @@ does. `ablo.<model>.join(ids, { ttl })` opens the participant handle
35
93
  (`.peers`, `.claims`, `await using` disposal); the returned `status` was
36
94
  already `'joined'`, and the layer beneath always called itself `join`, so the
37
95
  verb now matches. `onChange` remains the way to hear row *values* change, and
38
- `track` remains the durable read-dependency for actors.
96
+ `track` remains the durable premise for actors.
39
97
 
40
98
  ```ts
41
99
  // before
42
- await using room = await ablo.slides.watch(slideIds, { ttl: '5m' });
100
+ await using room = await ablo.documents.watch(documentIds, { ttl: '5m' });
43
101
  // after
44
- await using room = await ablo.slides.join(slideIds, { ttl: '5m' });
102
+ await using room = await ablo.documents.join(documentIds, { ttl: '5m' });
45
103
  ```
46
104
 
47
105
  The React hook follows: `useWatch({ scope })` → `useJoin({ scope })`. There is
@@ -148,7 +206,7 @@ distinct stores.
148
206
  server-side actors (agents, workers, serverless): the same `ablo.<model>` surface
149
207
  and `claim` coordination, but each call is one HTTP round-trip with identity on
150
208
  the Bearer credential — no websocket, no local synced pool. The return type
151
- narrows, so stateful-only APIs (`get` / `getAll` / `onChange`) become compile
209
+ narrows, so stateful-only APIs (the `local` reads, `onChange`) become compile
152
210
  errors instead of latent runtime gaps. Existing code keeps the default
153
211
  `'websocket'` transport, unchanged.
154
212
 
@@ -227,7 +285,7 @@ modifier are named siblings. Reactive local reads stay on the synchronous
227
285
  + await ablo.tasks.retrieve({ id })
228
286
 
229
287
  - useAblo((ablo) => ablo.tasks.retrieve(id)) ?? serverTask
230
- + useAblo((ablo) => ablo.tasks.get(id)) ?? serverTask
288
+ + useAblo((ablo) => ablo.tasks.local.retrieve(id)) ?? serverTask
231
289
  ```
232
290
 
233
291
  `claim` now returns a disposable handle instead of taking a callback. The handle
@@ -0,0 +1,111 @@
1
+ # Operating on Your Database
2
+
3
+ > Which actions run freely, which to verify first, and which belong to a human.
4
+
5
+ Ablo sits over your database as a coordination layer, not an owner. It reads
6
+ your Postgres replication stream and routes each write through a claim-checked
7
+ commit that lands in your own tables. It never runs DDL, never migrates, never
8
+ drops. That single boundary is why almost everything you do through Ablo is
9
+ either read-only or reversible — and why the few actions that aren't are easy to
10
+ name. This page is how to tell them apart, so you can work on a real database
11
+ without guessing which move is the dangerous one.
12
+
13
+ The habit that makes it easy is to look before you act. One command shows you
14
+ the real shape of your database measured against your schema, and changes
15
+ nothing:
16
+
17
+ ```bash
18
+ npx ablo check # read-only — reports which columns fit your models and which don't
19
+ ```
20
+
21
+ When a question is about the live database — does this column exist, is it
22
+ nullable, will this write fit — you can usually answer it by observing rather
23
+ than reasoning in the dark.
24
+
25
+ ## The floor: what Ablo never does
26
+
27
+ These hold on every database Ablo connects to, and they are what bound the blast
28
+ radius of anything you do through the model API:
29
+
30
+ - It **never runs DDL or migrations** on your database, and never drops a table
31
+ or column. Schema changes to your own tables are always your application's
32
+ action, run with your admin credential — never Ablo's.
33
+ - It **never owns your rows.** Canonical data stays in your tables; Ablo hosts
34
+ only the transaction log and the coordination state.
35
+ - Every model write is **claim-checked and recorded.** A write based on a row
36
+ that moved under you is rejected rather than applied, and the prior value is
37
+ retained in the log, so a confirmed change is attributable and
38
+ reconstructable.
39
+
40
+ So a normal `ablo.<model>.update(...)` cannot silently corrupt your database:
41
+ the worst case is a clean rejection and a re-read, not a lost row.
42
+
43
+ ## Three kinds of action
44
+
45
+ Sort any action you're about to take into one of these, and the right move
46
+ follows.
47
+
48
+ **Run freely — read-only or reversible.**
49
+ Reads (`retrieve`, `list`, `get`), `ablo check`, and `ablo pull` observe and
50
+ never change anything. Previews — `--show-sql`, `--dry-run` — print the exact
51
+ SQL a command would run without executing it. Model writes through
52
+ `ablo.<model>.create` / `update` are claim-checked, optimistic, rolled back if
53
+ the server rejects them, and recorded in the log with the prior value. All of
54
+ these are safe to run on your own initiative.
55
+
56
+ **Verify first — needs one look at the live database.**
57
+ Routing an existing table's writes through a model requires the model to match
58
+ the table's real columns. Run `ablo check`: it names the columns that fit and
59
+ the ones that don't, so a `NOT NULL` column your model doesn't set shows up as a
60
+ line in the report rather than a surprise at commit time. Decide the model shape
61
+ from what `check` tells you, then proceed. Nothing here is risky — it just reads
62
+ better after you've seen the ground truth.
63
+
64
+ **Hand to a human — irreversible, outside the log's protection.**
65
+ Raw DDL on the live database — `ALTER TABLE … OWNER TO`, adding or dropping a
66
+ column, changing a constraint — changes the database itself and is not covered
67
+ by the reversible log, so it belongs to a person with their hand on it. So does
68
+ a `connect` cutover run with its confirmation skipped (`--yes`): the prompt
69
+ exists because the step provisions real roles and reconciles publication on a
70
+ live database, and on a shared or production database that confirmation is the
71
+ human's to give. Removing a model from your schema belongs here too — for the
72
+ reason below.
73
+
74
+ ## The one action that isn't what it looks like
75
+
76
+ Deleting a model from `ablo/schema.ts` reads like a code cleanup, but it is a
77
+ schema change. Your schema is a desired-state declaration: `ablo push` diffs it
78
+ against the server's copy, and a model that has vanished from the schema can be
79
+ read as a table that should no longer exist. "Nothing imports it" answers a
80
+ code question. The question that governs safety is *does removing this drop a
81
+ real table on the next push* — and that one is answered against the database,
82
+ not the codebase. Before removing a model that maps a live table, confirm the
83
+ table is gone or empty and that your push path is additive; otherwise keep the
84
+ model until the data is dealt with. A `load: 'lazy'` mapping is often present
85
+ precisely to hold a table in place, so treat its comment as load-bearing.
86
+
87
+ ## The verification loop
88
+
89
+ Most of the uncertainty in working on a live database dissolves into a few
90
+ read-only checks:
91
+
92
+ - `ablo check` — does the live database match the schema? Reports the exact
93
+ column-by-column fit. Read-only.
94
+ - `ablo pull` — what is actually in the database, expressed as a schema.
95
+ Read-only, like `prisma db pull`.
96
+ - `--show-sql` / `--dry-run` on `connect` and `migrate` — the exact statements,
97
+ printed and unexecuted, so you approve the SQL before it runs.
98
+ - Read the row and its claim state before you write — `retrieve` / `list`, and
99
+ `ablo.<model>.claim.state({ id })` for who is already working on it.
100
+
101
+ The pattern underneath all of it is steady: reads and model writes flow freely
102
+ because the boundary and the log make them safe, DDL and cutovers pause for a
103
+ human because they change the database itself, and the space between the two is
104
+ one `ablo check` away from certain.
105
+
106
+ ## See also
107
+
108
+ - [Connect Your Database](./data-sources.md) — the one path a database joins Ablo.
109
+ - [Guarantees](./guarantees.md) — what a confirmed write, a stale check, and a claim promise.
110
+ - [CLI & Migrations](./cli.md) — `check`, `pull`, `migrate`, and their read-only / preview flags.
111
+ - [Schema Contract](./schema-contract.md) — how the schema drives push, and why it is a desired-state declaration.
package/docs/projects.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Projects
2
2
 
3
+ > One organization, many apps — each with its own schema, data planes, and keys.
4
+
3
5
  A **project** is the isolation unit inside your organization — the shape you
4
6
  know from Neon or Supabase. Each app you build gets its own project, and each
5
7
  project gets its own schema, its own sandbox/production data planes, and its
@@ -1,7 +1,9 @@
1
1
  # Quickstart
2
2
 
3
+ > Make your first coordinated write, on the Postgres you already have.
4
+
3
5
  Build with Ablo on **the Postgres you already have**. You declare a small Ablo
4
- schema for the models humans and agents edit together, connect Ablo to your
6
+ schema for the models your agents edit together, connect Ablo to your
5
7
  database (`ablo connect`), and read and write every one of those models through
6
8
  `ablo.<model>`. You write through Ablo; it lands the change in your Postgres and
7
9
  confirms it by tailing your write-ahead log (WAL). Your rows live in your database,
@@ -86,6 +88,22 @@ import type { Model } from '@abloatai/ablo/schema';
86
88
  type WeatherReport = Model<'weatherReports'>; // fully typed from YOUR schema
87
89
  ```
88
90
 
91
+ The same block is where you name the metadata your claims carry. Add a
92
+ `ClaimMeta` key and every `claim.state`, `claim.queue`, and held claim reads
93
+ `target.meta` as that shape:
94
+
95
+ ```ts
96
+ declare module '@abloatai/ablo' {
97
+ interface Register {
98
+ Schema: typeof schema;
99
+ ClaimMeta: { blocks: string[] };
100
+ }
101
+ }
102
+
103
+ const holder = ablo.weatherReports.claim.state({ id });
104
+ holder?.target.meta?.blocks.length; // typed, no guard
105
+ ```
106
+
89
107
  (The same `Register` binding types every hook and client — it's the
90
108
  TanStack-Router pattern: declare the source of truth once, everything
91
109
  infers from it.)
@@ -169,10 +187,9 @@ tables** — Ablo reads them, it does not create or migrate them:
169
187
  the tables with your own migration tool; Ablo syncs the subset of models you
170
188
  declared and reports the rest as "ignored / owned by you."
171
189
 
172
- > **Optional escape hatch:** if you have no tables yet and want Ablo to scaffold
173
- > them, `npx ablo migrate` can create your synced-model tables for you. This is
174
- > not the happy path connecting a real database is `ablo connect` (step 3), and
175
- > your own migrations stay in charge of your schema.
190
+ > **Starting from an empty database?** `npx ablo migrate` creates the tables
191
+ > your schema needs. Once they exist, your own migration tool stays in charge
192
+ > of themAblo adopts whatever shape you evolve.
176
193
 
177
194
  Nothing runs locally — there is no dev server to start. Your app talks to Ablo's
178
195
  hosted API; the rows live in your database.
package/docs/react.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # React
2
2
 
3
+ > Provider, hooks, and reactive reads for the interfaces people watch agent work arrive in.
4
+
3
5
  The React bindings for `@abloatai/ablo`. Use them when you want live
4
6
  data on the client without writing fetch + WebSocket plumbing yourself.
5
7
 
@@ -85,7 +87,7 @@ org / team / user map to what a participant can see.
85
87
  import { useAblo } from '@abloatai/ablo/react';
86
88
 
87
89
  export function ReportView({ report: serverReport }: { report: { id: string; location: string } }) {
88
- const report = useAblo((ablo) => ablo.weatherReports.get(serverReport.id)) ?? serverReport;
90
+ const report = useAblo((ablo) => ablo.weatherReports.local.retrieve(serverReport.id)) ?? serverReport;
89
91
  const active = useAblo((ablo) => ablo.weatherReports.claim.state({ id: serverReport.id }));
90
92
  const claimed = Boolean(active);
91
93
 
@@ -95,7 +97,7 @@ export function ReportView({ report: serverReport }: { report: { id: string; loc
95
97
 
96
98
  The hook:
97
99
 
98
- 1. Uses the same `ablo.<model>.get(id)` / `.getAll()` methods you'd call anywhere
100
+ 1. Uses the same `ablo.<model>.local.retrieve(id)` / `.local.list()` methods you'd call anywhere
99
101
  else in the SDK — the hook just makes them reactive.
100
102
  2. Tracks the model fields read by the selector and re-renders when confirmed
101
103
  deltas arrive.
@@ -110,14 +112,14 @@ effects, or writes:
110
112
  const abloClient = useAblo();
111
113
  ```
112
114
 
113
- Prefer selector reads like `useAblo((ablo) => ablo.<model>.get(id))`. Older hooks
115
+ Prefer selector reads like `useAblo((ablo) => ablo.<model>.local.retrieve(id))`. Older hooks
114
116
  also accept a string model name; prefer the selector form shown above.
115
117
 
116
118
  For collections, keep the selector on the model client too:
117
119
 
118
120
  ```tsx
119
121
  const reports = useAblo((ablo) =>
120
- ablo.weatherReports.getAll({
122
+ ablo.weatherReports.local.list({
121
123
  where: { projectId },
122
124
  filter: (report) => report.status !== 'ready',
123
125
  state: 'live',
@@ -135,7 +137,7 @@ Use `retrieve` in Server Components when the row may not be in the local pool
135
137
  yet — it hydrates from the local store and the server, and returns a Promise, so
136
138
  `await` it. (Server reads come in two shapes: `retrieve({ id })` for one row and
137
139
  `list({ where })` for many; both are async. The synchronous local reads are
138
- `get`/`getAll`/`getCount`, used in render below.)
140
+ the `local` reads, used in render below.)
139
141
 
140
142
  ## Writes
141
143
 
@@ -191,11 +193,11 @@ write interest in it.
191
193
 
192
194
  import { useJoin } from '@abloatai/ablo/react';
193
195
 
194
- export function DeckPresence({ deckId }: { deckId: string }) {
196
+ export function DeckPresence({ workspaceId }: { workspaceId: string }) {
195
197
  const { peers, claims, status } = useJoin({
196
- scope: { slideDecks: deckId },
198
+ scope: { slideDecks: workspaceId },
197
199
  claim: true, // I intend to write — pin the scope + let peers observe the claim
198
- hydrate: true, // backfill the deck's current rows if not already loaded
200
+ hydrate: true, // backfill the workspace's current rows if not already loaded
199
201
  });
200
202
 
201
203
  if (status !== 'joined') return <span>connecting…</span>;
@@ -230,8 +232,8 @@ connection is subscribed to.
230
232
 
231
233
  import { usePeers } from '@abloatai/ablo/react';
232
234
 
233
- export function CursorBroadcaster({ deckId }: { deckId: string }) {
234
- const peers = usePeers({ slideDecks: deckId });
235
+ export function CursorBroadcaster({ workspaceId }: { workspaceId: string }) {
236
+ const peers = usePeers({ slideDecks: workspaceId });
235
237
  const alone = !peers.some((p) => p.participantKind === 'user');
236
238
  // suppress live-cursor broadcasts while alone
237
239
  }
@@ -1,5 +1,7 @@
1
1
  # Schema Contract
2
2
 
3
+ > One schema becomes typed clients, agent writes, interface reads, and the hosted push.
4
+
3
5
  Ablo's schema is the integration contract. Define it once, pass it to `Ablo(...)`,
4
6
  and every actor gets the same typed model surface:
5
7
 
@@ -10,7 +12,7 @@ defineSchema(...) -> ablo.<model>.create/retrieve/update/claim(...)
10
12
  That one object drives:
11
13
 
12
14
  - typed model clients in trusted server runtimes,
13
- - React selectors through `useAblo((ablo) => ablo.<model>.get(id))`,
15
+ - React selectors through `useAblo((ablo) => ablo.<model>.local.retrieve(id))`,
14
16
  - agent and background-worker writes,
15
17
  - Data Source request/response shape when your database stays canonical,
16
18
  - hosted schema push, migration planning, and schema-version gating.
@@ -75,8 +77,8 @@ const ready = await ablo.weatherReports.list({ where: { status: 'ready' } });
75
77
  Use synchronous local reads in render after data has synced:
76
78
 
77
79
  ```ts
78
- const report = ablo.weatherReports.get(reportId);
79
- const pending = ablo.weatherReports.getAll({ where: { status: 'pending' } });
80
+ const report = ablo.weatherReports.local.retrieve(reportId);
81
+ const pending = ablo.weatherReports.local.list({ where: { status: 'pending' } });
80
82
  ```
81
83
 
82
84
  Use model writes for every actor:
@@ -0,0 +1,108 @@
1
+ # Session Settings
2
+
3
+ > Point your row-level-security policies at Ablo's writes, by naming the Postgres session settings they already read.
4
+
5
+ Ablo writes your rows through a scoped role with `row_security` on and
6
+ `NOBYPASSRLS` set, so your policies govern its writes the same way they govern
7
+ your own application's. They only govern well if they can see who the write is
8
+ for. Before each write, Ablo sets its own identity context on the transaction —
9
+ and if your policies read settings under names you chose, `sessionSettings` maps
10
+ one to the other:
11
+
12
+ ```ts
13
+ import { defineSchema, model, z } from '@abloatai/ablo/schema';
14
+
15
+ export const schema = defineSchema(
16
+ {
17
+ invoices: model({
18
+ total: z.number(),
19
+ reference: z.string(),
20
+ }),
21
+ },
22
+ {
23
+ sessionSettings: { 'app.current_org': 'orgId' },
24
+ },
25
+ );
26
+ ```
27
+
28
+ A policy written against `current_setting('app.current_org')` now applies to
29
+ Ablo's write, unchanged:
30
+
31
+ ```sql
32
+ CREATE POLICY tenant_isolation ON invoices
33
+ USING (organization_id = current_setting('app.current_org', true));
34
+ ```
35
+
36
+ The key is the setting name **your** policies read. The value names which piece
37
+ of Ablo's authenticated identity fills it.
38
+
39
+ ## What Ablo sets on its own
40
+
41
+ Every direct write runs inside a transaction that begins by setting this
42
+ context, whether or not you map anything:
43
+
44
+ | Setting | Carries |
45
+ | --- | --- |
46
+ | `app.current_org_id` | The organization the credential acts for |
47
+ | `app.current_project_id` | The project |
48
+ | `app.current_environment` | The environment |
49
+ | `app.current_sandbox_id` | The sandbox, when the write is in one |
50
+ | `app.current_participant_id` | The participant making the write |
51
+ | `app.current_participant_kind` | Whether that participant is a person, an agent, or the system |
52
+ | `app.current_user_id` | The person on whose behalf the write is made |
53
+
54
+ If your policies read these names directly, you need no mapping at all — this
55
+ page is for the case where they read different ones.
56
+
57
+ `app.current_user_id` is worth reading twice, because it has three states rather
58
+ than two. It carries a person's id when a person is behind the write. It carries
59
+ `*` when a backend credential is acting as the organization itself, which is the
60
+ authority a server-side key holds. And it carries the empty string when no
61
+ identity could be established — written explicitly rather than left alone, so a
62
+ policy on a pooled connection reads absence as absence and denies, instead of
63
+ inheriting whatever the previous transaction left behind.
64
+
65
+ ## What a mapping may name
66
+
67
+ The value side is a closed set, and every member is resolved by Ablo from the
68
+ authenticated key and the plane:
69
+
70
+ `orgId` · `projectId` · `environment` · `sandboxId` · `participantId` ·
71
+ `participantKind`
72
+
73
+ Because none of them come from the caller, a mapping can forward the tenant
74
+ identity Ablo already trusts, but cannot widen what a writer sees. A setting name
75
+ takes exactly one source — the name is the key — so naming the same setting twice
76
+ is unrepresentable rather than something to resolve later.
77
+
78
+ ## What a mapping may not name
79
+
80
+ The settings in the table above, along with `row_security`, `search_path`,
81
+ `statement_timeout`, and `lock_timeout`, are reserved. `defineSchema` rejects a
82
+ mapping onto any of them, and the engine refuses one at write time too.
83
+
84
+ The reason is worth stating plainly: those settings are how Ablo bounds its own
85
+ write. A schema that could reassign them could relax the scoping under which
86
+ Ablo writes, which would put the boundary inside the thing being bounded. Point
87
+ your policies at a name you own — `app.current_org` rather than
88
+ `app.current_org_id` — and map that.
89
+
90
+ ## Reads served from the log
91
+
92
+ One arrangement cannot honour a policy that names a person. When a plane is
93
+ served from its retained log rather than from its tables, every row carries the
94
+ organization and the project, but not the owner — so a rule about who owns a row
95
+ has nothing to act on.
96
+
97
+ Rather than fold those rows and return a plausible answer, such a read is
98
+ declined whole with `user_scope_not_enforced`: a member reading a colleague's
99
+ private records would otherwise be indistinguishable from a member reading their
100
+ own. Reads made by a credential acting for the organization are unaffected, as is
101
+ every plane served from its tables.
102
+
103
+ ## Related
104
+
105
+ - [Data Sources](./data-sources.md) — the writer role's privileges, and what it
106
+ can and cannot do to your database.
107
+ - [Operating on Your Database](./operating-on-your-database.md) — which actions
108
+ are read-only, which are reversible, and which belong to a human.
package/docs/sessions.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Sessions
2
2
 
3
+ > Short-lived scoped credentials your backend mints for a browser or an agent.
4
+
3
5
  A **session** is a short-lived credential your backend mints with its `sk_` and
4
6
  hands to one actor — a signed-in **person's browser** or a scoped **agent**. It's
5
7
  the same primitive in both cases (backend-minted, short-lived, scoped); the only
@@ -16,7 +18,7 @@ const userSession = await ablo.sessions.create({
16
18
  // A scoped agent session — gated to exactly the operations you name.
17
19
  const agentSession = await ablo.sessions.create({
18
20
  agent: { id: 'agent:task-writer' },
19
- can: { Task: ['read', 'update'], Deck: ['read'] },
21
+ can: { Task: ['read', 'update'], Workspace: ['read'] },
20
22
  });
21
23
  ```
22
24
 
package/docs/webhooks.md CHANGED
@@ -1,7 +1,9 @@
1
1
  # Webhooks
2
2
 
3
+ > Stream the committed transaction log to your own systems as signed events.
4
+
3
5
  Ablo keeps an ordered transaction log of every committed change and coordinates
4
- the writers — people and agents — that produce it. Your rows live in your own
6
+ the writers — agents, and the people alongside them — that produce it. Your rows live in your own
5
7
  database; Ablo holds only the log. **Webhooks stream that log to your systems as
6
8
  signed events:** every committed change is POSTed to an endpoint in your app, and
7
9
  your handler decides what to do with it.