@abloatai/ablo 0.36.0 → 0.37.1

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 (597) hide show
  1. package/AGENTS.md +2 -2
  2. package/CHANGELOG.md +55 -2014
  3. package/NOTICE +2 -2
  4. package/README.md +45 -63
  5. package/assets/banner.png +0 -0
  6. package/dist/auth.d.ts +2 -0
  7. package/dist/auth.d.ts.map +1 -0
  8. package/dist/auth.js +2 -0
  9. package/dist/auth.js.map +1 -0
  10. package/dist/client.d.ts +3 -0
  11. package/dist/client.d.ts.map +1 -0
  12. package/dist/client.js +3 -0
  13. package/dist/client.js.map +1 -0
  14. package/dist/coordination.d.ts +2 -0
  15. package/dist/coordination.d.ts.map +1 -0
  16. package/dist/coordination.js +2 -0
  17. package/dist/coordination.js.map +1 -0
  18. package/dist/index.d.ts +3 -114
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +3 -163
  21. package/dist/index.js.map +1 -0
  22. package/dist/react.d.ts +4 -0
  23. package/dist/react.d.ts.map +1 -0
  24. package/dist/react.js +3 -0
  25. package/dist/react.js.map +1 -0
  26. package/dist/schema.d.ts +2 -0
  27. package/dist/schema.d.ts.map +1 -0
  28. package/dist/schema.js +2 -0
  29. package/dist/schema.js.map +1 -0
  30. package/dist/server.d.ts +2 -0
  31. package/dist/server.d.ts.map +1 -0
  32. package/dist/server.js +2 -0
  33. package/dist/server.js.map +1 -0
  34. package/dist/source-conformance.d.ts +2 -0
  35. package/dist/source-conformance.d.ts.map +1 -0
  36. package/dist/source-conformance.js +2 -0
  37. package/dist/source-conformance.js.map +1 -0
  38. package/dist/source-drizzle.d.ts +2 -0
  39. package/dist/source-drizzle.d.ts.map +1 -0
  40. package/dist/source-drizzle.js +2 -0
  41. package/dist/source-drizzle.js.map +1 -0
  42. package/dist/source-kysely.d.ts +2 -0
  43. package/dist/source-kysely.d.ts.map +1 -0
  44. package/dist/source-kysely.js +2 -0
  45. package/dist/source-kysely.js.map +1 -0
  46. package/dist/source-next.d.ts +2 -0
  47. package/dist/source-next.d.ts.map +1 -0
  48. package/dist/source-next.js +2 -0
  49. package/dist/source-next.js.map +1 -0
  50. package/dist/source.d.ts +2 -0
  51. package/dist/source.d.ts.map +1 -0
  52. package/dist/source.js +2 -0
  53. package/dist/source.js.map +1 -0
  54. package/dist/wire.d.ts +2 -0
  55. package/dist/wire.d.ts.map +1 -0
  56. package/dist/wire.js +2 -0
  57. package/dist/wire.js.map +1 -0
  58. package/docs/agents.md +1 -1
  59. package/docs/api-keys.md +7 -6
  60. package/docs/api.md +10 -10
  61. package/docs/client-behavior.md +5 -5
  62. package/docs/coordination.md +52 -62
  63. package/docs/data-sources.md +1 -1
  64. package/docs/examples/agent-human.md +4 -4
  65. package/docs/examples/ai-sdk-tool.md +1 -1
  66. package/docs/examples/existing-python-backend.md +15 -4
  67. package/docs/examples/nextjs.md +27 -6
  68. package/docs/examples/server-agent.md +2 -2
  69. package/docs/how-it-works.md +4 -4
  70. package/docs/identity.md +2 -1
  71. package/docs/integration-guide.md +24 -13
  72. package/docs/internal/README.md +18 -0
  73. package/docs/internal/agent-fleet-coordination-design.md +171 -0
  74. package/docs/internal/agent-orchestration.md +58 -0
  75. package/docs/internal/commit-identifiers.md +91 -0
  76. package/docs/internal/concurrency-open-decisions.md +37 -0
  77. package/docs/internal/data-source-reverse-channel.md +150 -0
  78. package/docs/internal/per-field-conflict-detection.md +165 -0
  79. package/docs/internal/postgres-replication.md +64 -0
  80. package/docs/internal/serializable-schema.md +119 -0
  81. package/docs/internal/structure.md +32 -0
  82. package/docs/mcp.md +2 -2
  83. package/docs/migration.md +3 -3
  84. package/docs/quickstart.md +2 -2
  85. package/docs/react.md +5 -5
  86. package/docs/schema-contract.md +3 -3
  87. package/docs/sessions.md +91 -37
  88. package/examples/README.md +2 -2
  89. package/examples/data-source/README.md +1 -1
  90. package/examples/data-source/ablo-driver.ts +1 -1
  91. package/examples/data-source/customer-server.ts +1 -1
  92. package/examples/data-source/run.ts +1 -1
  93. package/examples/data-source/schema.ts +1 -1
  94. package/examples/quickstart.ts +2 -2
  95. package/llms.txt +8 -8
  96. package/package.json +63 -166
  97. package/bin/ablo.cjs +0 -39
  98. package/dist/BaseSyncedStore.d.ts +0 -843
  99. package/dist/BaseSyncedStore.js +0 -1971
  100. package/dist/Database.d.ts +0 -323
  101. package/dist/Database.js +0 -1502
  102. package/dist/InstanceCache.d.ts +0 -237
  103. package/dist/InstanceCache.js +0 -1166
  104. package/dist/LazyReferenceCollection.d.ts +0 -177
  105. package/dist/LazyReferenceCollection.js +0 -461
  106. package/dist/Model.d.ts +0 -454
  107. package/dist/Model.js +0 -919
  108. package/dist/ModelRegistry.d.ts +0 -225
  109. package/dist/ModelRegistry.js +0 -539
  110. package/dist/NetworkMonitor.d.ts +0 -28
  111. package/dist/NetworkMonitor.js +0 -79
  112. package/dist/RuntimeContext.d.ts +0 -52
  113. package/dist/RuntimeContext.js +0 -80
  114. package/dist/SyncClient.d.ts +0 -541
  115. package/dist/SyncClient.js +0 -2202
  116. package/dist/adapters/alwaysOnline.d.ts +0 -14
  117. package/dist/adapters/alwaysOnline.js +0 -17
  118. package/dist/adapters/inMemoryStorage.d.ts +0 -31
  119. package/dist/adapters/inMemoryStorage.js +0 -110
  120. package/dist/ai-sdk/coordinatedTool.d.ts +0 -120
  121. package/dist/ai-sdk/coordinatedTool.js +0 -134
  122. package/dist/ai-sdk/coordinationContext.d.ts +0 -46
  123. package/dist/ai-sdk/coordinationContext.js +0 -106
  124. package/dist/ai-sdk/index.d.ts +0 -121
  125. package/dist/ai-sdk/index.js +0 -121
  126. package/dist/ai-sdk/wrap.d.ts +0 -65
  127. package/dist/ai-sdk/wrap.js +0 -39
  128. package/dist/auth/index.d.ts +0 -1
  129. package/dist/auth/index.js +0 -8
  130. package/dist/batching/index.d.ts +0 -55
  131. package/dist/batching/index.js +0 -147
  132. package/dist/client/Ablo.d.ts +0 -231
  133. package/dist/client/Ablo.js +0 -160
  134. package/dist/client/abloClient.d.ts +0 -309
  135. package/dist/client/abloClient.js +0 -13
  136. package/dist/client/clientPrelude.d.ts +0 -52
  137. package/dist/client/clientPrelude.js +0 -60
  138. package/dist/client/consoleLogger.d.ts +0 -35
  139. package/dist/client/consoleLogger.js +0 -44
  140. package/dist/client/coreClient.d.ts +0 -60
  141. package/dist/client/coreClient.js +0 -118
  142. package/dist/client/createInternalComponents.d.ts +0 -50
  143. package/dist/client/createInternalComponents.js +0 -98
  144. package/dist/client/createModelProxy.d.ts +0 -248
  145. package/dist/client/createModelProxy.js +0 -884
  146. package/dist/client/humans.d.ts +0 -69
  147. package/dist/client/humans.js +0 -78
  148. package/dist/client/modelRegistration.d.ts +0 -10
  149. package/dist/client/modelRegistration.js +0 -312
  150. package/dist/client/options.d.ts +0 -461
  151. package/dist/client/options.js +0 -7
  152. package/dist/client/reactiveEngine.d.ts +0 -53
  153. package/dist/client/reactiveEngine.js +0 -688
  154. package/dist/client/resourceTypes.d.ts +0 -12
  155. package/dist/client/resourceTypes.js +0 -10
  156. package/dist/client/schemaConfig.d.ts +0 -44
  157. package/dist/client/schemaConfig.js +0 -185
  158. package/dist/client/storeCluster.d.ts +0 -47
  159. package/dist/client/storeCluster.js +0 -118
  160. package/dist/client/storeLifecycle.d.ts +0 -61
  161. package/dist/client/storeLifecycle.js +0 -231
  162. package/dist/client/validateAbloOptions.d.ts +0 -42
  163. package/dist/client/validateAbloOptions.js +0 -43
  164. package/dist/client/wsMutationExecutor.d.ts +0 -27
  165. package/dist/client/wsMutationExecutor.js +0 -72
  166. package/dist/context.d.ts +0 -42
  167. package/dist/context.js +0 -81
  168. package/dist/coordination/ClaimLog.d.ts +0 -26
  169. package/dist/coordination/ClaimLog.js +0 -32
  170. package/dist/coordination/index.d.ts +0 -1
  171. package/dist/coordination/index.js +0 -8
  172. package/dist/core/index.d.ts +0 -33
  173. package/dist/core/index.js +0 -48
  174. package/dist/docs/catalog.d.ts +0 -72
  175. package/dist/docs/catalog.js +0 -230
  176. package/dist/docs/index.d.ts +0 -10
  177. package/dist/docs/index.js +0 -10
  178. package/dist/environment.d.ts +0 -1
  179. package/dist/environment.js +0 -8
  180. package/dist/interfaces/index.d.ts +0 -311
  181. package/dist/interfaces/index.js +0 -9
  182. package/dist/keys/index.d.ts +0 -1
  183. package/dist/keys/index.js +0 -8
  184. package/dist/mutators/RecordingMutation.d.ts +0 -36
  185. package/dist/mutators/RecordingMutation.js +0 -182
  186. package/dist/mutators/Transaction.d.ts +0 -40
  187. package/dist/mutators/Transaction.js +0 -58
  188. package/dist/mutators/UndoManager.d.ts +0 -258
  189. package/dist/mutators/UndoManager.js +0 -658
  190. package/dist/mutators/defineMutators.d.ts +0 -60
  191. package/dist/mutators/defineMutators.js +0 -18
  192. package/dist/mutators/inverseOp.d.ts +0 -126
  193. package/dist/mutators/inverseOp.js +0 -71
  194. package/dist/mutators/mutateActions.d.ts +0 -45
  195. package/dist/mutators/mutateActions.js +0 -105
  196. package/dist/mutators/readerActions.d.ts +0 -33
  197. package/dist/mutators/readerActions.js +0 -57
  198. package/dist/mutators/undoApply.d.ts +0 -51
  199. package/dist/mutators/undoApply.js +0 -117
  200. package/dist/policy/index.d.ts +0 -21
  201. package/dist/policy/index.js +0 -20
  202. package/dist/query/QueryProcessor.d.ts +0 -75
  203. package/dist/query/QueryProcessor.js +0 -255
  204. package/dist/query/client.d.ts +0 -64
  205. package/dist/query/client.js +0 -138
  206. package/dist/query/types.d.ts +0 -85
  207. package/dist/query/types.js +0 -16
  208. package/dist/react/AbloProvider.d.ts +0 -242
  209. package/dist/react/AbloProvider.js +0 -458
  210. package/dist/react/ClientSideSuspense.d.ts +0 -36
  211. package/dist/react/ClientSideSuspense.js +0 -17
  212. package/dist/react/DefaultFallback.d.ts +0 -24
  213. package/dist/react/DefaultFallback.js +0 -43
  214. package/dist/react/context.d.ts +0 -55
  215. package/dist/react/context.js +0 -29
  216. package/dist/react/createAbloReact.d.ts +0 -56
  217. package/dist/react/createAbloReact.js +0 -51
  218. package/dist/react/index.d.ts +0 -62
  219. package/dist/react/index.js +0 -69
  220. package/dist/react/internalContext.d.ts +0 -33
  221. package/dist/react/internalContext.js +0 -3
  222. package/dist/react/useAblo.d.ts +0 -82
  223. package/dist/react/useAblo.js +0 -120
  224. package/dist/react/useCurrentUserId.d.ts +0 -22
  225. package/dist/react/useCurrentUserId.js +0 -34
  226. package/dist/react/useErrorListener.d.ts +0 -20
  227. package/dist/react/useErrorListener.js +0 -38
  228. package/dist/react/useMutationFailureListener.d.ts +0 -26
  229. package/dist/react/useMutationFailureListener.js +0 -38
  230. package/dist/react/useMutators.d.ts +0 -56
  231. package/dist/react/useMutators.js +0 -84
  232. package/dist/react/useReactive.d.ts +0 -35
  233. package/dist/react/useReactive.js +0 -123
  234. package/dist/react/useSyncStatus.d.ts +0 -59
  235. package/dist/react/useSyncStatus.js +0 -76
  236. package/dist/react/useUndoScope.d.ts +0 -34
  237. package/dist/react/useUndoScope.js +0 -81
  238. package/dist/schema/coordination.d.ts +0 -112
  239. package/dist/schema/coordination.js +0 -133
  240. package/dist/schema/ddl.d.ts +0 -97
  241. package/dist/schema/ddl.js +0 -491
  242. package/dist/schema/ddlLock.d.ts +0 -35
  243. package/dist/schema/ddlLock.js +0 -46
  244. package/dist/schema/diff.d.ts +0 -225
  245. package/dist/schema/diff.js +0 -289
  246. package/dist/schema/generate.d.ts +0 -19
  247. package/dist/schema/generate.js +0 -86
  248. package/dist/schema/index.d.ts +0 -42
  249. package/dist/schema/index.js +0 -80
  250. package/dist/schema/queries.d.ts +0 -201
  251. package/dist/schema/queries.js +0 -144
  252. package/dist/schema/select.d.ts +0 -40
  253. package/dist/schema/select.js +0 -90
  254. package/dist/schema/serialize.d.ts +0 -115
  255. package/dist/schema/serialize.js +0 -265
  256. package/dist/schema/sugar.d.ts +0 -109
  257. package/dist/schema/sugar.js +0 -83
  258. package/dist/schema/syncDeltaRow.d.ts +0 -6
  259. package/dist/schema/syncDeltaRow.js +0 -6
  260. package/dist/server/adapter.d.ts +0 -173
  261. package/dist/server/adapter.js +0 -18
  262. package/dist/server/commit.d.ts +0 -107
  263. package/dist/server/commit.js +0 -1
  264. package/dist/server/index.d.ts +0 -14
  265. package/dist/server/index.js +0 -2
  266. package/dist/server/readConfig.d.ts +0 -80
  267. package/dist/server/readConfig.js +0 -8
  268. package/dist/server/storageMode.d.ts +0 -23
  269. package/dist/server/storageMode.js +0 -17
  270. package/dist/source/adapter.d.ts +0 -83
  271. package/dist/source/adapter.js +0 -24
  272. package/dist/source/adapters/drizzle.d.ts +0 -48
  273. package/dist/source/adapters/drizzle.js +0 -219
  274. package/dist/source/adapters/kysely.d.ts +0 -42
  275. package/dist/source/adapters/kysely.js +0 -205
  276. package/dist/source/adapters/kyselyMutationCore.d.ts +0 -76
  277. package/dist/source/adapters/kyselyMutationCore.js +0 -125
  278. package/dist/source/adapters/memory.d.ts +0 -13
  279. package/dist/source/adapters/memory.js +0 -130
  280. package/dist/source/adapters/prisma.d.ts +0 -63
  281. package/dist/source/adapters/prisma.js +0 -202
  282. package/dist/source/conformance.d.ts +0 -37
  283. package/dist/source/conformance.js +0 -215
  284. package/dist/source/connector.d.ts +0 -95
  285. package/dist/source/connector.js +0 -266
  286. package/dist/source/connectorProtocol.d.ts +0 -154
  287. package/dist/source/connectorProtocol.js +0 -163
  288. package/dist/source/contract.d.ts +0 -195
  289. package/dist/source/contract.js +0 -164
  290. package/dist/source/factory.d.ts +0 -92
  291. package/dist/source/factory.js +0 -286
  292. package/dist/source/idempotency.d.ts +0 -61
  293. package/dist/source/idempotency.js +0 -144
  294. package/dist/source/index.d.ts +0 -23
  295. package/dist/source/index.js +0 -30
  296. package/dist/source/migrations.d.ts +0 -21
  297. package/dist/source/migrations.js +0 -103
  298. package/dist/source/next.d.ts +0 -32
  299. package/dist/source/next.js +0 -25
  300. package/dist/source/pushQueue.d.ts +0 -134
  301. package/dist/source/pushQueue.js +0 -256
  302. package/dist/source/signing.d.ts +0 -92
  303. package/dist/source/signing.js +0 -162
  304. package/dist/source/types.d.ts +0 -401
  305. package/dist/source/types.js +0 -59
  306. package/dist/storeContract.d.ts +0 -145
  307. package/dist/storeContract.js +0 -12
  308. package/dist/stores/DatabaseManager.d.ts +0 -107
  309. package/dist/stores/DatabaseManager.js +0 -388
  310. package/dist/stores/ObjectStore.d.ts +0 -115
  311. package/dist/stores/ObjectStore.js +0 -393
  312. package/dist/stores/ObjectStoreContract.d.ts +0 -38
  313. package/dist/stores/ObjectStoreContract.js +0 -1
  314. package/dist/stores/StoreManager.d.ts +0 -114
  315. package/dist/stores/StoreManager.js +0 -304
  316. package/dist/stores/SyncActionStore.d.ts +0 -99
  317. package/dist/stores/SyncActionStore.js +0 -506
  318. package/dist/stores/openIDBWithTimeout.d.ts +0 -65
  319. package/dist/stores/openIDBWithTimeout.js +0 -153
  320. package/dist/stores/syncAction.d.ts +0 -26
  321. package/dist/stores/syncAction.js +0 -16
  322. package/dist/surface.d.ts +0 -36
  323. package/dist/surface.js +0 -75
  324. package/dist/sync/BootstrapFetcher.d.ts +0 -284
  325. package/dist/sync/BootstrapFetcher.js +0 -964
  326. package/dist/sync/ConnectionManager.d.ts +0 -8
  327. package/dist/sync/ConnectionManager.js +0 -8
  328. package/dist/sync/OnDemandLoader.d.ts +0 -231
  329. package/dist/sync/OnDemandLoader.js +0 -743
  330. package/dist/sync/SubscriptionManager.d.ts +0 -159
  331. package/dist/sync/SubscriptionManager.js +0 -243
  332. package/dist/sync/SyncWebSocket.d.ts +0 -173
  333. package/dist/sync/SyncWebSocket.js +0 -438
  334. package/dist/sync/awaitClaimGrant.d.ts +0 -6
  335. package/dist/sync/awaitClaimGrant.js +0 -6
  336. package/dist/sync/bootstrapApply.d.ts +0 -73
  337. package/dist/sync/bootstrapApply.js +0 -73
  338. package/dist/sync/commitFrames.d.ts +0 -8
  339. package/dist/sync/commitFrames.js +0 -8
  340. package/dist/sync/contextPorts.d.ts +0 -18
  341. package/dist/sync/contextPorts.js +0 -31
  342. package/dist/sync/createClaimStream.d.ts +0 -7
  343. package/dist/sync/createClaimStream.js +0 -7
  344. package/dist/sync/createPresenceStream.d.ts +0 -69
  345. package/dist/sync/createPresenceStream.js +0 -200
  346. package/dist/sync/createSnapshot.d.ts +0 -29
  347. package/dist/sync/createSnapshot.js +0 -118
  348. package/dist/sync/credentialLifecycle.d.ts +0 -7
  349. package/dist/sync/credentialLifecycle.js +0 -7
  350. package/dist/sync/deltaPipeline.d.ts +0 -114
  351. package/dist/sync/deltaPipeline.js +0 -278
  352. package/dist/sync/groupChange.d.ts +0 -116
  353. package/dist/sync/groupChange.js +0 -244
  354. package/dist/sync/participants.d.ts +0 -132
  355. package/dist/sync/participants.js +0 -346
  356. package/dist/sync/persistedPrefix.d.ts +0 -12
  357. package/dist/sync/persistedPrefix.js +0 -22
  358. package/dist/sync/schemaDrift.d.ts +0 -55
  359. package/dist/sync/schemaDrift.js +0 -53
  360. package/dist/sync/schemas.d.ts +0 -71
  361. package/dist/sync/schemas.js +0 -94
  362. package/dist/sync/syncCursor.d.ts +0 -40
  363. package/dist/sync/syncCursor.js +0 -55
  364. package/dist/sync/syncPlan.d.ts +0 -54
  365. package/dist/sync/syncPlan.js +0 -50
  366. package/dist/sync/wsFrameHandlers.d.ts +0 -8
  367. package/dist/sync/wsFrameHandlers.js +0 -8
  368. package/dist/syncLog/contract.d.ts +0 -20
  369. package/dist/syncLog/contract.js +0 -19
  370. package/dist/syncLog/index.d.ts +0 -1
  371. package/dist/syncLog/index.js +0 -1
  372. package/dist/transaction/ablo.d.ts +0 -88
  373. package/dist/transaction/ablo.js +0 -33
  374. package/dist/transaction/auth/apiKey.d.ts +0 -152
  375. package/dist/transaction/auth/apiKey.js +0 -419
  376. package/dist/transaction/auth/bootstrapScope.d.ts +0 -15
  377. package/dist/transaction/auth/bootstrapScope.js +0 -1
  378. package/dist/transaction/auth/capability.d.ts +0 -212
  379. package/dist/transaction/auth/capability.js +0 -224
  380. package/dist/transaction/auth/credentialEndpoint.d.ts +0 -61
  381. package/dist/transaction/auth/credentialEndpoint.js +0 -86
  382. package/dist/transaction/auth/credentialPolicy.d.ts +0 -148
  383. package/dist/transaction/auth/credentialPolicy.js +0 -125
  384. package/dist/transaction/auth/credentialSource.d.ts +0 -30
  385. package/dist/transaction/auth/credentialSource.js +0 -55
  386. package/dist/transaction/auth/hostedEndpoints.d.ts +0 -21
  387. package/dist/transaction/auth/hostedEndpoints.js +0 -21
  388. package/dist/transaction/auth/identity.d.ts +0 -55
  389. package/dist/transaction/auth/identity.js +0 -210
  390. package/dist/transaction/auth/index.d.ts +0 -162
  391. package/dist/transaction/auth/index.js +0 -304
  392. package/dist/transaction/auth/schemas.d.ts +0 -59
  393. package/dist/transaction/auth/schemas.js +0 -85
  394. package/dist/transaction/auth/sessionMint.d.ts +0 -28
  395. package/dist/transaction/auth/sessionMint.js +0 -85
  396. package/dist/transaction/coordination/awaitClaimGrant.d.ts +0 -56
  397. package/dist/transaction/coordination/awaitClaimGrant.js +0 -124
  398. package/dist/transaction/coordination/claimHeartbeatLoop.d.ts +0 -84
  399. package/dist/transaction/coordination/claimHeartbeatLoop.js +0 -108
  400. package/dist/transaction/coordination/claimMeta.d.ts +0 -49
  401. package/dist/transaction/coordination/claimMeta.js +0 -52
  402. package/dist/transaction/coordination/createClaimStream.d.ts +0 -64
  403. package/dist/transaction/coordination/createClaimStream.js +0 -475
  404. package/dist/transaction/coordination/events.d.ts +0 -74
  405. package/dist/transaction/coordination/events.js +0 -7
  406. package/dist/transaction/coordination/index.d.ts +0 -19
  407. package/dist/transaction/coordination/index.js +0 -45
  408. package/dist/transaction/coordination/locator.d.ts +0 -104
  409. package/dist/transaction/coordination/locator.js +0 -102
  410. package/dist/transaction/coordination/schema.d.ts +0 -1536
  411. package/dist/transaction/coordination/schema.js +0 -1177
  412. package/dist/transaction/coordination/targetConflict.d.ts +0 -2
  413. package/dist/transaction/coordination/targetConflict.js +0 -107
  414. package/dist/transaction/coordination/trace.d.ts +0 -78
  415. package/dist/transaction/coordination/trace.js +0 -138
  416. package/dist/transaction/durableWrites.d.ts +0 -62
  417. package/dist/transaction/durableWrites.js +0 -71
  418. package/dist/transaction/environment.d.ts +0 -105
  419. package/dist/transaction/environment.js +0 -108
  420. package/dist/transaction/errorCodes.d.ts +0 -403
  421. package/dist/transaction/errorCodes.js +0 -484
  422. package/dist/transaction/errors.d.ts +0 -428
  423. package/dist/transaction/errors.js +0 -686
  424. package/dist/transaction/footprint.d.ts +0 -111
  425. package/dist/transaction/footprint.js +0 -0
  426. package/dist/transaction/index.d.ts +0 -20
  427. package/dist/transaction/index.js +0 -20
  428. package/dist/transaction/keys/index.d.ts +0 -87
  429. package/dist/transaction/keys/index.js +0 -207
  430. package/dist/transaction/log/syncDeltaRow.d.ts +0 -158
  431. package/dist/transaction/log/syncDeltaRow.js +0 -95
  432. package/dist/transaction/logPosition.d.ts +0 -97
  433. package/dist/transaction/logPosition.js +0 -125
  434. package/dist/transaction/logger.d.ts +0 -16
  435. package/dist/transaction/logger.js +0 -7
  436. package/dist/transaction/observability.d.ts +0 -53
  437. package/dist/transaction/observability.js +0 -19
  438. package/dist/transaction/persistence.d.ts +0 -12
  439. package/dist/transaction/persistence.js +0 -11
  440. package/dist/transaction/plugin.d.ts +0 -285
  441. package/dist/transaction/plugin.js +0 -106
  442. package/dist/transaction/policy/types.d.ts +0 -217
  443. package/dist/transaction/policy/types.js +0 -126
  444. package/dist/transaction/resources/functionalUpdate.d.ts +0 -79
  445. package/dist/transaction/resources/functionalUpdate.js +0 -87
  446. package/dist/transaction/resources/httpResources.d.ts +0 -321
  447. package/dist/transaction/resources/httpResources.js +0 -7
  448. package/dist/transaction/resources/modelOperations.d.ts +0 -427
  449. package/dist/transaction/resources/modelOperations.js +0 -12
  450. package/dist/transaction/resources/mutationOptions.d.ts +0 -66
  451. package/dist/transaction/resources/mutationOptions.js +0 -9
  452. package/dist/transaction/resources/where.d.ts +0 -101
  453. package/dist/transaction/resources/where.js +0 -115
  454. package/dist/transaction/resources/writeOptionsSchema.d.ts +0 -47
  455. package/dist/transaction/resources/writeOptionsSchema.js +0 -73
  456. package/dist/transaction/schema/field.d.ts +0 -120
  457. package/dist/transaction/schema/field.js +0 -265
  458. package/dist/transaction/schema/fieldRef.d.ts +0 -38
  459. package/dist/transaction/schema/fieldRef.js +0 -11
  460. package/dist/transaction/schema/loadStrategy.d.ts +0 -45
  461. package/dist/transaction/schema/loadStrategy.js +0 -46
  462. package/dist/transaction/schema/model.d.ts +0 -379
  463. package/dist/transaction/schema/model.js +0 -123
  464. package/dist/transaction/schema/openapi.d.ts +0 -58
  465. package/dist/transaction/schema/openapi.js +0 -501
  466. package/dist/transaction/schema/relation.d.ts +0 -204
  467. package/dist/transaction/schema/relation.js +0 -104
  468. package/dist/transaction/schema/residency.d.ts +0 -29
  469. package/dist/transaction/schema/residency.js +0 -25
  470. package/dist/transaction/schema/roles.d.ts +0 -249
  471. package/dist/transaction/schema/roles.js +0 -230
  472. package/dist/transaction/schema/schema.d.ts +0 -351
  473. package/dist/transaction/schema/schema.js +0 -325
  474. package/dist/transaction/schema/tenancy.d.ts +0 -139
  475. package/dist/transaction/schema/tenancy.js +0 -190
  476. package/dist/transaction/transactionLayer.d.ts +0 -82
  477. package/dist/transaction/transactionLayer.js +0 -24
  478. package/dist/transaction/transactions/settlement/commitEnvelope.d.ts +0 -143
  479. package/dist/transaction/transactions/settlement/commitEnvelope.js +0 -161
  480. package/dist/transaction/transactions/settlement/httpCommitEnvelope.d.ts +0 -53
  481. package/dist/transaction/transactions/settlement/httpCommitEnvelope.js +0 -207
  482. package/dist/transaction/transactions/settlement/idempotencyKey.d.ts +0 -10
  483. package/dist/transaction/transactions/settlement/idempotencyKey.js +0 -9
  484. package/dist/transaction/transactions/settlement/pendingWrite.d.ts +0 -112
  485. package/dist/transaction/transactions/settlement/pendingWrite.js +0 -20
  486. package/dist/transaction/transport/commitFrames.d.ts +0 -90
  487. package/dist/transaction/transport/commitFrames.js +0 -134
  488. package/dist/transaction/transport/connectionManager.d.ts +0 -215
  489. package/dist/transaction/transport/connectionManager.js +0 -673
  490. package/dist/transaction/transport/credentialLifecycle.d.ts +0 -177
  491. package/dist/transaction/transport/credentialLifecycle.js +0 -324
  492. package/dist/transaction/transport/heartbeat.d.ts +0 -65
  493. package/dist/transaction/transport/heartbeat.js +0 -93
  494. package/dist/transaction/transport/httpClient.d.ts +0 -131
  495. package/dist/transaction/transport/httpClient.js +0 -146
  496. package/dist/transaction/transport/httpOptions.d.ts +0 -33
  497. package/dist/transaction/transport/httpOptions.js +0 -12
  498. package/dist/transaction/transport/httpTransport.d.ts +0 -8
  499. package/dist/transaction/transport/httpTransport.js +0 -1388
  500. package/dist/transaction/transport/networkProbe.d.ts +0 -84
  501. package/dist/transaction/transport/networkProbe.js +0 -207
  502. package/dist/transaction/transport/wsFrameHandlers.d.ts +0 -128
  503. package/dist/transaction/transport/wsFrameHandlers.js +0 -429
  504. package/dist/transaction/transport/wsTransport.d.ts +0 -574
  505. package/dist/transaction/transport/wsTransport.js +0 -1023
  506. package/dist/transaction/types/assertExact.d.ts +0 -17
  507. package/dist/transaction/types/assertExact.js +0 -1
  508. package/dist/transaction/types/global.d.ts +0 -107
  509. package/dist/transaction/types/global.js +0 -40
  510. package/dist/transaction/types/index.d.ts +0 -205
  511. package/dist/transaction/types/index.js +0 -56
  512. package/dist/transaction/types/modelData.d.ts +0 -10
  513. package/dist/transaction/types/modelData.js +0 -9
  514. package/dist/transaction/types/participant.d.ts +0 -20
  515. package/dist/transaction/types/participant.js +0 -10
  516. package/dist/transaction/types/streams.d.ts +0 -550
  517. package/dist/transaction/types/streams.js +0 -11
  518. package/dist/transaction/utils/asyncIterator.d.ts +0 -34
  519. package/dist/transaction/utils/asyncIterator.js +0 -135
  520. package/dist/transaction/utils/duration.d.ts +0 -50
  521. package/dist/transaction/utils/duration.js +0 -77
  522. package/dist/transaction/utils/json.d.ts +0 -57
  523. package/dist/transaction/utils/json.js +0 -276
  524. package/dist/transaction/wire/accountResponses.d.ts +0 -420
  525. package/dist/transaction/wire/accountResponses.js +0 -290
  526. package/dist/transaction/wire/auth.d.ts +0 -56
  527. package/dist/transaction/wire/auth.js +0 -63
  528. package/dist/transaction/wire/bootstrapReason.d.ts +0 -9
  529. package/dist/transaction/wire/bootstrapReason.js +0 -8
  530. package/dist/transaction/wire/claimEvent.d.ts +0 -76
  531. package/dist/transaction/wire/claimEvent.js +0 -73
  532. package/dist/transaction/wire/claims.d.ts +0 -530
  533. package/dist/transaction/wire/claims.js +0 -327
  534. package/dist/transaction/wire/commit.d.ts +0 -603
  535. package/dist/transaction/wire/commit.js +0 -321
  536. package/dist/transaction/wire/delta.d.ts +0 -250
  537. package/dist/transaction/wire/delta.js +0 -147
  538. package/dist/transaction/wire/errorEnvelope.d.ts +0 -72
  539. package/dist/transaction/wire/errorEnvelope.js +0 -123
  540. package/dist/transaction/wire/feedCursor.d.ts +0 -60
  541. package/dist/transaction/wire/feedCursor.js +0 -82
  542. package/dist/transaction/wire/feedEvent.d.ts +0 -204
  543. package/dist/transaction/wire/feedEvent.js +0 -65
  544. package/dist/transaction/wire/frames.d.ts +0 -194
  545. package/dist/transaction/wire/frames.js +0 -50
  546. package/dist/transaction/wire/inboundFrames.d.ts +0 -562
  547. package/dist/transaction/wire/inboundFrames.js +0 -116
  548. package/dist/transaction/wire/index.d.ts +0 -54
  549. package/dist/transaction/wire/index.js +0 -83
  550. package/dist/transaction/wire/listEnvelope.d.ts +0 -37
  551. package/dist/transaction/wire/listEnvelope.js +0 -42
  552. package/dist/transaction/wire/modelMutations.d.ts +0 -31
  553. package/dist/transaction/wire/modelMutations.js +0 -52
  554. package/dist/transaction/wire/modelResponses.d.ts +0 -85
  555. package/dist/transaction/wire/modelResponses.js +0 -43
  556. package/dist/transaction/wire/modelShape.d.ts +0 -78
  557. package/dist/transaction/wire/modelShape.js +0 -74
  558. package/dist/transaction/wire/protocol.d.ts +0 -38
  559. package/dist/transaction/wire/protocol.js +0 -38
  560. package/dist/transaction/wire/protocolVersion.d.ts +0 -73
  561. package/dist/transaction/wire/protocolVersion.js +0 -83
  562. package/dist/transactions/mutations/MutationQueue.d.ts +0 -661
  563. package/dist/transactions/mutations/MutationQueue.js +0 -2807
  564. package/dist/transactions/mutations/MutationStore.d.ts +0 -20
  565. package/dist/transactions/mutations/MutationStore.js +0 -53
  566. package/dist/transactions/mutations/UnconfirmedWrites.d.ts +0 -82
  567. package/dist/transactions/mutations/UnconfirmedWrites.js +0 -104
  568. package/dist/transactions/mutations/coalesceRules.d.ts +0 -58
  569. package/dist/transactions/mutations/coalesceRules.js +0 -140
  570. package/dist/transactions/mutations/commitLatency.d.ts +0 -52
  571. package/dist/transactions/mutations/commitLatency.js +0 -130
  572. package/dist/transactions/mutations/commitOutboxStore.d.ts +0 -28
  573. package/dist/transactions/mutations/commitOutboxStore.js +0 -26
  574. package/dist/transactions/mutations/commitPayload.d.ts +0 -165
  575. package/dist/transactions/mutations/commitPayload.js +0 -152
  576. package/dist/transactions/mutations/deltaConfirmation.d.ts +0 -63
  577. package/dist/transactions/mutations/deltaConfirmation.js +0 -235
  578. package/dist/transactions/mutations/durableWriteStore.d.ts +0 -14
  579. package/dist/transactions/mutations/durableWriteStore.js +0 -12
  580. package/dist/transactions/mutations/optimisticApply.d.ts +0 -49
  581. package/dist/transactions/mutations/optimisticApply.js +0 -65
  582. package/dist/transactions/mutations/replayValidation.d.ts +0 -187
  583. package/dist/transactions/mutations/replayValidation.js +0 -164
  584. package/dist/utils/mobxSetup.d.ts +0 -53
  585. package/dist/utils/mobxSetup.js +0 -330
  586. package/dist/views/QueryView.d.ts +0 -79
  587. package/dist/views/QueryView.js +0 -218
  588. package/dist/views/ViewRegistry.d.ts +0 -20
  589. package/dist/views/ViewRegistry.js +0 -55
  590. package/dist/views/incrementalView.d.ts +0 -45
  591. package/dist/views/incrementalView.js +0 -69
  592. package/dist/webhooks/events.d.ts +0 -43
  593. package/dist/webhooks/events.js +0 -42
  594. package/dist/webhooks/index.d.ts +0 -8
  595. package/dist/webhooks/index.js +0 -8
  596. package/dist/wire/index.d.ts +0 -1
  597. package/dist/wire/index.js +0 -8
@@ -0,0 +1,165 @@
1
+ # Per-Field Conflict Detection (Track A)
2
+
3
+ Maintainer decision doc. Scopes the move from entity-level to field-level stale
4
+ detection in `executeCommit`. Library-free; restores Linear parity for the
5
+ disjoint-field case while keeping the agent-specific `readAt` reject.
6
+
7
+ ## Problem
8
+
9
+ `executeCommit` Step 0 (`apps/sync-server/src/mutators/commit.ts`) detects stale
10
+ writes at **entity granularity**:
11
+
12
+ ```sql
13
+ SELECT MAX(id) FROM sync_deltas WHERE model_name = ? AND model_id = ?
14
+ ```
15
+
16
+ If `observed > op.readAt`, the op conflicts. This means two writers touching
17
+ **different fields** of the same row collide falsely: agent A sets
18
+ `report.status`, human B sets `report.reviewer`, B carried a `readAt` from before A's
19
+ write → B is rejected with `AbloStaleContextError`, even though the edits never
20
+ overlapped.
21
+
22
+ This is an over-rejection. It is also stricter than the system we
23
+ reverse-engineered from (Linear), which never had this problem.
24
+
25
+ ## Why Linear says this is right
26
+
27
+ The model is reverse-engineered from Linear's sync engine. Linear's design
28
+ confirms every load-bearing choice here:
29
+
30
+ - **Transactions are property-level.** Linear's `UpdateTransaction` records
31
+ "the name of the changed property and its previous value" — it carries only
32
+ the changed properties, not a whole-object snapshot. Our `changed_fields`
33
+ column re-derives exactly that.
34
+ - **Resolution is last-writer-wins, per property, by total order:** `syncId`
35
+ (our `sync_id_seq`) is the total order. A partial transaction applies only its
36
+ properties, so two clients editing **different** properties both win — LWW
37
+ only bites on the **same** property.
38
+ - **CRDT is used only for issue descriptions.** Linear keeps LWW-per-property
39
+ for structured fields and reserves a CRDT for the one rich-text body. That is
40
+ the same Track A / Track B line we draw: this doc is Track A; rich-text bodies
41
+ (TipTap `content_json`) are out of scope and belong to a separate CRDT track.
42
+
43
+ So Track A is not a new feature — it **restores Linear parity** at the property
44
+ level we had flattened to entity level.
45
+
46
+ Sources: [reverse-linear-sync-engine (CTO-endorsed)](https://github.com/wzhudev/reverse-linear-sync-engine/blob/main/SUMMARY.md),
47
+ [Architectures for Central Server Collaboration — Weidner](https://mattweidner.com/2024/06/04/server-architectures.html).
48
+
49
+ ## The constraint that shapes the design
50
+
51
+ `sync_deltas.data` stores the **full post-update row**, not the changed columns.
52
+ This was a deliberate change (see `feedback_partial_update_delta_ui_drift`) so
53
+ the live-pool update path fires MobX reactivity for nested fields. Consequence:
54
+ we **cannot** recover "which fields did this delta change" from `data` — a
55
+ full-row snapshot does not tell you what moved.
56
+
57
+ We do have the changed set for free at write time: `Object.keys(snakeInput)` at
58
+ `commit.ts` UPDATE branch, after the unknown-column strip and before the
59
+ `updated_at` injection. So this is a write-side capture + a read-side
60
+ intersection, not a diff-the-snapshots problem.
61
+
62
+ ## Design
63
+
64
+ ### 1. Schema: `sync_deltas.changed_fields text[]` (nullable)
65
+
66
+ - Populate **only for UPDATE** with the real changed columns
67
+ (`Object.keys(snakeInput)` after strip, before `updated_at`).
68
+ - Leave `null` for CREATE / DELETE / ARCHIVE / UNARCHIVE.
69
+
70
+ `null` is semantically "whole-entity change" and always conflicts. This gives a
71
+ **safe migration**: every pre-migration delta is `null`, so detection falls back
72
+ to exactly today's entity-level behavior. Field granularity phases in only as
73
+ new deltas land — no risky backfill.
74
+
75
+ We store **field names only**, not previous values. LWW needs no value
76
+ comparison (latest `sync_id` wins); names are sufficient for the overlap check
77
+ that drives the optional reject. Prev-values would only matter for
78
+ "same field, same value ⇒ not a conflict" tie-breaking — defer it.
79
+
80
+ ### 2. Detection rewrite: Step 0 (`commit.ts`)
81
+
82
+ Replace the scalar `MAX(id)` with a field-aware scan:
83
+
84
+ ```ts
85
+ // op's own field set (snake-cased, framework cols excluded)
86
+ const opFields = new Set(Object.keys(op.input ?? {}).map(toSnakeCase));
87
+
88
+ const rows = await tx.unsafe(
89
+ `SELECT id, changed_fields FROM sync_deltas
90
+ WHERE model_name = $1 AND model_id = $2 AND id > $3
91
+ ORDER BY id DESC`,
92
+ [mapping.modelName, op.id, op.readAt] as never[],
93
+ );
94
+
95
+ // Conflict iff a newer delta touched a field this op also writes,
96
+ // OR a newer delta is whole-entity (changed_fields IS NULL → CREATE/DELETE).
97
+ const overlap = rows.find(
98
+ (r) => r.changedFields === null || r.changedFields.some((f) => opFields.has(f)),
99
+ );
100
+ if (overlap) {
101
+ conflicts.push({
102
+ /* ...existing fields... */
103
+ observedSyncId: overlap.id,
104
+ conflictingFields: intersect(overlap.changedFields, opFields),
105
+ });
106
+ }
107
+ ```
108
+
109
+ Disjoint-field concurrent writes now produce **no conflict** — they both apply.
110
+ That is LWW-per-field achieved by *not rejecting*; no merge code.
111
+
112
+ ### 3. Policy type: additive (`packages/transaction/src/policy/types.ts`)
113
+
114
+ Extend `StaleContextConflict` with:
115
+
116
+ ```ts
117
+ readonly conflictingFields?: readonly string[];
118
+ ```
119
+
120
+ Pure addition. `defaultPolicy` still rejects; existing policies compile
121
+ unchanged. A policy can now reason at field granularity, e.g. allow when the
122
+ only conflicting field is cosmetic.
123
+
124
+ ### 4. Scope boundary (honest)
125
+
126
+ Granularity is **column-level**, not JSON-path. Two writers editing different
127
+ keys *inside* one `content_json` column still conflict — that is the rich-text
128
+ case (Track B / CRDT), not this. JSON Merge Patch (RFC 7386) sub-column
129
+ granularity is a later refinement on the same column; v1 stops at columns.
130
+
131
+ ## Relationship to the existing `readAt` reject
132
+
133
+ Linear is pure LWW-per-property with no stale check. We keep `readAt` /
134
+ `onStale: 'reject'` as an **opt-in** for the agent-reasoned-against-stale-state
135
+ case (an LLM that read a stale value and reasoned on it is a real failure mode
136
+ humans rarely hit). After Track A:
137
+
138
+ - **No `readAt`** → LWW-per-field, Linear parity: disjoint fields never conflict.
139
+ - **`readAt` set** → reject only if a newer delta touched a field this op also
140
+ writes. The `changed_fields` column makes that intersection computable.
141
+ - **`onStale: 'overwrite'`** → unchanged; still skips detection entirely.
142
+
143
+ ## Index
144
+
145
+ Verify a `(model_name, model_id, id)` index exists on `sync_deltas` (the old
146
+ `MAX(id)` relied on it too). The new query is a bounded range scan (`id >
147
+ readAt`, usually a small recent window) on the same index prefix.
148
+
149
+ ## Tests (vitest, sync-server)
150
+
151
+ - Disjoint fields (A: `status`, B: `assignee`, same row, both stale `readAt`) →
152
+ **both commit, no `AbloStaleContextError`** — the regression that proves the win.
153
+ - Same field, both stale → still rejects (default policy unchanged).
154
+ - DELETE after `readAt` → conflicts regardless of op fields (`null`).
155
+ - Pre-migration delta (`null`) in the window → conflicts (back-compat).
156
+ - `onStale: 'overwrite'` → still skips detection.
157
+
158
+ ## Touch list
159
+
160
+ - `sync_deltas` migration — add `changed_fields text[]`.
161
+ - `commit.ts` — Step 0 detect rewrite + UPDATE write path populates
162
+ `changed_fields` + `deltaInfos` shape.
163
+ - `apps/sync-server/src/db/deltas.ts` — insert path carries `changed_fields`.
164
+ - `packages/transaction/src/policy/types.ts` — additive `conflictingFields`.
165
+ - vitest in sync-server.
@@ -0,0 +1,64 @@
1
+ # Postgres replication: internal architecture
2
+
3
+ > **Status: wired and covered by unit and real-Postgres journeys.** This is server-internal code under `apps/sync-server/src/replication/postgres/`; it is not an SDK surface.
4
+
5
+ ## Why this exists
6
+
7
+ Ablo observes a customer's Postgres through a publication and logical-replication slot. The customer owns the schema and write path. Ablo decodes committed changes, appends them to its control-plane log, and serves sync from that log. The low-level decoder and lifecycle draw on Zero and PowerSync patterns; ADR 0002 governs the product boundary.
8
+
9
+ ## The one job
10
+
11
+ **Postgres `pgoutput` messages → `PreparedDelta[]` + a confirmed LSN.** The consumer writes through `appendExternalDeltas`; deltas land in the control-plane `sync_deltas` log and use the normal fan-out pipeline.
12
+
13
+ ## Module map (`apps/sync-server/src/replication/postgres/`)
14
+
15
+ | file | role | provenance |
16
+ | -------------------------------------------------------- | ---------------------------------------------------------- | ----------------------------- |
17
+ | `binaryReader.ts` | big-endian protocol reader | modeled on Zero |
18
+ | `pgoutputTypes.ts`, `pgoutput.ts` | typed `pgoutput` messages and decoder | modeled on Zero |
19
+ | `lsn.ts` | `LSN` string ↔ `bigint` (`toBigInt`/`fromBigInt`) | ported subset ← Zero `lsn.ts` |
20
+ | `connection.ts`, `stream.ts`, `streamAdapter.ts` | dedicated query/replication connections and stream adapter | Zero/PowerSync patterns |
21
+ | `assembler.ts` | buffers a transaction and maps changes to `PreparedDelta` | Ablo adapter |
22
+ | `consumer.ts` | persist-before-ack consume loop with retry | PowerSync/Ablo patterns |
23
+ | `slot.ts`, `slotLease.ts`, `backfill.ts`, `watermark.ts` | slot ownership, initial snapshot, and durable progress | Ablo |
24
+ | `sources.ts`, `fleet.ts`, `start.ts` | registry resolution, reconciliation, start/stop lifecycle | Ablo |
25
+ | `preflight.ts`, `readiness.ts`, `publicationDrift.ts` | registration checks and runtime diagnostics | Ablo |
26
+
27
+ ## Data flow
28
+
29
+ ```
30
+ registered Postgres source
31
+ → replication slot + initial snapshot
32
+ → pgoutput stream
33
+ → TransactionAssembler
34
+ → WalConsumer
35
+ → appendExternalDeltas(controlSql, deltas, context)
36
+ → persist watermark
37
+ → acknowledge commit LSN
38
+ ```
39
+
40
+ ### Mapping (in `TransactionAssembler`, mirrors `events.ts:eventsToDeltas`)
41
+
42
+ - `actionType`: `insert→'I'`, `update→'U'`, `delete→'D'` (the 1:1 pgoutput↔Ablo coincidence).
43
+ - `modelName`: `mapping.tableToModel(schema, table)` — `null` skips the change.
44
+ - `modelId`: `mapping.rowToModelId(key)` over the replica-identity key.
45
+ - `data`: the row bound as an **object, never pre-stringified** (the jsonb double-encode trap at `deltaAppend.ts`).
46
+ - `transactionId`: `String(xid)`.
47
+
48
+ ## Load-bearing invariants
49
+
50
+ - **Persist-before-ack** (`WalConsumer`): `appendExternalDeltas` and the watermark transaction resolve before `ack(commitLsn)`. A crash between them replays work instead of losing it.
51
+ - **Keepalive watermark** (`streamAdapter.ts`, `stream.ts`): every reply carries the last confirmed LSN, never the server's live position — the timed status update included.
52
+ - **Liveness off the socket** (`stream.ts`): a status update goes out every 75% of the upstream's `wal_sender_timeout` whether or not the consumer is reading, so backpressure cannot get the connection terminated for silence; inbound silence on a stream we are reading for twice that long destroys it and falls into the per-source backoff. A `wal_sender_timeout` of 0 runs untimed.
53
+ - **Failover-capable slot** (`slot.ts`): from PostgreSQL 17 the slot is created with `FAILOVER true`, so a customer failover leaves our position intact instead of forcing the re-snapshot path. It only takes effect where the standby has `sync_replication_slots = on`, which the preflight recommends and never requires.
54
+ - **Fresh subscription per retry** (`WalConsumer`): every backoff iteration opens a new subscription so a half-dead socket / stale relation cache never carries into the retry.
55
+ - **Per-source isolation** (`start.ts`, `fleet.ts`): one broken source reports and retries without stopping healthy sources.
56
+ - **Runtime reconciliation** (`fleet.ts`): registrations, removals, schema changes, and secret rotations converge without a server restart.
57
+
58
+ ## Tests
59
+
60
+ Unit tests live beside the implementation in `replication/postgres/__tests__`. Real-Postgres coverage is grouped under `src/__journeys__/postgres-replication-*.journey.test.ts`: registration, registry migration, backfill, live streaming, source changes, bootstrap, query serving, read cutover, and customer-database isolation.
61
+
62
+ ## Operations
63
+
64
+ Registration is the enable signal. `startPostgresReplication` starts the fleet after the server begins listening; `postgresReplicationReady` is drained during graceful shutdown. Use `docs/runbooks/connect-customer-database-postgres-replication.md` for source setup and live verification.
@@ -0,0 +1,119 @@
1
+ # A `Schema` is serializable
2
+
3
+ A `Schema` (output of `defineSchema`) is JSON-serializable except for two
4
+ things, both of which are client-only:
5
+
6
+ - **Zod validators:** `model().schema` / `.shape`, `Schema.validators`. Used
7
+ by the client for type inference + validation. The server never reads them
8
+ (it checks `information_schema.columns` and does no field-shape validation in
9
+ the commit path).
10
+
11
+ Everything the server reads — `typename`, `tableName`, `mutable`, `load`, the
12
+ canonical `tenancy` descriptor (the `policy` authoring option is normalized away
13
+ at build), bootstrap hints, `relations` (`foreignKeyColumn`), field names, and
14
+ `identityRoles` — is plain data.
15
+
16
+ ## Identity roles are pure data
17
+
18
+ ```ts
19
+ interface IdentityRole {
20
+ kind: string;
21
+ template: string; // 'org:{id}'
22
+ source: IdentityRoleSource; // { field: 'organizationId', multi: false }
23
+ }
24
+ ```
25
+
26
+ The runtime behaviour lives in `extractIdentityIds(identity, source)`, a pure
27
+ function `composeIdentitySyncGroups` calls once per role. `identityRole({ kind,
28
+ template, source, multi? })` is the factory. Absent/falsy fields yield `[]`, so
29
+ a role whose field isn't present (a user with no `teamIds`) is a silent no-op —
30
+ org-only, org+user, and org+team are just different `identityRoles` arrays, not
31
+ different code paths. The engine ships zero prefixes; `org:`/`user:`/`team:`
32
+ live only in `ablo.schema.ts`.
33
+
34
+ ## Why this matters
35
+
36
+ Because a `Schema` carries no closures, the same object works in-process and,
37
+ for a hosted multi-tenant server, after being reconstructed from JSON over the
38
+ control plane (the GraphQL `printSchema` / `buildSchema` model). One type,
39
+ both places — no separate server-side schema type.
40
+
41
+ `apps/sync-server` reads the live `schema` directly today
42
+ (`buildModelMap(schema)`, `composeIdentitySyncGroups` via the `@ablo/schema`
43
+ wrapper).
44
+
45
+ ## Trust boundary
46
+
47
+ Never trust a client-connection schema for authz (Zero/Convex/Instant). A
48
+ client connection may carry only the schema **version** for compatibility
49
+ gating; the authoritative `Schema` arrives over an authenticated control-plane
50
+ path. The identity passed to `composeIdentitySyncGroups` is server-resolved
51
+ trusted claims.
52
+
53
+ ## Wire form (`serialize.ts`)
54
+
55
+ `serializeSchema(schema): string` / `parseSchema(json): Schema` are the
56
+ control-plane transport — the GraphQL `printSchema`/`buildSchema` model. The
57
+ JSON (`SchemaJSON`, envelope `{ v, models, identityRoles }`) carries every
58
+ model's routing/scoping metadata, relations (incl. resolved
59
+ `foreignKeyColumn`), field metadata, and identity roles. `parseSchema` rebuilds
60
+ each model's Zod permissively from `FieldMeta` (the server does no field-shape
61
+ validation) and drops `computed` closures. `schemaHash(schema)` is the stable
62
+ FNV-1a content hash used for connect-time gating. Round-trip tested in
63
+ `__tests__/serialize.test.ts`.
64
+
65
+ ## Storage + runtime resolution (`apps/sync-server/src/schema/`): built
66
+
67
+ - **`ablo_schemas` table** (`packages/database/prisma/models/sync.prisma`,
68
+ `SchemaArtifact`) — `(organizationId, version, schemaJson, schemaHash, state,
69
+ error, createdBy, createdAt, activatedAt)`, unique `(orgId, version)`. State
70
+ `pending|validated|active|overwritten|failed`, ≤1 active per tenant (Convex
71
+ `_schemas` machine; Zero's "row in the operational DB"). *Migration written,
72
+ not applied — 0 users, Neon direct-endpoint rule.*
73
+ - **`pgSchemaStore` / `memorySchemaStore`** (`schemaStore.ts`) — mirrors
74
+ `pgApiKeyStore`. `insertPending` assigns `MAX(version)+1`; `activate` is a
75
+ transaction that demotes the current active → `overwritten` then promotes the
76
+ target. State-machine invariants tested.
77
+ - **`createSchemaRegistry(store)`** (`schemaRegistry.ts`) — `load(orgId)` parses
78
+ the active artifact's `schemaJson` to a `Schema` and caches it (shared
79
+ in-flight promise across concurrent cold loads); `invalidate(orgId)` busts it
80
+ on activation (Convex `schema_registry`). This is the seam that turns the
81
+ boot-time `import { schema }` into per-tenant runtime resolution.
82
+
83
+ ## Push route (`apps/sync-server/src/routes/schema.ts`): built
84
+
85
+ `POST /api/schema`, mounted in `index.ts` (`schemaRoutes({ provider, store,
86
+ registry })`). Auth: secret `sk_` key carrying the `schema:push` scope —
87
+ `Identity.scopes` was added and `apiKeyProvider` now populates it from the key
88
+ row's `scopes` column (restricted `rk_` keys get no `scopes`, so they're
89
+ excluded). Tenant comes from `identity.organizationId`, never the body. Flow:
90
+ read `{ schema, force? }` → validate via `parseSchema` (throws → 400) →
91
+ authoritative hash via `schemaHash(parsed)` → reject removed-model changes (409)
92
+ unless `force` → no-op fast path on identical hash (200) → `insertPending` →
93
+ `activate` → `registry.invalidate(org)` → 201 `{ schemaId, version, hash }`. 6
94
+ route tests.
95
+
96
+ ## CLI (`packages/ablo-cli`): built
97
+
98
+ `ablo push` (`src/push.ts`, dispatched from `index.ts`). Imports the
99
+ user's `sync/schema.ts` at runtime via tsx's `tsImport` (the real object —
100
+ `migrate`'s regex parse can't produce a faithful AST), then `serializeSchema`
101
+ + `schemaHash` and POSTs `{ schema, force, renames }` to `POST /api/schema`
102
+ with `Authorization: Bearer $ABLO_API_KEY`. Flags: `--schema`, `--export`,
103
+ `--url` (`$ABLO_API_URL`, default `https://api.abloatai.com`), `--force`,
104
+ `--rename old:new` (repeatable). The route honors `renames` so a renamed model
105
+ isn't flagged as a removed-model incompatibility. `parsePushArgs` unit-tested.
106
+
107
+ ## Schema drift is advisory
108
+
109
+ Bootstrap includes the tenant's active schema hash. The client compares it to
110
+ its built-in hash and warns once when they differ. Hash drift never closes the
111
+ WebSocket: an additive rollout must allow old and new clients to overlap while
112
+ data is expanded, dual-read/written, backfilled, verified, and finally
113
+ contracted. Breaking wire shapes use the protocol-version codec registry
114
+ instead.
115
+
116
+ ## Not built yet
117
+ - **Switch the hot paths to per-tenant `registry.load(org)`:** boot still does
118
+ the single-tenant `import { schema }`; `buildModelMap`/bootstrap/commit
119
+ reading the registry per request is the final multi-tenant wiring.
@@ -0,0 +1,32 @@
1
+ # Repository Structure
2
+
3
+ The public repository preserves the same ownership boundaries as the main
4
+ monorepo. `@abloatai/ablo` is the product package; the packages beneath it are
5
+ implementation owners and first-party extension surfaces.
6
+
7
+ | Workspace | Responsibility |
8
+ | --- | --- |
9
+ | `packages/ablo` | Branded SDK, public entrypoints, docs, examples, release assets |
10
+ | `packages/transaction` | Headless HTTP client, canonical contracts, reads, commits, settlement, claims, durable observation |
11
+ | `packages/humans` | Reactive materializer, WebSocket transport, presence, browser persistence, React |
12
+ | `packages/agent` | Agent behavior, perception, and coordination helpers |
13
+ | `packages/cli` | Project setup, database connection, schema operations, and diagnostics |
14
+ | `packages/tsconfig` | Private shared compiler configuration |
15
+
16
+ Applications install and import `@abloatai/ablo`. The root entrypoint is the
17
+ headless HTTP API. Human-facing reactive behavior is explicit:
18
+
19
+ ```ts
20
+ import Ablo from '@abloatai/ablo';
21
+ import ReactiveAblo from '@abloatai/ablo/client';
22
+ import { AbloProvider, useAblo } from '@abloatai/ablo/react';
23
+ ```
24
+
25
+ The backend implementation remains in `apps/sync-server` in the private
26
+ monorepo. It consumes transaction contracts but is not part of the public SDK
27
+ repository.
28
+
29
+ Internal packages must not import the branded facade. Dependencies point from
30
+ the facade to the owners, from humans and agents to transaction, and never back
31
+ upward. The public mirror copies these workspaces as workspaces; it does not
32
+ flatten them or generate compatibility source.
package/docs/mcp.md CHANGED
@@ -57,7 +57,7 @@ Each tool mirrors an SDK verb, scoped to a model + id. Model names come from
57
57
 
58
58
  | Tool | Mirrors | Does |
59
59
  |---|---|---|
60
- | `get_model` | `ablo.<model>.local.retrieve(id)` | read latest state + active claims |
60
+ | `get_model` | `ablo.<model>.local.get(id)` | read latest state + active claims |
61
61
  | `list_records` | `ablo.<model>.list({…})` | cursor-paginated list with filters |
62
62
  | `create_model` | `ablo.<model>.create({ data })` | guarded create |
63
63
  | `update_model` | `ablo.<model>.update({ id, … })` | guarded update |
@@ -132,7 +132,7 @@ loading everything into context.
132
132
 
133
133
  Reusable, parameterised templates that drive an end-to-end flow:
134
134
 
135
- - `integrate-sync-engine` — wire the SDK into an existing project.
135
+ - `integrate-ablo` — wire the SDK into an existing project.
136
136
  - `add-agent` — add an agent worker that coordinates via claims and
137
137
  conflict-safe writes.
138
138
  - `define-schema` — design a Zod-first schema from a description, then run
package/docs/migration.md CHANGED
@@ -14,7 +14,7 @@ change when you upgrade.
14
14
  | Version | What changed | What to do |
15
15
  |---|---|---|
16
16
  | **0.36.0** | `ttlSeconds` deprecated on the join surfaces in favour of `ttl` | `useJoin({ scope, ttlSeconds: '5m' })` → `useJoin({ scope, ttl: '5m' })`; same for `ParticipantJoinOptions`. Both spellings work until 0.37.0 |
17
- | **0.35.0** | Synchronous reads moved under `local`, mirroring the async verbs | `get(id)` → `local.retrieve(id)`; `getAll(options)` → `local.list(options)`; `getCount(options)` → `local.count(options)` |
17
+ | **0.35.0** | Synchronous reads moved under `local`, mirroring the async verbs | `get(id)` → `local.get(id)`; `getAll(options)` → `local.list(options)`; `getCount(options)` → `local.count(options)` |
18
18
  | **0.35.0** | `causedByTaskId` write option + seven `turn_*` error codes removed | Delete the `causedByTaskId` argument from writes; a branch on `turn_validation_failed` was unreachable and can go with it |
19
19
  | **0.34.0** | Presence verb renamed `watch` → `join` | `ablo.<model>.watch(ids)` → `ablo.<model>.join(ids)`; `useWatch` → `useJoin`; the `WatchOptions` / `UseWatchOptions` / `UseWatchReturn` types → `JoinOptions` / `UseJoinOptions` / `UseJoinReturn`; error code `model_watch_not_configured` → `model_join_not_configured` |
20
20
  | **0.28.0** | Removed React placeholders that had no working runtime | `usePresence` → `usePeers` or `useJoin`; `useClaim` → `ablo.<model>.claim`; `SyncGroupProvider` / `useSyncGroup` → `useJoin({ scope })` |
@@ -56,7 +56,7 @@ unchanged: it has always carried seconds and still does.
56
56
  - const task = ablo.tasks.get(id);
57
57
  - const open = ablo.tasks.getAll({ where: { status: 'open' } });
58
58
  - const count = ablo.tasks.getCount({ where: { status: 'open' } });
59
- + const task = ablo.tasks.local.retrieve(id);
59
+ + const task = ablo.tasks.local.get(id);
60
60
  + const open = ablo.tasks.local.list({ where: { status: 'open' } });
61
61
  + const count = ablo.tasks.local.count({ where: { status: 'open' } });
62
62
  ```
@@ -304,7 +304,7 @@ modifier are named siblings. Reactive local reads stay on the synchronous
304
304
  + await ablo.tasks.retrieve({ id })
305
305
 
306
306
  - useAblo((ablo) => ablo.tasks.retrieve(id)) ?? serverTask
307
- + useAblo((ablo) => ablo.tasks.local.retrieve(id)) ?? serverTask
307
+ + useAblo((ablo) => ablo.tasks.local.get(id)) ?? serverTask
308
308
  ```
309
309
 
310
310
  `claim` now returns a disposable handle instead of taking a callback. The handle
@@ -215,12 +215,12 @@ const updated = await ablo.weatherReports.update({
215
215
  console.log({ id: updated.id, status: updated.status }); // { id: '...', status: 'ready' }
216
216
  ```
217
217
 
218
- Read a single row back with `retrieve({ id })`. It resolves to the row, or to
218
+ Read a single row back with `get({ id })`. It resolves to the row, or to
219
219
  `undefined` when no row has that id — so narrow it once, then the fields are
220
220
  fully typed:
221
221
 
222
222
  ```ts
223
- const report = await ablo.weatherReports.retrieve({ id: created.id });
223
+ const report = await ablo.weatherReports.get({ id: created.id });
224
224
  if (!report) throw new Error(`weatherReports ${created.id} not found`);
225
225
 
226
226
  console.log(report.status); // 'ready'
package/docs/react.md CHANGED
@@ -98,7 +98,7 @@ org / team / user map to what a participant can see.
98
98
  import { useAblo } from '@abloatai/ablo/react';
99
99
 
100
100
  export function ReportView({ report: serverReport }: { report: { id: string; location: string } }) {
101
- const report = useAblo((ablo) => ablo.weatherReports.local.retrieve(serverReport.id)) ?? serverReport;
101
+ const report = useAblo((ablo) => ablo.weatherReports.local.get(serverReport.id)) ?? serverReport;
102
102
  const active = useAblo((ablo) => ablo.weatherReports.claim.state({ id: serverReport.id }));
103
103
  const claimed = Boolean(active);
104
104
 
@@ -108,7 +108,7 @@ export function ReportView({ report: serverReport }: { report: { id: string; loc
108
108
 
109
109
  The hook:
110
110
 
111
- 1. Uses the same `ablo.<model>.local.retrieve(id)` / `.local.list()` methods you'd call anywhere
111
+ 1. Uses the same `ablo.<model>.local.get(id)` / `.local.list()` methods you'd call anywhere
112
112
  else in the SDK — the hook just makes them reactive.
113
113
  2. Tracks the model fields read by the selector and re-renders when confirmed
114
114
  deltas arrive.
@@ -123,7 +123,7 @@ effects, or writes:
123
123
  const abloClient = useAblo();
124
124
  ```
125
125
 
126
- Prefer selector reads like `useAblo((ablo) => ablo.<model>.local.retrieve(id))`. Older hooks
126
+ Prefer selector reads like `useAblo((ablo) => ablo.<model>.local.get(id))`. Older hooks
127
127
  also accept a string model name; prefer the selector form shown above.
128
128
 
129
129
  For collections, keep the selector on the model client too:
@@ -141,12 +141,12 @@ const reports = useAblo((ablo) =>
141
141
  ## Server Load
142
142
 
143
143
  ```tsx
144
- const report = await ablo.weatherReports.retrieve({ id });
144
+ const report = await ablo.weatherReports.get({ id });
145
145
  ```
146
146
 
147
147
  Use `retrieve` in Server Components when the row may not be in the local pool
148
148
  yet — it hydrates from the local store and the server, and returns a Promise, so
149
- `await` it. (Server reads come in two shapes: `retrieve({ id })` for one row and
149
+ `await` it. (Server reads come in two shapes: `get({ id })` for one row and
150
150
  `list({ where })` for many; both are async. The synchronous local reads are
151
151
  the `local` reads, used in render below.)
152
152
 
@@ -12,7 +12,7 @@ defineSchema(...) -> ablo.<model>.create/retrieve/update/claim(...)
12
12
  That one object drives:
13
13
 
14
14
  - typed model clients in trusted server runtimes,
15
- - React selectors through `useAblo((ablo) => ablo.<model>.local.retrieve(id))`,
15
+ - React selectors through `useAblo((ablo) => ablo.<model>.local.get(id))`,
16
16
  - agent and background-worker writes,
17
17
  - Data Source request/response shape when your database stays canonical,
18
18
  - hosted schema push, migration planning, and schema-version gating.
@@ -70,14 +70,14 @@ readable, you just don't author them.
70
70
  Use async reads when the row may not be local:
71
71
 
72
72
  ```ts
73
- const report = await ablo.weatherReports.retrieve({ id: reportId });
73
+ const report = await ablo.weatherReports.get({ id: reportId });
74
74
  const ready = await ablo.weatherReports.list({ where: { status: 'ready' } });
75
75
  ```
76
76
 
77
77
  Use synchronous local reads in render after data has synced:
78
78
 
79
79
  ```ts
80
- const report = ablo.weatherReports.local.retrieve(reportId);
80
+ const report = ablo.weatherReports.local.get(reportId);
81
81
  const pending = ablo.weatherReports.local.list({ where: { status: 'pending' } });
82
82
  ```
83
83