@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
package/docs/identity.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Identity & Sync Groups
2
2
 
3
+ > Who is connecting, and which slice of state they are allowed to see.
4
+
3
5
  This is the doc the Quickstart skips: **who is connecting, and which slice
4
6
  of shared state do they get?** If you've wired `<AbloProvider client={ablo}>`
5
7
  and wondered where org / team / user actually come from — start here.
@@ -20,7 +22,7 @@ that.
20
22
  ## What a sync group is
21
23
 
22
24
  A **sync group** is a named channel of shared state — a string like
23
- `org:acme` or `deck:abc123`. It is simultaneously:
25
+ `org:acme` or `workspace:abc123`. It is simultaneously:
24
26
 
25
27
  - **the unit of fan-out** — a confirmed write to a row publishes a delta to
26
28
  every participant subscribed to that row's sync group(s), and
@@ -38,7 +40,7 @@ runnable place, so the concepts below have code to attach to.
38
40
  The entire declaration surface is: `identityRoles` (who may see what), and on
39
41
  each model `scope` / `parent` / `grants` (which group a row fans out on), plus
40
42
  optional `syncGroups` at session-mint time (narrowing). Read the three blocks first —
41
- a human gets their `org` / `team` scope, an agent gets one `deck` — then the
43
+ a human gets their `org` / `team` scope, an agent gets one `workspace` — then the
42
44
  sections after explain each.
43
45
 
44
46
  ```ts
@@ -47,20 +49,18 @@ import { defineSchema, identityRole, relation, model, z } from '@abloatai/ablo/s
47
49
 
48
50
  export const schema = defineSchema(
49
51
  {
50
- // A scope root: its rows form the group `deck:<id>` (kind from `groups.root`).
52
+ // A scope root: its rows form the group `workspace:<id>` (kind from `groups.root`).
51
53
  // Tenant isolation defaults to a row-local `organization_id` column, so no
52
54
  // `policy` is needed here.
53
- decks: model(
55
+ workspaces: model(
54
56
  { title: z.string(), status: z.enum(['draft', 'published']) },
55
- {},
56
- { groups: { root: 'deck' } },
57
+ { groups: { root: 'workspace' } },
57
58
  ),
58
- // A child: it has no group of its own; it inherits its deck's group via the
59
- // `parent` edge. A write to a slide reaches everyone viewing the deck.
60
- slides: model(
61
- { deckId: z.string() },
62
- { deck: relation.belongsTo('decks', 'deckId', { parent: true }) },
63
- {},
59
+ // A child: it has no group of its own; it inherits its workspace's group via the
60
+ // `parent` edge. A write to a document reaches everyone viewing the workspace.
61
+ documents: model(
62
+ { workspaceId: z.string() },
63
+ { relations: { workspace: relation.belongsTo('workspaces', 'workspaceId', { parent: true }) } },
64
64
  ),
65
65
  },
66
66
  {
@@ -88,12 +88,12 @@ export const schema = defineSchema(
88
88
  // 3. an AGENT run inherits its user, narrowed to the entities in play.
89
89
  // You narrow at SESSION-MINT time: your backend calls `sessions.create` with the
90
90
  // agent's allowed `syncGroups`, built from each model's scope via the
91
- // `syncGroup(kind, id)` helper — never a hand-built `deck:<id>` string. The agent's
91
+ // `syncGroup(kind, id)` helper — never a hand-built `workspace:<id>` string. The agent's
92
92
  // runtime then connects with the minted token.
93
93
  const session = await server.sessions.create({
94
94
  agent: { id: agentId },
95
- can: { Deck: ['read', 'update'] },
96
- syncGroups: [syncGroup('deck', deckId)], // floor: just the deck it's working on
95
+ can: { Workspace: ['read', 'update'] },
96
+ syncGroups: [syncGroup('workspace', workspaceId)], // floor: just the workspace it's working on
97
97
  });
98
98
  // the agent runtime authenticates with the minted token
99
99
  const ablo = Ablo({ schema, apiKey: session.token });
@@ -103,27 +103,27 @@ That's the whole surface. The rest of this doc is the *why* behind each line.
103
103
 
104
104
  ## Two kinds of group — the whole mental model
105
105
 
106
- You just saw a human get `org` / `team` groups and an agent get one `deck`
106
+ You just saw a human get `org` / `team` groups and an agent get one `workspace`
107
107
  group. That split is the model. Every sync group is named after one of two
108
108
  things:
109
109
 
110
110
  - **Membership groups** — named after *who you are*: `org:{id}`, `team:{id}`,
111
111
  `user:{id}`. Produced from **identity** (`identityRoles`, Half 1). They're
112
112
  standing and durable — they don't change as you work.
113
- - **Entity groups** — named after *a thing*: `dataroom:{id}`, `deck:{id}`,
114
- `slide:{id}`. Produced from a **row's id** (a model's entity scope, Half 2).
113
+ - **Entity groups** — named after *a thing*: `dataroom:{id}`, `workspace:{id}`,
114
+ `document:{id}`. Produced from a **row's id** (a model's entity scope, Half 2).
115
115
  They're granular — one per record — and any participant can be pointed at a
116
116
  specific set of them.
117
117
 
118
- Humans and agents fill that same space differently, and you declare the two in
119
- different places. A human's groups come from who they are, so you declare them
120
- once in the schema. An agent's groups come from what it's working on right now,
121
- so you pass them in code when you start the run.
118
+ Agents and people fill that same space differently, and you declare the two in
119
+ different places. An agent's groups come from what it's working on right now, so
120
+ you pass them in code when you start the run. A person's groups come from who
121
+ they are, so you declare them once in the schema.
122
122
 
123
123
  | | Subscribed by | Declared where | Gets |
124
124
  | --- | --- | --- | --- |
125
125
  | **Human** | *who they are* — membership | **the schema** (`identityRoles`) — a rule, written once | every `org` / `team` / `user` group their identity implies — their whole standing world |
126
- | **Agent** | *what it's been given* — entities | **code, at the spawn site** — chosen per run | a handful of entity groups: the dataroom it's in, the slides it has read — never beyond what its user's membership could reach |
126
+ | **Agent** | *what it's been given* — entities | **code, at the spawn site** — chosen per run | a handful of entity groups: the dataroom it's in, the documents it has read — never beyond what its user's membership could reach |
127
127
 
128
128
  > **One line:** humans subscribe by who they are; agents subscribe by what
129
129
  > they've been given.
@@ -135,9 +135,9 @@ depends on *what it's working on*, which is only knowable at dispatch — so you
135
135
  pass its `syncGroups` **when your backend mints the agent session**
136
136
  (`sessions.create({ agent, can, syncGroups })`). The schema's
137
137
  only job for entities is to declare *that* a model is
138
- entity-scopable and *what its group is named* (`scope: 'deck'` → `deck:{id}`);
138
+ entity-scopable and *what its group is named* (`scope: 'workspace'` → `workspace:{id}`);
139
139
  it never declares *which* entities a given agent gets. (A human can opt into the
140
- same runtime narrowing — a page scoped to one deck — but by default a human's
140
+ same runtime narrowing — a page scoped to one workspace — but by default a human's
141
141
  scope is fully schema-derived.)
142
142
 
143
143
  So an agent doesn't need a `user:{id}` standing grant. It's a participant pointed
@@ -212,7 +212,7 @@ import { defineSchema, identityRole, model, z } from '@abloatai/ablo/schema';
212
212
 
213
213
  export const schema = defineSchema(
214
214
  {
215
- decks: model({
215
+ workspaces: model({
216
216
  title: z.string(),
217
217
  status: z.enum(['draft', 'published']),
218
218
  }),
@@ -247,28 +247,30 @@ declarations, in order of how often you reach for them:
247
247
  **`groups.root` — this model is a scope root.** Its rows form a group of their
248
248
  own. The kind comes from the model's `typename` by default, or pass a string to
249
249
  set it explicitly (use the string form when the wire kind differs from the
250
- typename, e.g. typename `SlideDeck` but group `deck:<id>`):
250
+ typename, e.g. typename `SlideDeck` but group `workspace:<id>`):
251
251
 
252
252
  ```ts
253
- decks: model({ title: z.string() }, {}, { groups: { root: 'deck' } });
254
- // a deck row → group `deck:<id>`
253
+ workspaces: model({ title: z.string() }, { groups: { root: 'workspace' } });
254
+ // a workspace row → group `workspace:<id>`
255
255
  ```
256
256
 
257
257
  **`parent` — this row lives inside another entity.** Mark the `belongsTo` edge
258
258
  to its owner; the row inherits that owner's group. This is the Zanzibar/ReBAC
259
259
  *parent* relation — "access inherits from parent" — and it chains transitively
260
- (a layer → its slide → its deck), so a write to any descendant reaches everyone
260
+ (a block → its document → its workspace), so a write to any descendant reaches everyone
261
261
  viewing the root. A *reference* (a provenance/template pointer, not ownership)
262
262
  must **not** be marked `parent`, or the row would leak into an unrelated scope:
263
263
 
264
264
  ```ts
265
- slides: model(
266
- { deckId: z.string(), sourceSlideId: z.string().optional() },
265
+ documents: model(
266
+ { workspaceId: z.string(), sourceSlideId: z.string().optional() },
267
267
  {
268
- deck: relation.belongsTo('decks', 'deckId', { parent: true }), // ownership → inherit deck:<id>
269
- sourceSlide: relation.belongsTo('slides', 'sourceSlideId'), // reference → NOT routed
268
+ // default policy: row-local organization_id
269
+ relations: {
270
+ workspace: relation.belongsTo('workspaces', 'workspaceId', { parent: true }), // ownership → inherit workspace:<id>
271
+ sourceSlide: relation.belongsTo('documents', 'sourceSlideId'), // reference → NOT routed
272
+ },
270
273
  },
271
- {}, // default policy: row-local organization_id
272
274
  );
273
275
  ```
274
276
 
@@ -288,10 +290,12 @@ org membership is already covered by the `org:` identity role.
288
290
  dataroomMember: model(
289
291
  { userId: z.string(), dataroomId: z.string() },
290
292
  {
291
- member: relation.belongsTo('users', 'userId'),
292
- room: relation.belongsTo('datarooms', 'dataroomId'),
293
+ relations: {
294
+ member: relation.belongsTo('users', 'userId'),
295
+ room: relation.belongsTo('datarooms', 'dataroomId'),
296
+ },
297
+ groups: { grants: { subject: 'member', scope: 'room' } },
293
298
  },
294
- { groups: { grants: { subject: 'member', scope: 'room' } } },
295
299
  );
296
300
  ```
297
301
 
@@ -398,7 +402,7 @@ What carries identity — and just as importantly, what does *not* set the bound
398
402
  | ------------ | ------------------------------------------------------------------------------------------------ |
399
403
  | `userId` prop | App-level participant id, used for app-owned fields and read by your `identityRole` `source`. **Not** the security boundary — the server enforces scope from the authenticated request. |
400
404
  | `teamIds` (on the client) | Team ids expanded into team sync groups via your `identityRoles`. |
401
- | `syncGroups` (at session mint) | Optional. **Narrows** a minted session's subscription to a subset of what auth already allows — it can never widen it. Passed to `sessions.create({ user \| agent, syncGroups })`; build entries with `syncGroup(kind, id)`. Use it to scope an agent (or a focused page's session) to one entity, e.g. `[syncGroup('deck', 'abc123')]`. |
405
+ | `syncGroups` (at session mint) | Optional. **Narrows** a minted session's subscription to a subset of what auth already allows — it can never widen it. Passed to `sessions.create({ user \| agent, syncGroups })`; build entries with `syncGroup(kind, id)`. Use it to scope an agent (or a focused page's session) to one entity, e.g. `[syncGroup('workspace', 'abc123')]`. |
402
406
 
403
407
  Because the server is the boundary, a client that changes `userId` to another
404
408
  user's id does not gain their data — the server resolves and enforces the real
@@ -433,21 +437,21 @@ an entity anchor on the models an agent operates on:
433
437
 
434
438
  ```ts
435
439
  // each scope-root model an agent edits forms a per-entity group
436
- documents: model({ /* … */ }, {}, { groups: { root: 'document' } }),
437
- decks: model({ /* … */ }, {}, { groups: { root: 'deck' } }),
440
+ documents: model({ /* … */ }, { groups: { root: 'document' } }),
441
+ workspaces: model({ /* … */ }, { groups: { root: 'workspace' } }),
438
442
  ```
439
443
 
440
444
  Then a run subscribes only to the entity groups for the rows it works on — a
441
445
  subset of what its user could see:
442
446
 
443
447
  ```ts
444
- // agent run triggered by `user`, working on one document + one deck.
448
+ // agent run triggered by `user`, working on one document + one workspace.
445
449
  // Your backend mints the agent session narrowed to just the entities in play
446
450
  // (the floor). Build each group from the model's scope with `syncGroup(kind, id)`.
447
451
  const session = await server.sessions.create({
448
452
  agent: { id: agentId },
449
- can: { Document: ['read', 'update'], Deck: ['read', 'update'] },
450
- syncGroups: [syncGroup('document', documentId), syncGroup('deck', deckId)],
453
+ can: { Document: ['read', 'update'], Workspace: ['read', 'update'] },
454
+ syncGroups: [syncGroup('document', documentId), syncGroup('workspace', workspaceId)],
451
455
  });
452
456
  // identity (the ceiling) is inherited from the triggering user via your
453
457
  // session-mint logic; the agent runtime connects with the minted token.
@@ -491,9 +495,9 @@ it claimed.
491
495
  ## Narrowing to specific entities
492
496
 
493
497
  A human gets their full membership automatically (`identityRoles`). There are
494
- three ways to narrow a participant to specific entities — a page on one deck, or
498
+ three ways to narrow a participant to specific entities — a page on one workspace, or
495
499
  an agent pointed at the entities it's working on. You **never hand-write**
496
- `deck:<id>`; build groups from the model's `scope` (Half 2) with the typed
500
+ `workspace:<id>`; build groups from the model's `scope` (Half 2) with the typed
497
501
  `syncGroup(kind, id)` helper from `@abloatai/ablo/schema`.
498
502
 
499
503
  1. **At session mint — `syncGroups`.** When your backend mints a session, pass the
@@ -501,13 +505,13 @@ an agent pointed at the entities it's working on. You **never hand-write**
501
505
  the way to scope a focused page's session):
502
506
 
503
507
  ```ts
504
- // an agent working across two decks and a document
508
+ // an agent working across two workspaces and a document
505
509
  const session = await server.sessions.create({
506
510
  agent: { id: agentId },
507
- can: { Deck: ['read', 'update'], Document: ['read'] },
511
+ can: { Workspace: ['read', 'update'], Document: ['read'] },
508
512
  syncGroups: [
509
- syncGroup('deck', deckA),
510
- syncGroup('deck', deckB),
513
+ syncGroup('workspace', deckA),
514
+ syncGroup('workspace', deckB),
511
515
  syncGroup('document', docId),
512
516
  ],
513
517
  });
@@ -525,9 +529,9 @@ an agent pointed at the entities it's working on. You **never hand-write**
525
529
  [Coordination](./coordination.md).
526
530
 
527
531
  > **`groups.root` is the schema model option, not a client setting.**
528
- > `groups: { root: 'deck' }` in `model(...)` declares a scope root
532
+ > `groups: { root: 'workspace' }` in `model(...)` declares a scope root
529
533
  > ([Half 2](#half-2--per-model-scope-row--group)) — it names the group
530
- > (`deck:<id>`) that the mechanisms above then subscribe to.
534
+ > (`workspace:<id>`) that the mechanisms above then subscribe to.
531
535
  > There is no `Ablo({ scope })` constructor option. The lifecycle filter on
532
536
  > [`list()`](./api.md#model-methods) is a separate axis named **`state`**
533
537
  > (`'live' | 'archived' | 'all'`, GitHub's open/closed/all), precisely so it
@@ -536,7 +540,7 @@ an agent pointed at the entities it's working on. You **never hand-write**
536
540
  > **Requested groups never grant.** At connect, the server intersects the session's
537
541
  > `syncGroups` with what the identity is actually allowed (`requested ∩ allowed`).
538
542
  > So `syncGroups` only ever *narrows* within a participant's ceiling — an agent
539
- > can't reach a deck its capability doesn't already permit, no matter what it
543
+ > can't reach a workspace its capability doesn't already permit, no matter what it
540
544
  > passes. Smaller bootstrap, less fan-out, same server-enforced boundary.
541
545
 
542
546
  ## How this compares — and the best practices it follows
@@ -583,7 +587,7 @@ The best practices Ablo inherits from that lineage:
583
587
  never the boundary. This is why changing `userId` in the browser grants nothing.
584
588
 
585
589
  3. **Scope by a hierarchical naming convention, declared once.** Ablo's `kind:id`
586
- group naming (`org:…` / `team:…` from `identityRoles`, `deck:…` from a model's
590
+ group naming (`org:…` / `team:…` from `identityRoles`, `workspace:…` from a model's
587
591
  `scope`) is the same idea as [Liveblocks' recommended room-id naming pattern](https://liveblocks.io/docs/authentication/access-token)
588
592
  (`org:*`, `org:group:*`) and [Ably's channel capabilities](https://ably.com/docs/auth/capabilities).
589
593
  Declaring the convention in one place — never composing scope strings in
package/docs/index.md CHANGED
@@ -1,101 +1,189 @@
1
1
  # Ablo Docs
2
2
 
3
- You have a database, and you want an AI agent to edit the same rows your
4
- users are editing — without the two clobbering each other's work. Ablo gives
5
- the agent a narrow, audited write path: you declare your models, then everyone
6
- (React components, server actions, and agents) calls the same
7
- `ablo.deck.update(...)`. Ablo streams confirmed changes to everyone live and
8
- rejects any write based on stale data.
3
+ > The agentic coordination layer: one API for AI agents, apps, and services to claim, change, and confirm the same rows.
9
4
 
10
- The flow is four steps: declare your models, read the current rows, claim the
11
- row you're about to change, then write — and the write is rejected if someone
12
- changed the row first.
5
+ Two agents reach for the same row. One claims it, does slow work an LLM call,
6
+ a fetch, a chain of tools — and commits. The second is neither rejected nor
7
+ allowed to clobber: it waits in line, is handed the row as it now stands, and
8
+ proceeds. Contention becomes an ordering problem instead of a retry loop.
13
9
 
14
10
  ```ts
15
- // The same call, whether a person, a server action, or an agent makes it.
16
- await ablo.deck.update({ id: deckId, data: { title: "Q3 Strategy" } });
11
+ // Take the row. Anyone else who wants it waits, then reads it fresh.
12
+ await using claim = await ablo.reports.claim({ id: reportId });
13
+
14
+ await ablo.reports.update({
15
+ id: claim.data.id,
16
+ data: { forecast: await generateForecast(claim.data) },
17
+ wait: 'confirmed',
18
+ });
17
19
  ```
18
20
 
19
- Claims don't lock. If another writer holds the row, `claim` waits for them,
20
- re-reads the fresh row, then hands it to you so two writers serialize
21
- instead of clobbering.
22
-
23
- ## What you get
24
-
25
- Three things stay true no matter how you use Ablo:
26
-
27
- - **One model API for every actor.** `ablo.<model>.update(...)` is the
28
- call from React components, server actions, background workers, and
29
- AI agents alike. No separate "agent SDK," no parallel mutation path.
30
- Attribution comes from the credential, not the call site.
31
- - **You declare tenancy scopes once.** Tenancy / per-entity scope
32
- prefixes (`org:`, `deck:`, or your own `region:` / `customer:`) are
33
- declared once on the schema's `identityRoles`, so application code
34
- never builds an `org:123` string by hand — which keeps tenant
35
- boundaries from leaking.
36
- - **Stale writes are rejected.** If the row changed after you read it,
37
- your write is turned away instead of silently overwriting the change
38
- you didn't see.
39
-
40
- ## Start here
41
-
42
- - [Quickstart](./quickstart.md) — Make your first schema-backed write.
43
- - [Schema Contract](./schema-contract.md) — One schema becomes typed model clients, React reads, agent writes, Data Source shape, and schema push.
44
- - [CLI & Migrations](./cli.md) — `init` / `migrate` / `push` / `generate`, the shared Zod→Postgres type map, and structured migration errors.
45
- - [Identity & Sync Groups](./identity.md) — Use your own authentication; tell Ablo who's connecting and how org / team / user map to sync-group scope.
46
- - [Integration Guide](./integration-guide.md) — Connect your database via Data Source, plus React, multiplayer, and agent patterns.
47
- - [Guarantees](./guarantees.md) — What confirmed writes, stale checks, and claims guarantee.
48
- - [Interaction Model](./interaction-model.md) — The schema, claim, update, confirmation loop.
49
- - [API Reference](./api.md) — Model-by-model method shape.
50
- - [Client Behavior](./client-behavior.md) — Options, errors, retries, timeouts, and imports.
51
- - [Debugging & Logs](./debugging.md) — Turn on the `[Ablo]` coordination trace (`debug` / `logLevel`) to watch claims, queueing, and grants while you build — or read the same activity in code via `ClaimLog` to render an activity feed.
52
- - [Connect Your Database](./data-sources.md) — Keep canonical rows in your app database without giving Ablo database credentials.
53
- - [React](./react.md) — Provider, hooks, and reactive reads for React apps.
54
- - [API Keys](./api-keys.md) — Bearer tokens for the public API.
55
-
56
- ## API shape
57
-
58
- | Plane | Primitives | Purpose |
59
- |---|---|---|
60
- | State | `Schema`, `Model`, `Claim`, `Receipt` | The product path. Load, coordinate, write, confirm. |
61
- | Storage | `Data Source` | Your rows live in your own database behind a signed Data Source endpoint. |
62
-
63
- ## Use cases
64
-
65
- - **Let agents write to shared state** — Give an AI agent scoped, revocable write access to your typed data.
66
- - **Coordinate multiple actors** — Use claims to show pre-write work across humans and agents.
67
- - **Audit every agent action** — Trace any write back to a human in one query.
68
- - **Build collaborative editors** — Humans and agents on the same record, with realtime updates and stale-read protection.
69
- - **Meter and gate API usage** — Per-key, per-team usage reports and quota enforcement.
70
- - **Integrate with A2A and MCP** — Speak the same protocols as Claude, Cursor, Gemini.
21
+ Claims do not lock. A lock is held against a caller who may never come back; a
22
+ claim is a durable lease with a wait-line behind it, so you can always ask who
23
+ holds a row and who is queued for it. The write returns a receipt, and a write
24
+ based on a row that has since changed is turned away rather than applied.
71
25
 
72
- ## Concepts
26
+ ## What people build
73
27
 
74
- - [Schema Contract](./schema-contract.md) — What the schema drives across SDK, React, agents, Data Source, and migrations.
75
- - [Model Methods](./api.md#model-methods) Load and write typed state.
76
- - [Integration Guide](./integration-guide.md) The normal app path and optional pieces.
77
- - [Guarantees](./guarantees.md) — Confirmed writes, optimistic state, stale-write protection, and agent lifecycle.
78
- - [Coordination](./coordination.md) — `claim`, `claim.state`, and `claim.queue` for active work.
79
- - [Connect Your Database](./data-sources.md) Where data lands when your app database is canonical.
80
- - [Receipt](./api.md#receipt) Confirm what landed.
81
- - [Usage](./api.md#usage) — Metering and audit dimensions.
82
- - [Audit Log](./audit.md) — Trace any confirmed write back to the human behind it.
83
- - [MCP](./mcp.md) — Expose Ablo models to MCP clients (Claude, Cursor).
28
+ <Columns>
29
+ <Card title="Run agents in parallel" icon="users" href="/coordination">
30
+ Many agents over one dataset. Claims put them in a line instead of a race.
31
+ </Card>
32
+
33
+ <Card title="Hand work between agents" icon="arrow-left-right" href="/agent-messaging">
34
+ One agent claims, works, releases. The next picks up with the fresh row and a durable note about why.
35
+ </Card>
84
36
 
85
- ## Examples
37
+ <Card title="Scope what an agent may write" icon="key-round" href="/api-keys">
38
+ A revocable key bound to one project's models. Attribution comes from the credential, not the call site.
39
+ </Card>
40
+
41
+ <Card title="Confirm what landed" icon="receipt" href="/guarantees">
42
+ Every write returns a receipt. Nothing is fire-and-forget, and stale writes are rejected.
43
+ </Card>
44
+
45
+ <Card title="Audit every agent action" icon="scroll-text" href="/audit">
46
+ Trace any committed change back to the key that made it, and to the person who authorized that key.
47
+ </Card>
48
+
49
+ <Card title="Keep a person in the loop" icon="hand" href="/react">
50
+ Add the `humans()` plugin and people get presence and live queries. A person's claim is just another holder the agent waits behind.
51
+ </Card>
52
+ </Columns>
53
+
54
+ ## Using Ablo
55
+
56
+ <Steps>
57
+ <Step title="Declare the models agents share">
58
+ `npx ablo init` scaffolds `ablo/schema.ts`, the typed client, and the type registration.
59
+ Declare only the models agents coordinate over — your auth, billing, and everything else
60
+ stay in your own migrations.
61
+
62
+ ```bash
63
+ npx ablo init && npx ablo push
64
+ ```
65
+
66
+ `push` is the step everything depends on: the server keeps its own copy of the schema, and
67
+ until it has yours, a write to a new model fails with `server_execute_unknown_model`.
68
+ </Step>
69
+
70
+ <Step title="Connect the database the rows live in">
71
+ Ablo writes through a scoped role and confirms by tailing your write-ahead log. It runs no
72
+ DDL and owns no schema — your migration tool stays in charge of the shape of your database.
73
+
74
+ ```bash
75
+ npx ablo connect
76
+ ```
77
+
78
+ No database yet? Pass an `apiKey` only and Ablo keeps the rows in its own log, so you can
79
+ build the whole system today and point it at Postgres when you are ready.
80
+ </Step>
81
+
82
+ <Step title="Build with Ablo">
83
+ You are writing the agent yourself — a worker, a job handler, a tool inside a model loop.
84
+ Agents hold no socket; the credential is the identity.
85
+
86
+ ```ts
87
+ const ablo = Ablo({ schema, apiKey: process.env.ABLO_API_KEY, transport: 'http' });
88
+ ```
89
+
90
+ Read with `list` / `retrieve`, coordinate with `claim`, write with `create` / `update` /
91
+ `delete`. See [Agents](./agents.md) for the loop and [API Reference](./api.md) for the shape.
92
+ </Step>
86
93
 
87
- - [AI SDK Tool](./examples/ai-sdk-tool.md) — Put Ablo inside an AI SDK tool call.
88
- - [Existing Python Backend](./examples/existing-python-backend.md) Add multiplayer and future agent writes without replacing a Python API server.
89
- - [Agent + Human](./examples/agent-human.md) Yield when a human is editing the same report.
90
- - [Server Agent](./examples/server-agent.md) — Schema-backed worker.
91
- - [Next.js](./examples/nextjs.md) — App-router setup with React bindings.
94
+ <Step title="Or point an MCP host at it">
95
+ The agent is Claude, Cursor, or another MCP host, and you want it operating your data
96
+ directly. The coordination server exposes the same claim-and-commit loop as tools.
92
97
 
93
- ## Runtime builds
98
+ ```bash
99
+ claude mcp add ablo -- npx -y @abloatai/mcp
100
+ ```
94
101
 
95
- - `@abloatai/ablo`schema-powered sync client for typed model operations, realtime claims, and receipts.
102
+ See [Model Context Protocol](./mcp.md) and read the surface table below before you pick,
103
+ because Ablo publishes two MCP servers and only one of them is a data plane.
104
+ </Step>
105
+ </Steps>
106
+
107
+ ## Surfaces
108
+
109
+ Every surface reaches the same coordinated state. Pick by who is calling.
110
+
111
+ | Surface | Use it for |
112
+ |---|---|
113
+ | **SDK** — `@abloatai/ablo`, `transport: 'http'` | The agents themselves. Stateless, request/response, nothing held open. The main path. |
114
+ | **Coordination MCP** — `@abloatai/mcp` | An agent living inside an MCP host that needs claim and commit as tools. A data plane. |
115
+ | **`humans()`** — with `@abloatai/ablo/react` | The interfaces a person watches agent work arrive in: presence, live queries, a local copy. |
116
+ | **CLI** — `ablo` | Scaffolding, schema push, connecting a database. Terminals and CI. |
117
+ | **REST** — `/api/v1` | Runtimes with no SDK. |
118
+ | **Integration-helper MCP** — hosted `/api/mcp` | Teaching a coding assistant the SDK while you build. Docs, lint, and scaffolds only. |
119
+
120
+ The two MCP servers are not interchangeable. The coordination server changes
121
+ your data; the integration-helper server serves documentation and has no
122
+ per-model data tools at all. An agent that edits rows uses the SDK or the
123
+ coordination server — never the helper.
124
+
125
+ ### Where people fit
126
+
127
+ The bare client is the coordination layer: commit, read, observe, claim. People
128
+ are something you add to it. `humans()` is the plugin that declares the local,
129
+ watchable copy — the offline store, live queries, presence, and the framework
130
+ bindings — and it needs a duplex connection, so a stateless agent cannot install
131
+ it and is told so at construction rather than left with a subscription that never
132
+ delivers.
133
+
134
+ There is no `agents()` plugin, and the absence is the point: agents are the
135
+ default caller, not a special one.
136
+
137
+ ## Concepts
138
+
139
+ - [Coordination](./coordination.md) — `claim`, `claim.state`, and `claim.queue`: who holds a row, and who is waiting.
140
+ - [Concurrency Convention](./concurrency-convention.md) — the governing rule for how concurrent writes resolve.
141
+ - [Guarantees](./guarantees.md) — what a confirmed write, a stale-write rejection, and a claim each promise.
142
+ - [Idempotency](./idempotency.md) — make a retried write safe; what replays, what re-runs, and for how long.
143
+ - [Schema Contract](./schema-contract.md) — one schema becomes typed clients, agent writes, React reads, and the push.
144
+ - [Agents](./agents.md) — the stateless participant: wake, read, claim, commit, idle.
145
+ - [Agent Messaging](./agent-messaging.md) — durable handoffs between agents, linked to the claim they discuss.
146
+ - [Identity & Sync Groups](./identity.md) — who is connecting, and which slice of state they see.
147
+ - [Interaction Model](./interaction-model.md) — the schema, claim, update, confirmation loop.
148
+ - [Change Propagation](./groups.md) — how one row's change reaches the actors that depend on it.
149
+ - [Client Behavior](./client-behavior.md) — options, errors, retries, timeouts, and imports.
150
+
151
+ ## Authority
152
+
153
+ - [Projects](./projects.md) — one organization, many apps; each with its own schema, planes, and keys.
154
+ - [API Keys](./api-keys.md) — the credential that carries an agent's identity and its scopes.
155
+ - [Sessions](./sessions.md) — short-lived scoped credentials your backend mints.
156
+ - [Audit Log](./audit.md) — trace any confirmed write back to the person behind it.
157
+ - [Operating on Your Database](./operating-on-your-database.md) — which actions run freely, which to verify first, and which belong to a human.
158
+ - [Session Settings](./session-settings.md) — point your row-level-security policies at Ablo's writes, by naming the settings they already read.
159
+
160
+ ## Build
161
+
162
+ - [Quickstart](./quickstart.md) — make your first coordinated write.
163
+ - [Integration Guide](./integration-guide.md) — the canonical end-to-end integration.
164
+ - [CLI & Migrations](./cli.md) — `init` / `connect` / `push` / `migrate` / `generate`.
165
+ - [Connect Your Database](./data-sources.md) — where rows land when your own database is canonical.
166
+ - [Deployment](./deployment.md) — the database, the keys, and the schema push that take an integration to production.
167
+ - [React](./react.md) — provider, hooks, and reactive reads.
168
+ - [Webhooks](./webhooks.md) — react to confirmed change from outside the SDK.
169
+ - [Debugging & Logs](./debugging.md) — watch claims, queueing, and grants while you build.
170
+
171
+ ## Reference
172
+
173
+ - [API Reference](./api.md) — model-by-model method shape.
174
+ - [Errors](./errors.md) — the code registry, its categories, and what to do about each.
175
+ - [Version History & Migration](./migration.md) — every breaking change and its migration.
176
+ - [Changelog](../CHANGELOG.md) — what shipped recently.
177
+
178
+ ## Examples
179
+
180
+ - [AI SDK Tool](./examples/ai-sdk-tool.md) — put Ablo inside a model's tool call.
181
+ - [Agent + Human](./examples/agent-human.md) — yield when a person is holding the same report.
182
+ - [Server Agent](./examples/server-agent.md) — a schema-backed worker.
183
+ - [Existing Python Backend](./examples/existing-python-backend.md) — add coordination without replacing your API server.
184
+ - [Next.js](./examples/nextjs.md) — app-router setup with React bindings.
96
185
 
97
186
  ## More
98
187
 
99
188
  - [README](../README.md) — product overview and first example.
100
- - [AGENTS.md](../AGENTS.md) — short installation guidance for coding assistants.
101
- - [Changelog](../CHANGELOG.md) — what shipped recently.
189
+ - [AGENTS.md](../AGENTS.md) — installation guidance for coding assistants.
@@ -1,11 +1,13 @@
1
1
  # Integration Guide
2
2
 
3
- If humans and AI agents both edit the same records in your app, they overwrite
4
- each other and there's no good place to coordinate. Ablo gives them one shared,
5
- typed write path the same `ablo.<model>.update(...)` call for a React
6
- component, a server action, a background worker, or an agent and reconciles the
7
- edits. This guide adds it to a product that already has a backend and database,
8
- one model at a time.
3
+ > The canonical end-to-end integration, added to an existing product one model at a time.
4
+
5
+ When several AI agents edit the same records in your app — alongside any people
6
+ watching them work they overwrite each other, and there is no good place to
7
+ coordinate. Ablo gives them one shared, typed write path: the same
8
+ `ablo.<model>.update(...)` call from an agent, a background worker, a server
9
+ action, or a React component. This guide adds it to a product that already has a
10
+ backend and a database, one model at a time.
9
11
 
10
12
  Three things hold no matter which actor is writing:
11
13
 
@@ -79,7 +81,7 @@ and write path are ready for production.
79
81
  When handing this to a coding agent, give it a concrete target:
80
82
 
81
83
  ```txt
82
- Add Ablo to this app for one model that humans and agents both edit.
84
+ Add Ablo to this app for one model your agents edit.
83
85
  Use the org sandbox sk_test_* key. Declare schema, add the Ablo client, replace
84
86
  one write with ablo.<model>.update(..., { readAt, onStale: 'reject',
85
87
  wait: 'confirmed' }), and add a smoke test for two concurrent writers.
@@ -139,7 +141,6 @@ model(
139
141
  {
140
142
  /* fields */
141
143
  },
142
- /* relations */ {},
143
144
  {
144
145
  // Axis 1 — `policy`: who may READ a row (tenant isolation / RLS). A
145
146
  // row-local `organization_id` column is the default, so you omit this for
@@ -256,7 +257,7 @@ refreshes before expiry.
256
257
  Reads come in two flavors, and you pick based on whether you can wait.
257
258
  `retrieve({ id })` and `list({ where })` hit the server (and hydrate the local
258
259
  store) — they're async, so you `await` them. `get(id)` (positional),
259
- `getAll({ where })`, and `getCount({ where })` read the already-synced local
260
+ `local.list({ where })`, and `local.count({ where })` read the already-synced local
260
261
  graph synchronously, so they're the ones you call in render — and the ones you
261
262
  use inside a `useAblo` selector, never the async `retrieve`/`list`.
262
263
 
@@ -270,12 +271,12 @@ const report = await ablo.weatherReports.retrieve({ id: 'report_stockholm' });
270
271
  if (!report) throw new Error('report not found');
271
272
  ```
272
273
 
273
- Use `get`, `getAll`, and `getCount` for synchronous local-graph reads after
274
+ Use `local.retrieve`, `local.list`, and `local.count` for synchronous local-graph reads after
274
275
  data has synced.
275
276
 
276
277
  ```ts
277
- const report = ablo.weatherReports.get('report_stockholm');
278
- const activeReports = ablo.weatherReports.getAll({
278
+ const report = ablo.weatherReports.local.retrieve('report_stockholm');
279
+ const activeReports = ablo.weatherReports.local.list({
279
280
  where: { projectId: 'proj_123' },
280
281
  filter: (report) => report.status !== 'ready',
281
282
  orderBy: { updatedAt: 'desc' },
@@ -295,7 +296,7 @@ export function ReportRow({
295
296
  }: {
296
297
  report: { id: string; location: string; status: string };
297
298
  }) {
298
- const report = useAblo((ablo) => ablo.weatherReports.get(serverReport.id)) ?? serverReport;
299
+ const report = useAblo((ablo) => ablo.weatherReports.local.retrieve(serverReport.id)) ?? serverReport;
299
300
  const active = useAblo((ablo) => ablo.weatherReports.claim.state({ id: serverReport.id }));
300
301
 
301
302
  return <button disabled={Boolean(active) || report.status === 'ready'}>{report.location}</button>;
@@ -375,7 +376,7 @@ The migration can be gradual:
375
376
 
376
377
  1. Declare schema for one model, such as `reports`.
377
378
  2. Keep existing server loads for first paint.
378
- 3. Add `useAblo((ablo) => ablo.weatherReports.get(id)) ?? serverReport` for live rows.
379
+ 3. Add `useAblo((ablo) => ablo.weatherReports.local.retrieve(id)) ?? serverReport` for live rows.
379
380
  4. Add one Data Source endpoint that calls the existing service layer.
380
381
  5. Move one mutation button from `fetch('/api/reports/...')` to `ablo.weatherReports.update(...)`.
381
382
  6. Add an outbox/events path for writes that still happen outside Ablo.
@@ -507,8 +508,8 @@ them.
507
508
  | `retrieve({ id })` | Async read of one row from the server (await it). |
508
509
  | `list({ where })` | Async read of many rows from the server (await it). |
509
510
  | `get(id)` | Synchronous local read of one synced row (positional id; use in render). |
510
- | `getAll({ where })` | Synchronous local read of many synced rows. |
511
- | `getCount({ where })` | Synchronous local count of synced rows. |
511
+ | `local.list({ where })` | Synchronous local read of many synced rows. |
512
+ | `local.count({ where })` | Synchronous local count of synced rows. |
512
513
  | `create({ data, id? })` | Create through the model client. |
513
514
  | `update({ id, data, ...opts })` | Update through the model client. |
514
515
  | `delete({ id, ...opts })` | Delete through the model client. |