@abloatai/ablo 0.34.1 → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (483) hide show
  1. package/AGENTS.md +2 -1
  2. package/CHANGELOG.md +674 -5
  3. package/README.md +39 -22
  4. package/dist/BaseSyncedStore.d.ts +152 -44
  5. package/dist/BaseSyncedStore.js +300 -184
  6. package/dist/Database.d.ts +9 -24
  7. package/dist/Database.js +37 -22
  8. package/dist/InstanceCache.d.ts +25 -4
  9. package/dist/InstanceCache.js +48 -15
  10. package/dist/LazyReferenceCollection.d.ts +3 -3
  11. package/dist/LazyReferenceCollection.js +4 -4
  12. package/dist/Model.d.ts +6 -6
  13. package/dist/Model.js +10 -10
  14. package/dist/ModelRegistry.d.ts +4 -4
  15. package/dist/ModelRegistry.js +3 -3
  16. package/dist/{SyncEngineContext.d.ts → RuntimeContext.d.ts} +20 -13
  17. package/dist/{SyncEngineContext.js → RuntimeContext.js} +11 -12
  18. package/dist/SyncClient.d.ts +42 -32
  19. package/dist/SyncClient.js +166 -110
  20. package/dist/ai-sdk/coordinatedTool.d.ts +2 -2
  21. package/dist/ai-sdk/coordinatedTool.js +1 -1
  22. package/dist/ai-sdk/coordinationContext.d.ts +2 -2
  23. package/dist/ai-sdk/coordinationContext.js +1 -1
  24. package/dist/ai-sdk/wrap.d.ts +3 -3
  25. package/dist/ai-sdk/wrap.js +2 -2
  26. package/dist/auth/index.d.ts +1 -156
  27. package/dist/auth/index.js +8 -301
  28. package/dist/cli.cjs +3344 -1073
  29. package/dist/client/Ablo.d.ts +42 -287
  30. package/dist/client/Ablo.js +118 -963
  31. package/dist/client/abloClient.d.ts +309 -0
  32. package/dist/client/abloClient.js +13 -0
  33. package/dist/client/clientPrelude.d.ts +52 -0
  34. package/dist/client/clientPrelude.js +60 -0
  35. package/dist/client/consoleLogger.d.ts +2 -2
  36. package/dist/client/coreClient.d.ts +60 -0
  37. package/dist/client/coreClient.js +118 -0
  38. package/dist/client/createInternalComponents.d.ts +4 -4
  39. package/dist/client/createInternalComponents.js +9 -8
  40. package/dist/client/createModelProxy.d.ts +78 -373
  41. package/dist/client/createModelProxy.js +114 -86
  42. package/dist/client/humans.d.ts +48 -0
  43. package/dist/client/humans.js +52 -0
  44. package/dist/client/modelRegistration.d.ts +1 -1
  45. package/dist/client/modelRegistration.js +9 -9
  46. package/dist/client/options.d.ts +73 -17
  47. package/dist/client/reactiveEngine.d.ts +48 -0
  48. package/dist/client/reactiveEngine.js +910 -0
  49. package/dist/client/resourceTypes.d.ts +9 -250
  50. package/dist/client/resourceTypes.js +8 -5
  51. package/dist/client/schemaConfig.d.ts +4 -4
  52. package/dist/client/schemaConfig.js +6 -2
  53. package/dist/client/validateAbloOptions.d.ts +3 -2
  54. package/dist/client/validateAbloOptions.js +1 -1
  55. package/dist/client/wsMutationExecutor.d.ts +3 -3
  56. package/dist/client/wsMutationExecutor.js +3 -3
  57. package/dist/context.d.ts +9 -9
  58. package/dist/context.js +10 -9
  59. package/dist/coordination/ClaimLog.d.ts +26 -0
  60. package/dist/coordination/ClaimLog.js +32 -0
  61. package/dist/coordination/index.d.ts +1 -15
  62. package/dist/coordination/index.js +8 -31
  63. package/dist/core/DatabaseManager.js +1 -1
  64. package/dist/core/QueryView.d.ts +1 -1
  65. package/dist/core/QueryView.js +1 -1
  66. package/dist/core/StoreManager.d.ts +4 -23
  67. package/dist/core/StoreManager.js +5 -55
  68. package/dist/core/index.d.ts +2 -2
  69. package/dist/core/index.js +2 -2
  70. package/dist/core/storeContract.d.ts +2 -2
  71. package/dist/docs/catalog.d.ts +72 -0
  72. package/dist/docs/catalog.js +227 -0
  73. package/dist/docs/index.d.ts +10 -0
  74. package/dist/docs/index.js +10 -0
  75. package/dist/environment.d.ts +1 -40
  76. package/dist/environment.js +8 -37
  77. package/dist/index.d.ts +40 -34
  78. package/dist/index.js +26 -20
  79. package/dist/interfaces/index.d.ts +44 -134
  80. package/dist/keys/index.d.ts +1 -77
  81. package/dist/keys/index.js +8 -190
  82. package/dist/mutators/{RecordingTransaction.d.ts → RecordingMutation.d.ts} +4 -4
  83. package/dist/mutators/{RecordingTransaction.js → RecordingMutation.js} +2 -2
  84. package/dist/mutators/Transaction.d.ts +1 -1
  85. package/dist/mutators/Transaction.js +1 -1
  86. package/dist/mutators/UndoManager.d.ts +6 -6
  87. package/dist/mutators/UndoManager.js +5 -5
  88. package/dist/mutators/defineMutators.d.ts +3 -3
  89. package/dist/mutators/defineMutators.js +1 -1
  90. package/dist/mutators/inverseOp.js +2 -2
  91. package/dist/mutators/mutateActions.d.ts +3 -3
  92. package/dist/mutators/mutateActions.js +1 -1
  93. package/dist/mutators/readerActions.d.ts +1 -1
  94. package/dist/mutators/undoApply.d.ts +1 -1
  95. package/dist/mutators/undoApply.js +1 -1
  96. package/dist/policy/index.d.ts +2 -2
  97. package/dist/policy/index.js +1 -1
  98. package/dist/query/client.d.ts +2 -2
  99. package/dist/query/client.js +4 -4
  100. package/dist/query/types.d.ts +6 -41
  101. package/dist/query/types.js +2 -2
  102. package/dist/react/AbloProvider.d.ts +6 -8
  103. package/dist/react/AbloProvider.js +5 -7
  104. package/dist/react/context.d.ts +1 -1
  105. package/dist/react/context.js +1 -1
  106. package/dist/react/index.d.ts +5 -5
  107. package/dist/react/index.js +3 -3
  108. package/dist/react/internalContext.d.ts +1 -1
  109. package/dist/react/useAblo.d.ts +3 -3
  110. package/dist/react/useAblo.js +1 -1
  111. package/dist/react/useCurrentUserId.js +1 -1
  112. package/dist/react/useErrorListener.js +1 -1
  113. package/dist/react/useMutationFailureListener.d.ts +2 -2
  114. package/dist/react/useMutationFailureListener.js +1 -1
  115. package/dist/react/useMutators.d.ts +3 -3
  116. package/dist/react/useMutators.js +3 -3
  117. package/dist/react/useUndoScope.d.ts +5 -5
  118. package/dist/react/useUndoScope.js +1 -1
  119. package/dist/schema/coordination.d.ts +69 -10
  120. package/dist/schema/coordination.js +86 -9
  121. package/dist/schema/ddl.js +2 -2
  122. package/dist/schema/diff.d.ts +1 -1
  123. package/dist/schema/generate.js +1 -1
  124. package/dist/schema/index.d.ts +10 -10
  125. package/dist/schema/index.js +18 -18
  126. package/dist/schema/queries.d.ts +27 -27
  127. package/dist/schema/queries.js +23 -23
  128. package/dist/schema/select.d.ts +3 -3
  129. package/dist/schema/select.js +3 -3
  130. package/dist/schema/serialize.d.ts +15 -6
  131. package/dist/schema/serialize.js +17 -3
  132. package/dist/schema/sugar.d.ts +6 -7
  133. package/dist/schema/sugar.js +9 -12
  134. package/dist/schema/syncDeltaRow.d.ts +4 -152
  135. package/dist/schema/syncDeltaRow.js +4 -105
  136. package/dist/server/adapter.d.ts +18 -1
  137. package/dist/server/commit.d.ts +10 -16
  138. package/dist/server/index.d.ts +1 -1
  139. package/dist/server/index.js +1 -1
  140. package/dist/server/readConfig.d.ts +1 -1
  141. package/dist/source/adapters/drizzle.d.ts +1 -1
  142. package/dist/source/adapters/drizzle.js +2 -2
  143. package/dist/source/adapters/kysely.d.ts +1 -1
  144. package/dist/source/adapters/kysely.js +1 -1
  145. package/dist/source/adapters/kyselyMutationCore.d.ts +1 -1
  146. package/dist/source/adapters/kyselyMutationCore.js +2 -2
  147. package/dist/source/adapters/memory.js +1 -1
  148. package/dist/source/adapters/prisma.d.ts +8 -3
  149. package/dist/source/adapters/prisma.js +1 -1
  150. package/dist/source/connector.js +1 -1
  151. package/dist/source/connectorProtocol.d.ts +2 -8
  152. package/dist/source/connectorProtocol.js +3 -2
  153. package/dist/source/contract.d.ts +29 -17
  154. package/dist/source/contract.js +27 -22
  155. package/dist/source/factory.d.ts +1 -1
  156. package/dist/source/footprint.d.ts +111 -0
  157. package/dist/source/footprint.js +0 -0
  158. package/dist/source/idempotency.js +2 -2
  159. package/dist/source/index.d.ts +1 -0
  160. package/dist/source/index.js +3 -0
  161. package/dist/source/next.d.ts +1 -1
  162. package/dist/source/signing.d.ts +9 -2
  163. package/dist/source/signing.js +4 -1
  164. package/dist/source/types.d.ts +6 -4
  165. package/dist/source/types.js +1 -1
  166. package/dist/stores/ObjectStore.d.ts +1 -1
  167. package/dist/stores/SyncActionStore.d.ts +1 -1
  168. package/dist/stores/SyncActionStore.js +2 -10
  169. package/dist/stores/syncAction.d.ts +26 -0
  170. package/dist/stores/syncAction.js +16 -0
  171. package/dist/surface.d.ts +3 -3
  172. package/dist/surface.js +6 -4
  173. package/dist/sync/BootstrapFetcher.d.ts +123 -6
  174. package/dist/sync/BootstrapFetcher.js +492 -66
  175. package/dist/sync/ConnectionManager.d.ts +6 -198
  176. package/dist/sync/ConnectionManager.js +6 -677
  177. package/dist/sync/OnDemandLoader.d.ts +2 -2
  178. package/dist/sync/OnDemandLoader.js +60 -21
  179. package/dist/sync/SubscriptionManager.d.ts +13 -2
  180. package/dist/sync/SubscriptionManager.js +23 -5
  181. package/dist/sync/SyncWebSocket.d.ts +27 -510
  182. package/dist/sync/SyncWebSocket.js +76 -954
  183. package/dist/sync/awaitClaimGrant.d.ts +4 -44
  184. package/dist/sync/awaitClaimGrant.js +4 -109
  185. package/dist/sync/commitFrames.d.ts +6 -40
  186. package/dist/sync/commitFrames.js +6 -97
  187. package/dist/sync/contextPorts.d.ts +18 -0
  188. package/dist/sync/contextPorts.js +31 -0
  189. package/dist/sync/createClaimStream.d.ts +5 -49
  190. package/dist/sync/createClaimStream.js +5 -469
  191. package/dist/sync/createPresenceStream.d.ts +26 -4
  192. package/dist/sync/createPresenceStream.js +28 -20
  193. package/dist/sync/createSnapshot.d.ts +2 -2
  194. package/dist/sync/createSnapshot.js +1 -1
  195. package/dist/sync/credentialLifecycle.d.ts +5 -173
  196. package/dist/sync/credentialLifecycle.js +5 -320
  197. package/dist/sync/deltaPipeline.d.ts +1 -1
  198. package/dist/sync/participants.d.ts +5 -4
  199. package/dist/sync/participants.js +29 -22
  200. package/dist/sync/schemaDrift.d.ts +55 -0
  201. package/dist/sync/schemaDrift.js +53 -0
  202. package/dist/sync/schemas.d.ts +21 -32
  203. package/dist/sync/schemas.js +26 -17
  204. package/dist/sync/syncPlan.d.ts +3 -3
  205. package/dist/sync/wsFrameHandlers.d.ts +6 -114
  206. package/dist/sync/wsFrameHandlers.js +6 -392
  207. package/dist/testing/fixtures/bootstrap.d.ts +1 -1
  208. package/dist/testing/fixtures/deltas.d.ts +1 -1
  209. package/dist/testing/fixtures/httpResponses.d.ts +70 -0
  210. package/dist/testing/fixtures/httpResponses.js +90 -0
  211. package/dist/testing/fixtures/models.js +1 -1
  212. package/dist/testing/helpers/wait.js +1 -1
  213. package/dist/testing/mocks/MockMutationExecutor.d.ts +2 -2
  214. package/dist/testing/mocks/MockMutationExecutor.js +8 -14
  215. package/dist/testing/mocks/MockSyncContext.d.ts +11 -11
  216. package/dist/testing/mocks/MockSyncContext.js +10 -9
  217. package/dist/testing/mocks/MockSyncStore.js +1 -1
  218. package/dist/testing/mocks/MockWebSocket.d.ts +2 -2
  219. package/dist/transaction/ablo.d.ts +88 -0
  220. package/dist/transaction/ablo.js +33 -0
  221. package/dist/{client/auth.d.ts → transaction/auth/apiKey.d.ts} +43 -8
  222. package/dist/{client/auth.js → transaction/auth/apiKey.js} +19 -0
  223. package/dist/transaction/auth/bootstrapScope.d.ts +15 -0
  224. package/dist/transaction/auth/bootstrapScope.js +1 -0
  225. package/dist/transaction/auth/capability.d.ts +177 -0
  226. package/dist/transaction/auth/capability.js +199 -0
  227. package/dist/{auth → transaction/auth}/credentialSource.d.ts +8 -1
  228. package/dist/{client → transaction/auth}/identity.d.ts +8 -7
  229. package/dist/{client → transaction/auth}/identity.js +1 -1
  230. package/dist/transaction/auth/index.d.ts +162 -0
  231. package/dist/transaction/auth/index.js +304 -0
  232. package/dist/{auth → transaction/auth}/schemas.d.ts +1 -1
  233. package/dist/{auth → transaction/auth}/schemas.js +13 -13
  234. package/dist/{client → transaction/auth}/sessionMint.d.ts +8 -8
  235. package/dist/{client → transaction/auth}/sessionMint.js +4 -7
  236. package/dist/transaction/coordination/awaitClaimGrant.d.ts +49 -0
  237. package/dist/transaction/coordination/awaitClaimGrant.js +112 -0
  238. package/dist/transaction/coordination/claimMeta.d.ts +49 -0
  239. package/dist/transaction/coordination/claimMeta.js +52 -0
  240. package/dist/transaction/coordination/createClaimStream.d.ts +64 -0
  241. package/dist/transaction/coordination/createClaimStream.js +475 -0
  242. package/dist/transaction/coordination/events.d.ts +74 -0
  243. package/dist/transaction/coordination/events.js +7 -0
  244. package/dist/transaction/coordination/index.d.ts +19 -0
  245. package/dist/transaction/coordination/index.js +44 -0
  246. package/dist/transaction/coordination/locator.d.ts +83 -0
  247. package/dist/transaction/coordination/locator.js +82 -0
  248. package/dist/transaction/coordination/schema.d.ts +1473 -0
  249. package/dist/{coordination → transaction/coordination}/schema.js +490 -55
  250. package/dist/transaction/coordination/targetConflict.d.ts +2 -0
  251. package/dist/transaction/coordination/targetConflict.js +103 -0
  252. package/dist/{coordination → transaction/coordination}/trace.d.ts +7 -18
  253. package/dist/{coordination → transaction/coordination}/trace.js +18 -25
  254. package/dist/transaction/durableWrites.d.ts +62 -0
  255. package/dist/{client → transaction}/durableWrites.js +28 -3
  256. package/dist/transaction/environment.d.ts +105 -0
  257. package/dist/transaction/environment.js +108 -0
  258. package/dist/{errorCodes.d.ts → transaction/errorCodes.d.ts} +11 -11
  259. package/dist/{errorCodes.js → transaction/errorCodes.js} +35 -12
  260. package/dist/{errors.d.ts → transaction/errors.d.ts} +37 -13
  261. package/dist/{errors.js → transaction/errors.js} +85 -16
  262. package/dist/transaction/index.d.ts +20 -0
  263. package/dist/transaction/index.js +20 -0
  264. package/dist/transaction/keys/index.d.ts +87 -0
  265. package/dist/transaction/keys/index.js +207 -0
  266. package/dist/transaction/log/syncDeltaRow.d.ts +158 -0
  267. package/dist/transaction/log/syncDeltaRow.js +95 -0
  268. package/dist/{sync/syncPosition.d.ts → transaction/logPosition.d.ts} +22 -8
  269. package/dist/{sync/syncPosition.js → transaction/logPosition.js} +15 -6
  270. package/dist/transaction/logger.d.ts +16 -0
  271. package/dist/transaction/logger.js +7 -0
  272. package/dist/transaction/observability.d.ts +53 -0
  273. package/dist/transaction/observability.js +19 -0
  274. package/dist/transaction/plugin.d.ts +192 -0
  275. package/dist/transaction/plugin.js +87 -0
  276. package/dist/{policy → transaction/policy}/types.d.ts +3 -3
  277. package/dist/{policy → transaction/policy}/types.js +2 -0
  278. package/dist/transaction/resources/httpResources.d.ts +266 -0
  279. package/dist/transaction/resources/httpResources.js +7 -0
  280. package/dist/transaction/resources/modelOperations.d.ts +319 -0
  281. package/dist/transaction/resources/modelOperations.js +12 -0
  282. package/dist/transaction/resources/mutationOptions.d.ts +66 -0
  283. package/dist/transaction/resources/mutationOptions.js +9 -0
  284. package/dist/transaction/resources/where.d.ts +85 -0
  285. package/dist/transaction/resources/where.js +70 -0
  286. package/dist/{client → transaction/resources}/writeOptionsSchema.d.ts +2 -6
  287. package/dist/{client → transaction/resources}/writeOptionsSchema.js +9 -5
  288. package/dist/{schema → transaction/schema}/field.d.ts +5 -5
  289. package/dist/{schema → transaction/schema}/field.js +5 -5
  290. package/dist/transaction/schema/loadStrategy.d.ts +45 -0
  291. package/dist/transaction/schema/loadStrategy.js +46 -0
  292. package/dist/{schema → transaction/schema}/model.d.ts +50 -35
  293. package/dist/{schema → transaction/schema}/model.js +30 -20
  294. package/dist/transaction/schema/openapi.d.ts +57 -0
  295. package/dist/transaction/schema/openapi.js +340 -0
  296. package/dist/{schema → transaction/schema}/relation.d.ts +14 -14
  297. package/dist/{schema → transaction/schema}/relation.js +7 -7
  298. package/dist/{schema → transaction/schema}/residency.d.ts +0 -9
  299. package/dist/{schema → transaction/schema}/residency.js +0 -5
  300. package/dist/{schema → transaction/schema}/roles.d.ts +5 -5
  301. package/dist/{schema → transaction/schema}/roles.js +5 -5
  302. package/dist/{schema → transaction/schema}/schema.d.ts +12 -10
  303. package/dist/{schema → transaction/schema}/schema.js +4 -3
  304. package/dist/{schema → transaction/schema}/tenancy.d.ts +1 -1
  305. package/dist/{schema → transaction/schema}/tenancy.js +7 -4
  306. package/dist/transaction/transactionLayer.d.ts +82 -0
  307. package/dist/transaction/transactionLayer.js +24 -0
  308. package/dist/{transactions → transaction/transactions/settlement}/commitEnvelope.d.ts +4 -5
  309. package/dist/{transactions → transaction/transactions/settlement}/commitEnvelope.js +9 -13
  310. package/dist/{transactions → transaction/transactions/settlement}/httpCommitEnvelope.d.ts +9 -2
  311. package/dist/{transactions → transaction/transactions/settlement}/httpCommitEnvelope.js +5 -9
  312. package/dist/{transactions/durableWriteStore.d.ts → transaction/transactions/settlement/pendingWrite.d.ts} +10 -36
  313. package/dist/transaction/transactions/settlement/pendingWrite.js +20 -0
  314. package/dist/transaction/transport/commitFrames.d.ts +90 -0
  315. package/dist/transaction/transport/commitFrames.js +134 -0
  316. package/dist/transaction/transport/connectionManager.d.ts +215 -0
  317. package/dist/transaction/transport/connectionManager.js +673 -0
  318. package/dist/transaction/transport/credentialLifecycle.d.ts +177 -0
  319. package/dist/transaction/transport/credentialLifecycle.js +324 -0
  320. package/dist/{sync → transaction/transport}/heartbeat.d.ts +3 -1
  321. package/dist/{sync → transaction/transport}/heartbeat.js +6 -4
  322. package/dist/{client → transaction/transport}/httpClient.d.ts +59 -16
  323. package/dist/{client → transaction/transport}/httpClient.js +5 -5
  324. package/dist/transaction/transport/httpOptions.d.ts +33 -0
  325. package/dist/transaction/transport/httpOptions.js +12 -0
  326. package/dist/{client → transaction/transport}/httpTransport.js +171 -85
  327. package/dist/{sync/NetworkProbe.d.ts → transaction/transport/networkProbe.d.ts} +7 -4
  328. package/dist/{sync/NetworkProbe.js → transaction/transport/networkProbe.js} +14 -13
  329. package/dist/transaction/transport/wsFrameHandlers.d.ts +128 -0
  330. package/dist/transaction/transport/wsFrameHandlers.js +429 -0
  331. package/dist/transaction/transport/wsTransport.d.ts +576 -0
  332. package/dist/transaction/transport/wsTransport.js +1017 -0
  333. package/dist/transaction/types/assertExact.d.ts +17 -0
  334. package/dist/transaction/types/assertExact.js +1 -0
  335. package/dist/{types → transaction/types}/global.d.ts +17 -2
  336. package/dist/{types → transaction/types}/global.js +2 -1
  337. package/dist/{types → transaction/types}/index.d.ts +14 -46
  338. package/dist/{types → transaction/types}/index.js +7 -16
  339. package/dist/{types → transaction/types}/streams.d.ts +63 -45
  340. package/dist/{utils → transaction/utils}/json.d.ts +18 -0
  341. package/dist/transaction/utils/json.js +276 -0
  342. package/dist/transaction/wire/accountResponses.d.ts +351 -0
  343. package/dist/transaction/wire/accountResponses.js +255 -0
  344. package/dist/transaction/wire/auth.d.ts +49 -0
  345. package/dist/transaction/wire/auth.js +57 -0
  346. package/dist/transaction/wire/claimEvent.d.ts +76 -0
  347. package/dist/transaction/wire/claimEvent.js +73 -0
  348. package/dist/transaction/wire/claims.d.ts +463 -0
  349. package/dist/transaction/wire/claims.js +229 -0
  350. package/dist/{wire → transaction/wire}/commit.d.ts +125 -193
  351. package/dist/{wire → transaction/wire}/commit.js +68 -47
  352. package/dist/{wire → transaction/wire}/delta.d.ts +66 -17
  353. package/dist/{wire → transaction/wire}/delta.js +37 -13
  354. package/dist/transaction/wire/errorEnvelope.d.ts +72 -0
  355. package/dist/{wire → transaction/wire}/errorEnvelope.js +36 -5
  356. package/dist/transaction/wire/feedCursor.d.ts +60 -0
  357. package/dist/transaction/wire/feedCursor.js +82 -0
  358. package/dist/transaction/wire/feedEvent.d.ts +177 -0
  359. package/dist/transaction/wire/feedEvent.js +39 -0
  360. package/dist/transaction/wire/frames.d.ts +194 -0
  361. package/dist/transaction/wire/frames.js +50 -0
  362. package/dist/transaction/wire/inboundFrames.d.ts +552 -0
  363. package/dist/transaction/wire/inboundFrames.js +116 -0
  364. package/dist/transaction/wire/index.d.ts +50 -0
  365. package/dist/transaction/wire/index.js +74 -0
  366. package/dist/{wire → transaction/wire}/listEnvelope.d.ts +13 -14
  367. package/dist/transaction/wire/listEnvelope.js +42 -0
  368. package/dist/transaction/wire/modelResponses.d.ts +85 -0
  369. package/dist/transaction/wire/modelResponses.js +43 -0
  370. package/dist/transactions/{TransactionQueue.d.ts → mutations/MutationQueue.d.ts} +79 -38
  371. package/dist/transactions/{TransactionQueue.js → mutations/MutationQueue.js} +110 -59
  372. package/dist/transactions/{TransactionStore.d.ts → mutations/MutationStore.d.ts} +8 -8
  373. package/dist/transactions/{TransactionStore.js → mutations/MutationStore.js} +2 -2
  374. package/dist/transactions/{coalesceRules.d.ts → mutations/coalesceRules.d.ts} +10 -10
  375. package/dist/transactions/{coalesceRules.js → mutations/coalesceRules.js} +1 -1
  376. package/dist/transactions/mutations/commitLatency.d.ts +52 -0
  377. package/dist/transactions/mutations/commitLatency.js +130 -0
  378. package/dist/transactions/{commitOutboxStore.d.ts → mutations/commitOutboxStore.d.ts} +1 -5
  379. package/dist/transactions/{commitOutboxStore.js → mutations/commitOutboxStore.js} +1 -1
  380. package/dist/transactions/{commitPayload.d.ts → mutations/commitPayload.d.ts} +16 -15
  381. package/dist/transactions/{commitPayload.js → mutations/commitPayload.js} +12 -12
  382. package/dist/transactions/{deltaConfirmation.d.ts → mutations/deltaConfirmation.d.ts} +11 -11
  383. package/dist/transactions/{deltaConfirmation.js → mutations/deltaConfirmation.js} +7 -7
  384. package/dist/transactions/mutations/durableWriteStore.d.ts +14 -0
  385. package/dist/transactions/mutations/durableWriteStore.js +12 -0
  386. package/dist/transactions/{optimisticApply.d.ts → mutations/optimisticApply.d.ts} +7 -7
  387. package/dist/transactions/{replayValidation.d.ts → mutations/replayValidation.d.ts} +3 -3
  388. package/dist/transactions/{replayValidation.js → mutations/replayValidation.js} +4 -3
  389. package/dist/utils/mobxSetup.d.ts +1 -1
  390. package/dist/utils/mobxSetup.js +5 -2
  391. package/dist/webhooks/events.d.ts +2 -2
  392. package/dist/wire/index.d.ts +1 -34
  393. package/dist/wire/index.js +8 -49
  394. package/docs/agent-messaging.md +3 -3
  395. package/docs/agents.md +19 -12
  396. package/docs/api-keys.md +8 -4
  397. package/docs/api.md +22 -18
  398. package/docs/audit.md +2 -0
  399. package/docs/cli.md +31 -3
  400. package/docs/client-behavior.md +8 -6
  401. package/docs/concurrency-convention.md +30 -24
  402. package/docs/coordination.md +48 -38
  403. package/docs/data-sources.md +3 -1
  404. package/docs/debugging.md +5 -3
  405. package/docs/deployment.md +267 -0
  406. package/docs/examples/agent-human.md +49 -42
  407. package/docs/examples/ai-sdk-tool.md +69 -44
  408. package/docs/examples/existing-python-backend.md +8 -6
  409. package/docs/examples/nextjs.md +129 -47
  410. package/docs/examples/scoped-agent.md +45 -44
  411. package/docs/examples/server-agent.md +46 -26
  412. package/docs/groups.md +32 -29
  413. package/docs/guarantees.md +4 -2
  414. package/docs/how-it-works.md +9 -7
  415. package/docs/idempotency.md +126 -0
  416. package/docs/identity.md +58 -54
  417. package/docs/index.md +172 -86
  418. package/docs/integration-guide.md +17 -16
  419. package/docs/interaction-model.md +6 -4
  420. package/docs/mcp.md +41 -16
  421. package/docs/migration.md +63 -5
  422. package/docs/operating-on-your-database.md +3 -1
  423. package/docs/projects.md +2 -0
  424. package/docs/quickstart.md +22 -5
  425. package/docs/react.md +12 -10
  426. package/docs/schema-contract.md +5 -3
  427. package/docs/session-settings.md +108 -0
  428. package/docs/sessions.md +3 -1
  429. package/docs/webhooks.md +3 -1
  430. package/llms.txt +47 -17
  431. package/package.json +10 -8
  432. package/dist/agent/Agent.d.ts +0 -366
  433. package/dist/agent/Agent.js +0 -514
  434. package/dist/agent/index.d.ts +0 -115
  435. package/dist/agent/index.js +0 -128
  436. package/dist/agent/session.d.ts +0 -93
  437. package/dist/agent/session.js +0 -149
  438. package/dist/agent/types.d.ts +0 -68
  439. package/dist/agent/types.js +0 -9
  440. package/dist/client/durableWrites.d.ts +0 -21
  441. package/dist/coordination/schema.d.ts +0 -722
  442. package/dist/schema/openapi.d.ts +0 -29
  443. package/dist/schema/openapi.js +0 -124
  444. package/dist/transactions/durableWriteStore.js +0 -30
  445. package/dist/utils/json.js +0 -88
  446. package/dist/wire/errorEnvelope.d.ts +0 -55
  447. package/dist/wire/frames.d.ts +0 -197
  448. package/dist/wire/frames.js +0 -49
  449. package/dist/wire/listEnvelope.js +0 -18
  450. /package/dist/{client → transaction/auth}/credentialEndpoint.d.ts +0 -0
  451. /package/dist/{client → transaction/auth}/credentialEndpoint.js +0 -0
  452. /package/dist/{auth → transaction/auth}/credentialPolicy.d.ts +0 -0
  453. /package/dist/{auth → transaction/auth}/credentialPolicy.js +0 -0
  454. /package/dist/{auth → transaction/auth}/credentialSource.js +0 -0
  455. /package/dist/{client → transaction/auth}/hostedEndpoints.d.ts +0 -0
  456. /package/dist/{client → transaction/auth}/hostedEndpoints.js +0 -0
  457. /package/dist/{client → transaction/coordination}/claimHeartbeatLoop.d.ts +0 -0
  458. /package/dist/{client → transaction/coordination}/claimHeartbeatLoop.js +0 -0
  459. /package/dist/{client → transaction}/persistence.d.ts +0 -0
  460. /package/dist/{client → transaction}/persistence.js +0 -0
  461. /package/dist/{client → transaction/resources}/functionalUpdate.d.ts +0 -0
  462. /package/dist/{client → transaction/resources}/functionalUpdate.js +0 -0
  463. /package/dist/{transactions → transaction/transactions/settlement}/idempotencyKey.d.ts +0 -0
  464. /package/dist/{transactions → transaction/transactions/settlement}/idempotencyKey.js +0 -0
  465. /package/dist/{client → transaction/transport}/httpTransport.d.ts +0 -0
  466. /package/dist/{types → transaction/types}/modelData.d.ts +0 -0
  467. /package/dist/{types → transaction/types}/modelData.js +0 -0
  468. /package/dist/{types → transaction/types}/participant.d.ts +0 -0
  469. /package/dist/{types → transaction/types}/participant.js +0 -0
  470. /package/dist/{types → transaction/types}/streams.js +0 -0
  471. /package/dist/{utils → transaction/utils}/asyncIterator.d.ts +0 -0
  472. /package/dist/{utils → transaction/utils}/asyncIterator.js +0 -0
  473. /package/dist/{utils → transaction/utils}/duration.d.ts +0 -0
  474. /package/dist/{utils → transaction/utils}/duration.js +0 -0
  475. /package/dist/{wire → transaction/wire}/bootstrapReason.d.ts +0 -0
  476. /package/dist/{wire → transaction/wire}/bootstrapReason.js +0 -0
  477. /package/dist/{wire → transaction/wire}/protocol.d.ts +0 -0
  478. /package/dist/{wire → transaction/wire}/protocol.js +0 -0
  479. /package/dist/{wire → transaction/wire}/protocolVersion.d.ts +0 -0
  480. /package/dist/{wire → transaction/wire}/protocolVersion.js +0 -0
  481. /package/dist/transactions/{UnconfirmedWrites.d.ts → mutations/UnconfirmedWrites.d.ts} +0 -0
  482. /package/dist/transactions/{UnconfirmedWrites.js → mutations/UnconfirmedWrites.js} +0 -0
  483. /package/dist/transactions/{optimisticApply.js → mutations/optimisticApply.js} +0 -0
@@ -3,29 +3,56 @@
3
3
  * `ablo.<model>`.
4
4
  *
5
5
  * Each schema model gets one {@link ModelOperations}: the async server reads
6
- * `retrieve` and `list`, the synchronous local-graph snapshots `get`, `getAll`,
7
- * and `getCount`, the writes `create`, `update`, and `delete`, the coordination
6
+ * `retrieve` and `list`, the same verbs restricted to the local graph under
7
+ * `local`, the writes `create`, `update`, and `delete`, the coordination
8
8
  * namespace `claim` (callable as `claim({ id })`, plus `claim.state`,
9
9
  * `claim.queue`, `claim.release`, and `claim.reorder`), `join`, and `onChange`.
10
10
  * The factory returns a plain object; the client assembles the `ablo.<model>`
11
11
  * lookup table from one of these per model.
12
12
  */
13
13
  import { autorun } from 'mobx';
14
- import { AbloClaimedError, AbloStaleContextError, AbloValidationError, formatClaimedErrorMessage, toAbloError, } from '../errors.js';
15
- import { reconcileFunctionalUpdate, } from './functionalUpdate.js';
14
+ import { AbloClaimedError, AbloValidationError, formatClaimedErrorMessage, toAbloError, } from '../transaction/errors.js';
15
+ import { reconcileFunctionalUpdate, } from '../transaction/resources/functionalUpdate.js';
16
+ import { claimDescription, } from '../transaction/coordination/schema.js';
16
17
  import { Model, modelAsRow } from '../Model.js';
17
- import { toMs } from '../utils/duration.js';
18
- import { LEASE_TTL_MS } from '../wire/protocol.js';
19
- import { heartbeatCadenceMs, resolveHeartbeatOptions, startClaimHeartbeatLoop, } from './claimHeartbeatLoop.js';
20
- import { assertWriteOptions } from './writeOptionsSchema.js';
21
- import { ModelScope } from '../types/index.js';
18
+ import { toMs } from '../transaction/utils/duration.js';
19
+ import { LEASE_TTL_MS } from '../transaction/wire/protocol.js';
20
+ import { heartbeatCadenceMs, resolveHeartbeatOptions, startClaimHeartbeatLoop, } from '../transaction/coordination/claimHeartbeatLoop.js';
21
+ import { assertWriteOptions } from '../transaction/resources/writeOptionsSchema.js';
22
+ import { modelTarget, subTarget } from '../transaction/coordination/index.js';
23
+ import { ModelScope } from '../transaction/types/index.js';
22
24
  const modelClientMeta = new WeakMap();
23
25
  export function getModelClientMeta(modelClient) {
24
26
  if (typeof modelClient !== 'object' || modelClient === null)
25
27
  return undefined;
26
28
  return modelClientMeta.get(modelClient);
27
29
  }
28
- export function createModelProxy(schemaKey, registeredModelName, objectPool, syncClient, registry, hydration, collaboration) {
30
+ export function createModelProxy(schemaKey, registeredModelName, objectPool, syncClient, registry, hydration, collaboration,
31
+ /** The client-wide `wait` default; a per-call `wait` still wins over it. */
32
+ defaultWait) {
33
+ /**
34
+ * Resolve a row **this** resource owns.
35
+ *
36
+ * The pool is one id space, so `objectPool.get(id)` happily returns another
37
+ * model's row. Every write path below addresses rows by bare id, so without
38
+ * this an id from a sibling model resolves and gets written — silently
39
+ * corrupting a row the caller never named.
40
+ *
41
+ * `undefined` means genuinely absent. A row belonging to another model throws:
42
+ * unlike a read, a cross-model *write* is never a legitimate outcome, and
43
+ * naming both models turns a silent corruption into a one-line diagnosis.
44
+ */
45
+ const ownRowOrThrow = (id) => {
46
+ const own = objectPool.getOfType(id, registeredModelName);
47
+ if (own)
48
+ return own;
49
+ const foreign = objectPool.get(id);
50
+ if (!foreign)
51
+ return undefined;
52
+ const owner = foreign.getModelName();
53
+ throw new AbloValidationError(`No ${registeredModelName} with id ${id} — that id belongs to a ${owner}. ` +
54
+ `Read or write it through ${owner}.`, { code: 'entity_not_found' });
55
+ };
29
56
  const ModelClass = registry.getModelByName(registeredModelName);
30
57
  if (!ModelClass) {
31
58
  throw new AbloValidationError(`Ablo: schema model "${schemaKey}" resolved to "${registeredModelName}", ` +
@@ -66,7 +93,11 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
66
93
  return rows;
67
94
  };
68
95
  const waitForMutation = async (model, options) => {
69
- if (options?.wait !== 'confirmed')
96
+ // A per-call `wait` wins; otherwise the client-wide default decides. This
97
+ // is the single point that turns "confirmed" into actually waiting, so a
98
+ // client configured that way rejects on a refused write everywhere rather
99
+ // than in the one place a caller remembered to ask.
100
+ if ((options?.wait ?? defaultWait) !== 'confirmed')
70
101
  return;
71
102
  await syncClient.syncNow();
72
103
  await syncClient.waitForConfirmation(model.getModelName(), model.id);
@@ -93,7 +124,6 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
93
124
  value.object === 'claim' &&
94
125
  typeof value.id === 'string' &&
95
126
  typeof value.release === 'function';
96
- const claimMeta = (options) => options?.meta;
97
127
  const claimContextFromClaim = (claim) => {
98
128
  return {
99
129
  id: claim.id,
@@ -104,12 +134,8 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
104
134
  status: claim.status,
105
135
  expiresAt: claim.expiresAt,
106
136
  target: {
107
- model: claim.target.type,
108
- id: claim.target.id,
109
- path: claim.target.path,
110
- range: claim.target.range,
111
- field: claim.target.field,
112
- meta: claim.target.meta,
137
+ ...modelTarget(claim.target),
138
+ ...subTarget(claim.target),
113
139
  },
114
140
  };
115
141
  };
@@ -155,10 +181,10 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
155
181
  }), { code: 'entity_claimed', claims: [claim] });
156
182
  }
157
183
  // Ensure the row exists locally before claiming.
158
- let model = objectPool.get(id);
184
+ let model = ownRowOrThrow(id);
159
185
  if (!model) {
160
186
  await load({ where: [['id', id]] });
161
- model = objectPool.get(id);
187
+ model = ownRowOrThrow(id);
162
188
  }
163
189
  if (!model) {
164
190
  throw new AbloValidationError(`Entity not found: ${registeredModelName}/${id}`, { code: 'entity_not_found' });
@@ -180,12 +206,12 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
180
206
  target: {
181
207
  model: wireModel,
182
208
  id,
183
- ...(options.field ? { field: options.field } : {}),
184
- ...(options.path ? { path: options.path } : {}),
185
- ...(options.range ? { range: options.range } : {}),
186
- ...(claimMeta(options) ? { meta: claimMeta(options) } : {}),
209
+ // The whole sub-entity locator in one move — listing its members here
210
+ // is what let `fields` die between the caller and the lease, so the
211
+ // claim covered the whole row while the caller believed it named parts.
212
+ ...subTarget(options),
187
213
  },
188
- description: options.description ?? 'editing',
214
+ description: claimDescription(options),
189
215
  ttl: options.ttl,
190
216
  queue: !failFast,
191
217
  maxQueueDepth: options.maxQueueDepth,
@@ -205,20 +231,17 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
205
231
  // holder's final write may not have fanned out yet — the exact
206
232
  // stale-snapshot race this re-read closes.
207
233
  await load({ where: [['id', id]], type: 'complete' });
208
- model = objectPool.get(id) ?? model;
234
+ model = ownRowOrThrow(id) ?? model;
209
235
  }
210
236
  const snapshot = collaboration.createSnapshot(schemaKey, id);
211
- const description = options.description ?? 'editing';
237
+ const description = claimDescription(options);
212
238
  // The self-claim's `ClaimTarget` mirrors what a peer's `claim.state` would
213
239
  // report (`state` maps `held.target.model` to `type`), so a holder and a
214
240
  // peer see the same `target.type` for one row — the wire model token.
215
241
  const selfTarget = {
216
242
  type: wireModel,
217
243
  id,
218
- ...(options.field ? { field: options.field } : {}),
219
- ...(options.path ? { path: options.path } : {}),
220
- ...(options.range ? { range: options.range } : {}),
221
- ...(claimMeta(options) ? { meta: claimMeta(options) } : {}),
244
+ ...subTarget(options),
222
245
  };
223
246
  const ttlMs = options.ttl !== undefined ? toMs(options.ttl) : DEFAULT_LEASE_TTL_MS;
224
247
  const expiresAt = Date.now() + ttlMs;
@@ -232,10 +255,7 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
232
255
  const target = {
233
256
  type: schemaKey,
234
257
  id,
235
- ...(options.field ? { field: options.field } : {}),
236
- ...(options.path ? { path: options.path } : {}),
237
- ...(options.range ? { range: options.range } : {}),
238
- ...(claimMeta(options) ? { meta: claimMeta(options) } : {}),
258
+ ...subTarget(options),
239
259
  };
240
260
  // A beat resolves with the server's extended expiry; keep the local
241
261
  // self-claim estimate in step so `claim.state` renders the real window,
@@ -329,12 +349,12 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
329
349
  target: {
330
350
  model: wireModel,
331
351
  id,
332
- ...(options.field ? { field: options.field } : {}),
333
- ...(options.path ? { path: options.path } : {}),
334
- ...(options.range ? { range: options.range } : {}),
335
- ...(claimMeta(options) ? { meta: claimMeta(options) } : {}),
352
+ // The whole sub-entity locator in one move — listing its members here
353
+ // is what let `fields` die between the caller and the lease, so the
354
+ // claim covered the whole row while the caller believed it named parts.
355
+ ...subTarget(options),
336
356
  },
337
- description: options.description ?? 'editing',
357
+ description: claimDescription(options),
338
358
  ttl: options.ttl,
339
359
  queue: !failFast,
340
360
  maxQueueDepth: options.maxQueueDepth,
@@ -344,14 +364,11 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
344
364
  // empty). It costs nothing extra and gives a write taken under this lease a
345
365
  // real `readAt` to guard against changes since the lease was acquired.
346
366
  const snapshot = collaboration.createSnapshot(schemaKey, id);
347
- const description = options.description ?? 'editing';
367
+ const description = claimDescription(options);
348
368
  const selfTarget = {
349
369
  type: wireModel,
350
370
  id,
351
- ...(options.field ? { field: options.field } : {}),
352
- ...(options.path ? { path: options.path } : {}),
353
- ...(options.range ? { range: options.range } : {}),
354
- ...(claimMeta(options) ? { meta: claimMeta(options) } : {}),
371
+ ...subTarget(options),
355
372
  };
356
373
  const ttlMs = options.ttl !== undefined ? toMs(options.ttl) : DEFAULT_LEASE_TTL_MS;
357
374
  const expiresAt = Date.now() + ttlMs;
@@ -365,10 +382,7 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
365
382
  const target = {
366
383
  type: schemaKey,
367
384
  id,
368
- ...(options.field ? { field: options.field } : {}),
369
- ...(options.path ? { path: options.path } : {}),
370
- ...(options.range ? { range: options.range } : {}),
371
- ...(claimMeta(options) ? { meta: claimMeta(options) } : {}),
385
+ ...subTarget(options),
372
386
  };
373
387
  // A beat resolves with the server's extended expiry; keep the local
374
388
  // self-claim estimate in step so `claim.state` renders the real window.
@@ -434,7 +448,14 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
434
448
  // members to read/steer the coordination plane. Attach the readers to the
435
449
  // callable so `ablo.<model>.claim(...)` and `ablo.<model>.claim.state(...)`
436
450
  // are the same object.
437
- const claimApi = Object.assign(claim, {
451
+ // `state` and `queue` take a caller-named `meta` shape. The runtime cannot
452
+ // check it and is not meant to: `target.meta` is application data the
453
+ // protocol carries verbatim and never interprets, so naming its type is the
454
+ // caller asserting what it put there — the same bargain as parsing your own
455
+ // JSON into an interface. These read as `Claim` here, and the one assertion
456
+ // that applies the caller's parameter is on the assignment below, in one
457
+ // place rather than at every call site.
458
+ const claimReaders = {
438
459
  state(params) {
439
460
  // Read interest: a passive observer of a row's claim state must enter that
440
461
  // row's entity scope, or it sits only on broader `org:`/`user:` groups and
@@ -470,28 +491,17 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
470
491
  collaboration?.reorder({ model: wireModel, id: params.id }, params.order);
471
492
  },
472
493
  release: guard((params) => releaseClaim(isClaimHandle(params) ? params.target.id : params.id)),
473
- });
474
- const operations = {
475
- retrieve: guard(async (params) => {
476
- // Read-interest enrolment: reading a row enters its entity scope, so a
477
- // client lands in the same group the holder's claim presence fans out
478
- // on and `claim.state`/`claim.queue` report peers. Best-effort and
479
- // fire-and-forget it never makes the read reject or run slower.
480
- void collaboration?.enterScope?.({ [schemaKey]: params.id });
481
- const rows = await load({
482
- ...params,
483
- where: [['id', params.id]],
484
- limit: 1,
485
- });
486
- return rows[0];
487
- }),
488
- // No automatic scope enrolment on bulk `list`/`getAll`: that would subscribe
489
- // to an unbounded set of rows' entity groups.
490
- list: guard(load),
491
- get(id) {
492
- return objectPool.get(id);
494
+ };
495
+ // The one place the caller's `meta` parameter is applied — see the note on
496
+ // `claimReaders`. Everything else about this object is checked structurally.
497
+ const claimApi = Object.assign(claim, claimReaders);
498
+ const local = {
499
+ retrieve(id) {
500
+ // Scoped to this model: an id belonging to a sibling model reads as
501
+ // absent rather than being handed back as if it were a `T`.
502
+ return objectPool.getOfType(id, registeredModelName);
493
503
  },
494
- getAll(options) {
504
+ list(options) {
495
505
  const all = objectPool.getByType(ModelClass, (options?.state ?? ModelScope.live));
496
506
  let result = all;
497
507
  if (options?.where) {
@@ -525,9 +535,28 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
525
535
  result = result.slice(0, options.limit);
526
536
  return result;
527
537
  },
528
- getCount(options) {
529
- return this.getAll(options).length;
538
+ count(options) {
539
+ return local.list(options).length;
530
540
  },
541
+ };
542
+ const operations = {
543
+ local,
544
+ retrieve: guard(async (params) => {
545
+ // Read-interest enrolment: reading a row enters its entity scope, so a
546
+ // client lands in the same group the holder's claim presence fans out
547
+ // on and `claim.state`/`claim.queue` report peers. Best-effort and
548
+ // fire-and-forget — it never makes the read reject or run slower.
549
+ void collaboration?.enterScope?.({ [schemaKey]: params.id });
550
+ const rows = await load({
551
+ ...params,
552
+ where: [['id', params.id]],
553
+ limit: 1,
554
+ });
555
+ return rows[0];
556
+ }),
557
+ // No automatic scope enrolment on bulk `list`: that would subscribe to an
558
+ // unbounded set of rows' entity groups.
559
+ list: guard(load),
531
560
  create: guard(async (params) => {
532
561
  const id = params.id ?? Model.generateId();
533
562
  const opts = mutationOptions(params);
@@ -547,12 +576,9 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
547
576
  target: {
548
577
  model: wireModel,
549
578
  id,
550
- ...(claim.field ? { field: claim.field } : {}),
551
- ...(claim.path ? { path: claim.path } : {}),
552
- ...(claim.range ? { range: claim.range } : {}),
553
- ...(claimMeta(claim) ? { meta: claimMeta(claim) } : {}),
579
+ ...subTarget(claim),
554
580
  },
555
- description: claim.description ?? 'creating',
581
+ description: claimDescription(claim, 'creating'),
556
582
  ttl: claim.ttl,
557
583
  queue: claim.queue !== false,
558
584
  maxQueueDepth: claim.maxQueueDepth,
@@ -615,7 +641,7 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
615
641
  // `type: 'complete'` forces the round-trip — the hydration ledger
616
642
  // would otherwise serve a possibly-stale local row for a hydrated id.
617
643
  await load({ where: [['id', id]], type: 'complete' });
618
- const fresh = objectPool.get(id);
644
+ const fresh = ownRowOrThrow(id);
619
645
  const snapshot = collaboration.createSnapshot(schemaKey, id);
620
646
  return {
621
647
  data: fresh ? modelAsRow(fresh) : undefined,
@@ -623,7 +649,7 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
623
649
  };
624
650
  },
625
651
  writeNext: async (patch, readAt) => {
626
- const model = objectPool.get(id);
652
+ const model = ownRowOrThrow(id);
627
653
  if (!model) {
628
654
  throw new AbloValidationError(`Entity not found: ${registeredModelName}/${id}`, { code: 'entity_not_found' });
629
655
  }
@@ -651,7 +677,7 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
651
677
  }
652
678
  }
653
679
  const { id } = params;
654
- const model = objectPool.get(id);
680
+ const model = ownRowOrThrow(id);
655
681
  if (!model)
656
682
  throw new AbloValidationError(`Entity not found: ${registeredModelName}/${id}`, { code: 'entity_not_found' });
657
683
  // If we hold a claim on this row, guard the write with its snapshot
@@ -711,7 +737,10 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
711
737
  return;
712
738
  }
713
739
  const { id } = params;
714
- const model = objectPool.get(id);
740
+ // Scoped: "ensure absent" stays idempotent for an id this model simply
741
+ // doesn't hold, but an id owned by a sibling model throws rather than
742
+ // deleting a row the caller never addressed.
743
+ const model = ownRowOrThrow(id);
715
744
  // Idempotent delete: "ensure absent". A row that isn't in this client's
716
745
  // replicated view is already gone from its perspective, so a delete is a
717
746
  // no-op success rather than an `entity_not_found` error. This matches the
@@ -758,13 +787,13 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
758
787
  };
759
788
  // A track carries no write, so it rides the commit lane as a zero-operation
760
789
  // commit: the queue tolerates disconnects and de-dupes replays, and the
761
- // server's track-only path registers the dependency and reports anything
790
+ // server's track-only path registers the premise and reports anything
762
791
  // that already fired. Reuse the same lane the batch `commits.create` door
763
792
  // uses rather than opening a bespoke transport.
764
793
  const clientTxId = typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'
765
794
  ? crypto.randomUUID()
766
795
  : `tx_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
767
- const queue = syncClient.getTransactionQueue();
796
+ const queue = syncClient.getMutationQueue();
768
797
  await queue.enqueueCommit(clientTxId, [], { track: [dep] });
769
798
  const { notifications } = await queue.waitForCommitReceipt(clientTxId);
770
799
  return notifications && notifications.length > 0 ? { notifications } : {};
@@ -777,8 +806,7 @@ export function createModelProxy(schemaKey, registeredModelName, objectPool, syn
777
806
  }),
778
807
  onChange(callback, options) {
779
808
  return autorun(() => {
780
- const entities = this.getAll(options);
781
- callback(entities);
809
+ callback(local.list(options));
782
810
  });
783
811
  },
784
812
  };
@@ -0,0 +1,48 @@
1
+ /**
2
+ * `humans()` — the reactive materialiser, declared as a capability (ADR 0016).
3
+ *
4
+ * The bare client is the coordination layer: commit, read, observe, claim.
5
+ * Add `humans()` when people are watching — it declares the local, watchable
6
+ * copy: the offline store, live queries, presence, and the framework
7
+ * bindings. There is no `agents()` counterpart, and the absence is the
8
+ * message: agents are the default caller, not a special one.
9
+ *
10
+ * Transitional shape: the contract fields do real configuration work
11
+ * (`requires.duplex` rejects it on a request-response client at construction
12
+ * time; `materialises` is the five-second membership test as a checkable
13
+ * property), and `init` constructs what the widened context already carries
14
+ * enough to build — the presence stream, attached to the connection the
15
+ * context carries (the host built it before resolving the plugin list). The
16
+ * rest of the materialiser (store, bootstrap, delta pipeline, framework
17
+ * bindings) still lives in the composition root and migrates here as the
18
+ * context grows to carry what it needs.
19
+ */
20
+ import type { PluginContext } from '../transaction/plugin.js';
21
+ import { type AttachablePresenceStream } from '../sync/createPresenceStream.js';
22
+ /**
23
+ * What `humans()` contributes to the client — exactly the members that merge
24
+ * onto it, nothing else. Whether a plugin materialises is declared on the
25
+ * plugin itself, never restated on its surface.
26
+ */
27
+ export interface HumansSurface {
28
+ /**
29
+ * Who is here and what they are doing. Attached to the connection at
30
+ * construction; calls before the socket opens mutate local state and skip
31
+ * the wire send, and the stream re-announces on every connect.
32
+ */
33
+ readonly presence: AttachablePresenceStream;
34
+ }
35
+ /**
36
+ * The reactive materialiser. Installed by default when `Ablo({ ... })` is
37
+ * constructed over the socket with no `plugins` list; listed explicitly, it
38
+ * reads as what it is — this client renders for people.
39
+ */
40
+ export declare function humans(): {
41
+ readonly id: "humans";
42
+ readonly requires: {
43
+ readonly duplex: true;
44
+ };
45
+ readonly materialises: true;
46
+ readonly stage: "apply";
47
+ readonly init: (context: PluginContext) => HumansSurface;
48
+ };
@@ -0,0 +1,52 @@
1
+ /**
2
+ * `humans()` — the reactive materialiser, declared as a capability (ADR 0016).
3
+ *
4
+ * The bare client is the coordination layer: commit, read, observe, claim.
5
+ * Add `humans()` when people are watching — it declares the local, watchable
6
+ * copy: the offline store, live queries, presence, and the framework
7
+ * bindings. There is no `agents()` counterpart, and the absence is the
8
+ * message: agents are the default caller, not a special one.
9
+ *
10
+ * Transitional shape: the contract fields do real configuration work
11
+ * (`requires.duplex` rejects it on a request-response client at construction
12
+ * time; `materialises` is the five-second membership test as a checkable
13
+ * property), and `init` constructs what the widened context already carries
14
+ * enough to build — the presence stream, attached to the connection the
15
+ * context carries (the host built it before resolving the plugin list). The
16
+ * rest of the materialiser (store, bootstrap, delta pipeline, framework
17
+ * bindings) still lives in the composition root and migrates here as the
18
+ * context grows to carry what it needs.
19
+ */
20
+ import { createPresenceStream, } from '../sync/createPresenceStream.js';
21
+ /**
22
+ * The reactive materialiser. Installed by default when `Ablo({ ... })` is
23
+ * constructed over the socket with no `plugins` list; listed explicitly, it
24
+ * reads as what it is — this client renders for people.
25
+ */
26
+ export function humans() {
27
+ return {
28
+ id: 'humans',
29
+ // Live queries, presence, and claim push are server-initiated frames, so
30
+ // a request-response client rejects this plugin while it is being
31
+ // configured — a typed error, not a subscription that never delivers.
32
+ requires: { duplex: true },
33
+ // The point of the plugin: it keeps a local copy of rows. A stateless
34
+ // caller can assert its own list is uniformly false.
35
+ materialises: true,
36
+ // Deltas land in the materialised in-memory graph at `apply`.
37
+ stage: 'apply',
38
+ init: (context) => ({
39
+ presence: createPresenceStream({
40
+ participantId: context.participant?.id ?? '',
41
+ syncGroups: [...(context.syncGroups ?? [])],
42
+ // Peers' kinds are server-stamped; only the local `self` entry is ours.
43
+ isAgent: context.participant?.kind === 'agent',
44
+ },
45
+ // The host built the connection before resolving the plugin list, so
46
+ // the stream attaches now and starts the moment the feed opens.
47
+ context.transport ?? null),
48
+ }),
49
+ // `satisfies` rather than a return annotation, so `id` keeps its literal
50
+ // type and a plugin list's surface can be keyed by id at the type level.
51
+ };
52
+ }
@@ -5,6 +5,6 @@
5
5
  * and opt-in field-level reactivity) and registers the model's properties,
6
6
  * relations, and any local-database indexes.
7
7
  */
8
- import type { Schema } from '../schema/schema.js';
8
+ import type { Schema } from '../transaction/schema/schema.js';
9
9
  import type { ModelRegistry } from '../ModelRegistry.js';
10
10
  export declare function registerModelsFromSchema(schema: Schema, registry: ModelRegistry): void;
@@ -6,9 +6,9 @@
6
6
  * relations, and any local-database indexes.
7
7
  */
8
8
  import { z } from 'zod';
9
- import { baseFieldsSchema } from '../schema/schema.js';
9
+ import { baseFieldsSchema } from '../transaction/schema/schema.js';
10
10
  import { Model } from '../Model.js';
11
- import { LoadStrategy, PropertyType } from '../types/index.js';
11
+ import { PropertyType } from '../transaction/types/index.js';
12
12
  // ── Auto model registration from schema ───────────────────────────────────
13
13
  export function registerModelsFromSchema(schema, registry) {
14
14
  registry.startBatch();
@@ -50,10 +50,10 @@ export function registerModelsFromSchema(schema, registry) {
50
50
  ];
51
51
  const computed = modelDef.computed;
52
52
  const DynamicModel = createDynamicModelClass(modelName, jsonSubFields, fieldNames, computed, isLazy);
53
- // Respect the schema's load strategy so lazy models skip IDB hydration + bootstrap
54
- const loadStrategy = modelDef.load === 'lazy' || modelDef.load === 'manual'
55
- ? LoadStrategy.lazy
56
- : LoadStrategy.instant;
53
+ // The schema's strategy carries straight through authoring and runtime
54
+ // name the same set, so there is nothing here to translate and nothing to
55
+ // fall out of step. Lazy models skip IDB hydration and bootstrap.
56
+ const loadStrategy = modelDef.load;
57
57
  registry.registerModel(modelName, DynamicModel, {
58
58
  loadStrategy,
59
59
  fields: modelDef.fields,
@@ -70,14 +70,14 @@ export function registerModelsFromSchema(schema, registry) {
70
70
  // id, and indexing every scalar is worse still.
71
71
  const indexedFields = new Set();
72
72
  for (const relDef of Object.values(modelDef.relations)) {
73
- if (relDef.type === 'belongsTo' && relDef.foreignKey && relDef.options?.index === true) {
73
+ if (relDef.type === 'belongsTo' && relDef.foreignKey && relDef.options.index === true) {
74
74
  indexedFields.add(relDef.foreignKey);
75
75
  }
76
76
  }
77
77
  // Register fields as properties (from Zod shape).
78
78
  for (const [fieldName, rawZodType] of Object.entries(modelDef.shape)) {
79
79
  const zodType = rawZodType;
80
- const isOptional = zodType.isOptional?.() ?? false;
80
+ const isOptional = zodType.isOptional();
81
81
  // A field is indexed if it is the foreign key of a
82
82
  // `belongsTo({ index: true })` relation. A `description === 'indexed'` tag
83
83
  // also works, for consumers using the `field.*().indexed()` builder.
@@ -87,7 +87,7 @@ export function registerModelsFromSchema(schema, registry) {
87
87
  // would walk every nested property and create an atom per leaf, producing a
88
88
  // storm of updates on each commit or streaming change. Reference tracking
89
89
  // watches only reassignment, which is how blob consumers actually use them.
90
- const wireType = modelDef.fields?.[fieldName]?.type;
90
+ const wireType = modelDef.fields[fieldName]?.type;
91
91
  const observability = wireType === 'json' ? 'ref' : undefined;
92
92
  registry.registerProperty(modelName, fieldName, {
93
93
  type: PropertyType.property,