@sixb/core 0.1.9 → 0.1.11

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 (328) hide show
  1. package/dist/actions/index.js +9 -9
  2. package/dist/agents/index.js +17 -16
  3. package/dist/agents/index.js.map +1 -1
  4. package/dist/blob-storage/types.d.ts +4 -1
  5. package/dist/blob-storage/types.d.ts.map +1 -1
  6. package/dist/bootstrap/index.js +21 -20
  7. package/dist/bootstrap/index.js.map +1 -1
  8. package/dist/broker/in-memory.d.ts +8 -2
  9. package/dist/broker/in-memory.d.ts.map +1 -1
  10. package/dist/broker/index.d.ts +4 -2
  11. package/dist/broker/index.d.ts.map +1 -1
  12. package/dist/broker/index.js +7 -3
  13. package/dist/broker/index.js.map +1 -1
  14. package/dist/broker/retention.d.ts +4 -0
  15. package/dist/broker/retention.d.ts.map +1 -0
  16. package/dist/broker/subscriber.d.ts +10 -0
  17. package/dist/broker/subscriber.d.ts.map +1 -0
  18. package/dist/broker/types.d.ts +14 -1
  19. package/dist/broker/types.d.ts.map +1 -1
  20. package/dist/{chunk-ypbtykv6.js → chunk-01kj2pbh.js} +1 -1
  21. package/dist/{chunk-k3cqkkn2.js → chunk-1824gssz.js} +30 -65
  22. package/dist/chunk-1824gssz.js.map +12 -0
  23. package/dist/{chunk-xyr8kppc.js → chunk-1yefycb1.js} +1 -1
  24. package/dist/chunk-2c4j899j.js.map +1 -1
  25. package/dist/{chunk-ppytyr6w.js → chunk-358caqf5.js} +4 -4
  26. package/dist/chunk-358caqf5.js.map +12 -0
  27. package/dist/{chunk-m3z3x9v0.js → chunk-3ckk0xfj.js} +2 -2
  28. package/dist/{chunk-kxwa347f.js → chunk-3qms4nax.js} +2 -2
  29. package/dist/{chunk-kxwa347f.js.map → chunk-3qms4nax.js.map} +3 -3
  30. package/dist/{chunk-52hbv0ak.js → chunk-4zhmdsx6.js} +141 -55
  31. package/dist/chunk-4zhmdsx6.js.map +36 -0
  32. package/dist/{chunk-zcnq6105.js → chunk-85cd7e8c.js} +2 -1
  33. package/dist/chunk-85cd7e8c.js.map +10 -0
  34. package/dist/{chunk-3f7veca0.js → chunk-9x8dybsb.js} +3 -3
  35. package/dist/chunk-9x8dybsb.js.map +10 -0
  36. package/dist/{chunk-0w35wavj.js → chunk-a0e6x5hd.js} +1 -1
  37. package/dist/{chunk-r29fxdhn.js → chunk-aa6z4a19.js} +160 -44
  38. package/dist/chunk-aa6z4a19.js.map +12 -0
  39. package/dist/{chunk-emyyk7dx.js → chunk-cfvakeax.js} +22 -145
  40. package/dist/chunk-cfvakeax.js.map +12 -0
  41. package/dist/chunk-d62kjtbg.js.map +1 -1
  42. package/dist/{chunk-h1gfhhbh.js → chunk-d63nnr5b.js} +2 -2
  43. package/dist/{chunk-r4tfx1sf.js → chunk-fh8kgex1.js} +5 -5
  44. package/dist/{chunk-an5tt9y0.js → chunk-ftv470j8.js} +42 -4
  45. package/dist/{chunk-an5tt9y0.js.map → chunk-ftv470j8.js.map} +7 -7
  46. package/dist/{chunk-jjy0fhrn.js → chunk-g91qxjj0.js} +20 -3
  47. package/dist/chunk-g91qxjj0.js.map +12 -0
  48. package/dist/{chunk-hpr1r6av.js → chunk-gq8vhakp.js} +51 -40
  49. package/dist/{chunk-hpr1r6av.js.map → chunk-gq8vhakp.js.map} +6 -6
  50. package/dist/{chunk-x57ycxq0.js → chunk-gqh45d2n.js} +42 -3
  51. package/dist/{chunk-x57ycxq0.js.map → chunk-gqh45d2n.js.map} +3 -3
  52. package/dist/{chunk-mjbk2djy.js → chunk-gqm76kse.js} +231 -125
  53. package/dist/{chunk-mjbk2djy.js.map → chunk-gqm76kse.js.map} +9 -8
  54. package/dist/{chunk-e0d1rzef.js → chunk-jsy70480.js} +16 -3
  55. package/dist/chunk-jsy70480.js.map +15 -0
  56. package/dist/{chunk-0rdrecsb.js → chunk-kfee1h52.js} +116 -32
  57. package/dist/chunk-kfee1h52.js.map +13 -0
  58. package/dist/{chunk-3frsnm7x.js → chunk-qma80ych.js} +4 -6
  59. package/dist/chunk-qma80ych.js.map +11 -0
  60. package/dist/{chunk-vf691g1r.js → chunk-sepyxgpc.js} +3 -3
  61. package/dist/chunk-v2vcg0w6.js +151 -0
  62. package/dist/chunk-v2vcg0w6.js.map +11 -0
  63. package/dist/{chunk-3tgwrcyh.js → chunk-wf88w4kp.js} +17 -23
  64. package/dist/chunk-wf88w4kp.js.map +14 -0
  65. package/dist/{chunk-xfbydgzy.js → chunk-x9m9x2eq.js} +7 -8
  66. package/dist/{chunk-xfbydgzy.js.map → chunk-x9m9x2eq.js.map} +3 -3
  67. package/dist/{chunk-qhcpj9wc.js → chunk-z0271qkp.js} +98 -2
  68. package/dist/chunk-z0271qkp.js.map +15 -0
  69. package/dist/{chunk-1enhpacz.js → chunk-z0s4axeh.js} +6 -6
  70. package/dist/connectors/connections/authorizations.d.ts.map +1 -1
  71. package/dist/connectors/connections/command-context.d.ts +2 -0
  72. package/dist/connectors/connections/command-context.d.ts.map +1 -1
  73. package/dist/connectors/connections/contracts.d.ts +4 -1
  74. package/dist/connectors/connections/contracts.d.ts.map +1 -1
  75. package/dist/connectors/connections/execution.d.ts +1 -0
  76. package/dist/connectors/connections/execution.d.ts.map +1 -1
  77. package/dist/connectors/connections/internal.js +1 -1
  78. package/dist/connectors/connections/request.d.ts +3 -1
  79. package/dist/connectors/connections/request.d.ts.map +1 -1
  80. package/dist/connectors/connections/runs.d.ts +1 -0
  81. package/dist/connectors/connections/runs.d.ts.map +1 -1
  82. package/dist/connectors/connections/service.d.ts +2 -0
  83. package/dist/connectors/connections/service.d.ts.map +1 -1
  84. package/dist/connectors/connections/tokens.d.ts.map +1 -1
  85. package/dist/connectors/connections/validation.d.ts +5 -1
  86. package/dist/connectors/connections/validation.d.ts.map +1 -1
  87. package/dist/connectors/types.d.ts +19 -4
  88. package/dist/connectors/types.d.ts.map +1 -1
  89. package/dist/events/execution.d.ts +1 -1
  90. package/dist/events/execution.d.ts.map +1 -1
  91. package/dist/events/index.js +1 -1
  92. package/dist/events/outbox-dispatcher.d.ts +2 -2
  93. package/dist/events/outbox-dispatcher.d.ts.map +1 -1
  94. package/dist/events/service.d.ts +2 -2
  95. package/dist/events/service.d.ts.map +1 -1
  96. package/dist/execution/agent.js +17 -16
  97. package/dist/execution/agent.js.map +1 -1
  98. package/dist/execution/primitive.js +17 -16
  99. package/dist/execution/primitive.js.map +2 -2
  100. package/dist/execution/request.js +17 -16
  101. package/dist/execution/request.js.map +2 -2
  102. package/dist/index.d.ts +3 -3
  103. package/dist/index.d.ts.map +1 -1
  104. package/dist/index.js +31 -29
  105. package/dist/index.js.map +1 -1
  106. package/dist/lake-storage/changes.d.ts +5 -0
  107. package/dist/lake-storage/changes.d.ts.map +1 -0
  108. package/dist/lake-storage/in-memory.d.ts +2 -1
  109. package/dist/lake-storage/in-memory.d.ts.map +1 -1
  110. package/dist/lake-storage/index.d.ts +2 -1
  111. package/dist/lake-storage/index.d.ts.map +1 -1
  112. package/dist/lake-storage/index.js +4 -2
  113. package/dist/lake-storage/index.js.map +1 -1
  114. package/dist/lake-storage/types.d.ts +38 -0
  115. package/dist/lake-storage/types.d.ts.map +1 -1
  116. package/dist/logging/internal.js +1 -1
  117. package/dist/maintenance/ontology-maintenance.d.ts.map +1 -1
  118. package/dist/maintenance/types.d.ts +1 -1
  119. package/dist/maintenance/types.d.ts.map +1 -1
  120. package/dist/materialization/index.d.ts +1 -1
  121. package/dist/materialization/index.d.ts.map +1 -1
  122. package/dist/materialization/model.d.ts +12 -1
  123. package/dist/materialization/model.d.ts.map +1 -1
  124. package/dist/materializer/index.d.ts +1 -1
  125. package/dist/materializer/index.d.ts.map +1 -1
  126. package/dist/materializer/index.js +6 -6
  127. package/dist/materializer/materializer.d.ts +5 -1
  128. package/dist/materializer/materializer.d.ts.map +1 -1
  129. package/dist/materializer/projections/entry-validator.d.ts +2 -1
  130. package/dist/materializer/projections/entry-validator.d.ts.map +1 -1
  131. package/dist/materializer/projections/replace.d.ts.map +1 -1
  132. package/dist/materializer/projections/source-materialization.d.ts +4 -3
  133. package/dist/materializer/projections/source-materialization.d.ts.map +1 -1
  134. package/dist/materializer/shared/normalize.d.ts +2 -1
  135. package/dist/materializer/shared/normalize.d.ts.map +1 -1
  136. package/dist/models/definitions.d.ts +7 -0
  137. package/dist/models/definitions.d.ts.map +1 -1
  138. package/dist/models/execution/index.js +6 -6
  139. package/dist/models/index.js +1 -1
  140. package/dist/objects/index.js +10 -10
  141. package/dist/objects/query/index.js +6 -6
  142. package/dist/pipelines/index.js +7 -7
  143. package/dist/pipelines/run-dispatch.d.ts.map +1 -1
  144. package/dist/projections/internal.js +7 -9
  145. package/dist/projections/internal.js.map +1 -1
  146. package/dist/projections/run-dispatch.d.ts.map +1 -1
  147. package/dist/queues/in-memory.d.ts +7 -3
  148. package/dist/queues/in-memory.d.ts.map +1 -1
  149. package/dist/queues/index.js +1 -1
  150. package/dist/queues/indexed-heap.d.ts +15 -0
  151. package/dist/queues/indexed-heap.d.ts.map +1 -0
  152. package/dist/runtime/host.d.ts.map +1 -1
  153. package/dist/runtime/internal.js +1 -1
  154. package/dist/runtime/ontology-mutations.d.ts +3 -1
  155. package/dist/runtime/ontology-mutations.d.ts.map +1 -1
  156. package/dist/shares/internal.js +5 -5
  157. package/dist/storage/agents/provider.js +1 -1
  158. package/dist/storage/connector-connections/in-memory.d.ts +1 -0
  159. package/dist/storage/connector-connections/in-memory.d.ts.map +1 -1
  160. package/dist/storage/connector-connections/provider/connections.d.ts.map +1 -1
  161. package/dist/storage/connector-connections/provider/runs.d.ts +1 -0
  162. package/dist/storage/connector-connections/provider/runs.d.ts.map +1 -1
  163. package/dist/storage/connector-connections/provider/shared.d.ts +1 -0
  164. package/dist/storage/connector-connections/provider/shared.d.ts.map +1 -1
  165. package/dist/storage/connector-connections/provider.d.ts +1 -0
  166. package/dist/storage/connector-connections/provider.d.ts.map +1 -1
  167. package/dist/storage/connector-connections/provider.js +11 -17
  168. package/dist/storage/connector-connections/provider.js.map +6 -6
  169. package/dist/storage/connector-connections/types.d.ts +6 -3
  170. package/dist/storage/connector-connections/types.d.ts.map +1 -1
  171. package/dist/storage/index.d.ts +1 -1
  172. package/dist/storage/index.d.ts.map +1 -1
  173. package/dist/storage/index.js +5 -5
  174. package/dist/storage/internal.js +1 -1
  175. package/dist/storage/ontology/in-memory/materializations-state.d.ts.map +1 -1
  176. package/dist/storage/ontology/in-memory/materializations.d.ts +1 -1
  177. package/dist/storage/ontology/in-memory/materializations.d.ts.map +1 -1
  178. package/dist/storage/ontology/in-memory/shared-state.d.ts +15 -2
  179. package/dist/storage/ontology/in-memory/shared-state.d.ts.map +1 -1
  180. package/dist/storage/ontology/in-memory/source-roots.d.ts +6 -0
  181. package/dist/storage/ontology/in-memory/source-roots.d.ts.map +1 -0
  182. package/dist/storage/ontology/in-memory/sources.d.ts.map +1 -1
  183. package/dist/storage/ontology/index.d.ts +1 -1
  184. package/dist/storage/ontology/index.d.ts.map +1 -1
  185. package/dist/storage/ontology/outbox.d.ts +1 -0
  186. package/dist/storage/ontology/outbox.d.ts.map +1 -1
  187. package/dist/storage/ontology/provider.d.ts +16 -0
  188. package/dist/storage/ontology/provider.d.ts.map +1 -1
  189. package/dist/storage/ontology/provider.js +4 -2
  190. package/dist/storage/ontology/provider.js.map +1 -1
  191. package/dist/storage/ontology/sources.d.ts +13 -4
  192. package/dist/storage/ontology/sources.d.ts.map +1 -1
  193. package/dist/storage/projection-runs/lifecycle.d.ts.map +1 -1
  194. package/dist/storage/projection-runs/provider.js +2 -2
  195. package/dist/storage/projection-runs/types.d.ts +2 -0
  196. package/dist/storage/projection-runs/types.d.ts.map +1 -1
  197. package/dist/syncs/index.js +9 -8
  198. package/dist/syncs/index.js.map +1 -1
  199. package/dist/syncs/run-dispatch.d.ts.map +1 -1
  200. package/dist/testing/broker-contract.d.ts.map +1 -1
  201. package/dist/testing/connector-connection-storage-contract.d.ts.map +1 -1
  202. package/dist/testing/index.d.ts +1 -0
  203. package/dist/testing/index.d.ts.map +1 -1
  204. package/dist/testing/index.js +1499 -963
  205. package/dist/testing/index.js.map +10 -9
  206. package/dist/testing/lake-changes-contract.d.ts +6 -0
  207. package/dist/testing/lake-changes-contract.d.ts.map +1 -0
  208. package/dist/testing/lake-storage-contract.d.ts.map +1 -1
  209. package/dist/testing/materializer-storage-contract.d.ts.map +1 -1
  210. package/dist/testing/ontology-storage-contract.d.ts.map +1 -1
  211. package/dist/testing/projection-run-storage-contract.d.ts.map +1 -1
  212. package/dist/webhooks/connections.d.ts +6 -0
  213. package/dist/webhooks/connections.d.ts.map +1 -0
  214. package/dist/webhooks/index.d.ts +1 -1
  215. package/dist/webhooks/index.d.ts.map +1 -1
  216. package/dist/webhooks/internal.d.ts +2 -0
  217. package/dist/webhooks/internal.d.ts.map +1 -1
  218. package/dist/webhooks/internal.js +55 -10
  219. package/dist/webhooks/internal.js.map +4 -3
  220. package/dist/webhooks/registry.d.ts +1 -1
  221. package/dist/webhooks/registry.d.ts.map +1 -1
  222. package/dist/webhooks/types.d.ts +15 -4
  223. package/dist/webhooks/types.d.ts.map +1 -1
  224. package/dist/workflows/index.js +18 -17
  225. package/dist/workflows/index.js.map +1 -1
  226. package/dist/workflows/run-dispatch.d.ts +3 -1
  227. package/dist/workflows/run-dispatch.d.ts.map +1 -1
  228. package/package.json +1 -1
  229. package/src/agents/model-loop.ts +7 -0
  230. package/src/blob-storage/types.ts +4 -1
  231. package/src/broker/in-memory.ts +104 -39
  232. package/src/broker/index.ts +4 -1
  233. package/src/broker/retention.ts +28 -0
  234. package/src/broker/subscriber.ts +21 -0
  235. package/src/broker/types.ts +15 -1
  236. package/src/connectors/builders.ts +0 -6
  237. package/src/connectors/connections/authorizations.ts +11 -5
  238. package/src/connectors/connections/command-context.ts +21 -4
  239. package/src/connectors/connections/contracts.ts +7 -1
  240. package/src/connectors/connections/execution.ts +3 -0
  241. package/src/connectors/connections/request.ts +56 -22
  242. package/src/connectors/connections/runs.ts +39 -1
  243. package/src/connectors/connections/service.ts +6 -0
  244. package/src/connectors/connections/tokens.ts +4 -0
  245. package/src/connectors/connections/validation.ts +91 -5
  246. package/src/connectors/types.ts +19 -4
  247. package/src/events/execution.ts +2 -2
  248. package/src/events/outbox-dispatcher.ts +20 -26
  249. package/src/events/service.ts +3 -3
  250. package/src/index.ts +10 -2
  251. package/src/lake-storage/changes.ts +43 -0
  252. package/src/lake-storage/in-memory.ts +75 -0
  253. package/src/lake-storage/index.ts +4 -0
  254. package/src/lake-storage/types.ts +42 -0
  255. package/src/logging/service.ts +1 -1
  256. package/src/maintenance/ontology-maintenance.ts +6 -2
  257. package/src/maintenance/types.ts +1 -1
  258. package/src/materialization/index.ts +2 -0
  259. package/src/materialization/model.ts +14 -1
  260. package/src/materializer/README.md +1 -1
  261. package/src/materializer/index.ts +2 -0
  262. package/src/materializer/materializer.ts +10 -0
  263. package/src/materializer/projections/entry-validator.ts +19 -1
  264. package/src/materializer/projections/replace.ts +36 -1
  265. package/src/materializer/projections/source-materialization.ts +26 -6
  266. package/src/materializer/shared/normalize.ts +1 -1
  267. package/src/models/definitions.ts +19 -0
  268. package/src/models/pricing.ts +6 -2
  269. package/src/pipelines/run-dispatch.ts +21 -1
  270. package/src/projections/run-dispatch.ts +30 -68
  271. package/src/queues/in-memory.ts +105 -62
  272. package/src/queues/indexed-heap.ts +74 -0
  273. package/src/runtime/host.ts +0 -14
  274. package/src/runtime/ontology-mutations.ts +4 -0
  275. package/src/storage/connector-connections/in-memory.ts +19 -19
  276. package/src/storage/connector-connections/provider/connections.ts +1 -15
  277. package/src/storage/connector-connections/provider/runs.ts +9 -1
  278. package/src/storage/connector-connections/provider/shared.ts +2 -3
  279. package/src/storage/connector-connections/provider.ts +6 -0
  280. package/src/storage/connector-connections/types.ts +8 -3
  281. package/src/storage/index.ts +1 -0
  282. package/src/storage/ontology/in-memory/materializations-state.ts +5 -18
  283. package/src/storage/ontology/in-memory/materializations.ts +73 -92
  284. package/src/storage/ontology/in-memory/shared-state.ts +36 -4
  285. package/src/storage/ontology/in-memory/source-roots.ts +123 -0
  286. package/src/storage/ontology/in-memory/sources.ts +78 -23
  287. package/src/storage/ontology/index.ts +1 -0
  288. package/src/storage/ontology/outbox.ts +1 -0
  289. package/src/storage/ontology/provider.ts +70 -0
  290. package/src/storage/ontology/sources.ts +14 -3
  291. package/src/storage/projection-runs/lifecycle.ts +5 -2
  292. package/src/storage/projection-runs/types.ts +4 -3
  293. package/src/syncs/run-dispatch.ts +19 -1
  294. package/src/testing/broker-contract.ts +95 -0
  295. package/src/testing/connector-connection-storage-contract.ts +29 -12
  296. package/src/testing/index.ts +1 -0
  297. package/src/testing/lake-changes-contract.ts +240 -0
  298. package/src/testing/lake-storage-contract.ts +29 -0
  299. package/src/testing/materializer-storage-contract.ts +172 -1
  300. package/src/testing/ontology-storage-contract.ts +15 -3
  301. package/src/testing/projection-run-storage-contract.ts +34 -0
  302. package/src/webhooks/connections.ts +56 -0
  303. package/src/webhooks/index.ts +2 -0
  304. package/src/webhooks/internal.ts +2 -0
  305. package/src/webhooks/registry.ts +3 -4
  306. package/src/webhooks/types.ts +17 -4
  307. package/src/workflows/run-dispatch.ts +42 -29
  308. package/dist/chunk-0rdrecsb.js.map +0 -11
  309. package/dist/chunk-3f7veca0.js.map +0 -10
  310. package/dist/chunk-3frsnm7x.js.map +0 -11
  311. package/dist/chunk-3tgwrcyh.js.map +0 -14
  312. package/dist/chunk-52hbv0ak.js.map +0 -36
  313. package/dist/chunk-e0d1rzef.js.map +0 -15
  314. package/dist/chunk-emyyk7dx.js.map +0 -14
  315. package/dist/chunk-jjy0fhrn.js.map +0 -12
  316. package/dist/chunk-k3cqkkn2.js.map +0 -12
  317. package/dist/chunk-ppytyr6w.js.map +0 -12
  318. package/dist/chunk-qhcpj9wc.js.map +0 -14
  319. package/dist/chunk-r29fxdhn.js.map +0 -11
  320. package/dist/chunk-zcnq6105.js.map +0 -10
  321. /package/dist/{chunk-ypbtykv6.js.map → chunk-01kj2pbh.js.map} +0 -0
  322. /package/dist/{chunk-xyr8kppc.js.map → chunk-1yefycb1.js.map} +0 -0
  323. /package/dist/{chunk-m3z3x9v0.js.map → chunk-3ckk0xfj.js.map} +0 -0
  324. /package/dist/{chunk-0w35wavj.js.map → chunk-a0e6x5hd.js.map} +0 -0
  325. /package/dist/{chunk-h1gfhhbh.js.map → chunk-d63nnr5b.js.map} +0 -0
  326. /package/dist/{chunk-r4tfx1sf.js.map → chunk-fh8kgex1.js.map} +0 -0
  327. /package/dist/{chunk-vf691g1r.js.map → chunk-sepyxgpc.js.map} +0 -0
  328. /package/dist/{chunk-1enhpacz.js.map → chunk-z0s4axeh.js.map} +0 -0
@@ -31,6 +31,7 @@ export interface ConnectorConnectionPersistence {
31
31
  deleteAuthorizationAttempt(id: string): Promise<boolean>
32
32
 
33
33
  insertConnectionRun(record: ConnectorConnectionRunRecord): Promise<boolean>
34
+ listPendingConnectionRuns(): Promise<readonly ConnectorConnectionRunRecord[]>
34
35
  getConnectionRun(id: string): Promise<ConnectorConnectionRunRecord | null>
35
36
  updateConnectionRun(record: ConnectorConnectionRunRecord): Promise<void>
36
37
 
@@ -88,6 +89,7 @@ export async function currentConnectionRun(
88
89
  const run = await persistence.getConnectionRun(runId)
89
90
  if (!run || (run.status !== "waiting" && run.status !== "running")) return run
90
91
 
92
+ if (run.status === "waiting" && run.waitingFor === "account_selection") return run
91
93
  const now = await persistence.now()
92
94
  if (run.expiresAt.getTime() > now.getTime()) return run
93
95
 
@@ -96,9 +98,6 @@ export async function currentConnectionRun(
96
98
  if (attempt) await persistence.deleteAuthorizationAttempt(attempt.id)
97
99
  }
98
100
  if (run.status === "waiting") {
99
- if (run.kind === "connect" && run.waitingFor === "account_selection") {
100
- await markPendingAuthorizationForCleanup(persistence, run.authorizationId, now)
101
- }
102
101
  const expired = expireConnectionRun(run, now)
103
102
  await persistence.updateConnectionRun(expired)
104
103
  return expired
@@ -77,6 +77,12 @@ export class DurableConnectorConnectionStorage implements ConnectorConnectionSto
77
77
  return this.runs.finishConnectionRun(...args)
78
78
  }
79
79
 
80
+ listPendingConnectionRuns(
81
+ ...args: Parameters<ConnectorConnectionStorage["listPendingConnectionRuns"]>
82
+ ) {
83
+ return this.runs.listPendingConnectionRuns(...args)
84
+ }
85
+
80
86
  async getConnectionRun(
81
87
  ...args: Parameters<ConnectorConnectionStorage["getConnectionRun"]>
82
88
  ): Promise<Awaited<ReturnType<ConnectorConnectionStorage["getConnectionRun"]>>> {
@@ -58,6 +58,7 @@ export interface ConnectorConnectionRunAwaitingSelectionRecord extends Connector
58
58
  readonly status: "waiting"
59
59
  readonly waitingFor: "account_selection"
60
60
  readonly authorizationId: string
61
+ /** Legacy persistence field; account selection no longer expires. */
61
62
  readonly expiresAt: Date
62
63
  }
63
64
 
@@ -198,7 +199,8 @@ export interface ConnectorAuthorizationAttemptRecord extends ConnectorConnection
198
199
  /** Durable execution that initiated and authorizes completion of this OAuth attempt. */
199
200
  readonly initiatedByExecutionId: string
200
201
  readonly stateHash: string
201
- readonly codeVerifier: SealedConnectorCredential
202
+ /** Absent when the authorization attempt explicitly disabled PKCE. */
203
+ readonly codeVerifier?: SealedConnectorCredential
202
204
  readonly redirectUri: string
203
205
  /** Present only for attempts created by the headless connection-run API. */
204
206
  readonly connectionRunId?: string
@@ -219,7 +221,7 @@ export interface CreateConnectorAuthorizationAttemptInput extends ConnectorConne
219
221
  readonly connectorId: string
220
222
  readonly initiatedByExecutionId: string
221
223
  readonly stateHash: string
222
- readonly codeVerifier: SealedConnectorCredential
224
+ readonly codeVerifier?: SealedConnectorCredential
223
225
  readonly redirectUri: string
224
226
  readonly connectionRunId?: string
225
227
  readonly returnTo?: string
@@ -278,7 +280,7 @@ export interface ConnectorAuthorizationRecord {
278
280
  readonly scopes: readonly string[]
279
281
  readonly accounts: readonly ConnectorAccountCandidate[]
280
282
  readonly status: ConnectorAuthorizationStatus
281
- /** Storage-authoritative deadline for the first account selection. */
283
+ /** Legacy persistence field; no longer enforced as a selection deadline. */
282
284
  readonly selectionExpiresAt?: Date
283
285
  readonly revision: number
284
286
  readonly credentialMutation?: ConnectorCredentialMutation
@@ -477,6 +479,9 @@ export interface ConnectorConnectionStorage {
477
479
  finishConnectionRun(
478
480
  input: FinishConnectorConnectionRunInput
479
481
  ): Promise<ConnectorConnectionRunRecord | null>
482
+ listPendingConnectionRuns(
483
+ input: ListConnectorConnectionsInput
484
+ ): Promise<readonly ConnectorConnectionRunRecord[]>
480
485
  getConnectionRun(
481
486
  input: GetConnectorConnectionRunInput
482
487
  ): Promise<ConnectorConnectionRunRecord | null>
@@ -532,6 +532,7 @@ export type {
532
532
  SourceReplacementStatePage,
533
533
  StageMaterializationWorkInput,
534
534
  StageSourceAssertion,
535
+ StageSourceRoot,
535
536
  StageSourceRowsInput,
536
537
  StageSourceRowsResult,
537
538
  StoredLinkOverride,
@@ -27,6 +27,7 @@ import type {
27
27
  InMemoryStoredLinkSlotOverride,
28
28
  InMemoryStoredObjectOverride,
29
29
  } from "./shared-state"
30
+ import { projectEntityKey, sourceMaterializationKey } from "./shared-state"
30
31
 
31
32
  export function publicObjectOverride(
32
33
  value: InMemoryStoredObjectOverride | undefined
@@ -120,24 +121,10 @@ export function findActiveSourceMaterialization(
120
121
  projectId: string,
121
122
  sourceId: string
122
123
  ): InMemorySourceMaterialization | undefined {
123
- let active: InMemorySourceMaterialization | undefined
124
- for (const materialization of state.sourceMaterializations.values()) {
125
- if (
126
- materialization.projectId !== projectId ||
127
- materialization.source.projectionId !== sourceId ||
128
- materialization.status !== "active"
129
- ) {
130
- continue
131
- }
132
- if (active) {
133
- throw new MaterializationConflictError(
134
- "source-materialization",
135
- `Source '${sourceId}' has more than one active materialization.`
136
- )
137
- }
138
- active = materialization
139
- }
140
- return active
124
+ const id = state.activeSourceHeads.get(projectEntityKey(projectId, sourceId))
125
+ return id
126
+ ? state.sourceMaterializations.get(sourceMaterializationKey(projectId, sourceId, id))
127
+ : undefined
141
128
  }
142
129
 
143
130
  export function storedSource(
@@ -86,7 +86,6 @@ import {
86
86
  publicLinkSlotOverride,
87
87
  publicObjectOverride,
88
88
  storedPoint,
89
- storedSource,
90
89
  storedSourceLink,
91
90
  storedSourceObject,
92
91
  uniqueBy,
@@ -117,6 +116,7 @@ import {
117
116
  projectEntityKey,
118
117
  sourceMaterializationKey,
119
118
  } from "./shared-state"
119
+ import { activateSourceRoots, previousSourceRows } from "./source-roots"
120
120
 
121
121
  export interface SessionState {
122
122
  readonly providerToken: object
@@ -160,7 +160,7 @@ export interface ReplacementLinkWork {
160
160
  export interface ReplacementSessionState {
161
161
  readonly sourceId: string
162
162
  readonly candidateMaterializationId: string
163
- readonly previous: InMemorySourceMaterialization | undefined
163
+ readonly owned: Set<string>
164
164
  readonly candidate: InMemorySourceMaterialization
165
165
  readonly objects: Map<string, ReplacementObjectWork>
166
166
  readonly links: Map<string, ReplacementLinkWork>
@@ -432,8 +432,7 @@ export class InMemoryOntologyMaterializationStorage implements OntologyMateriali
432
432
  for (const entry of selected) {
433
433
  const key = projectionEntityKey({ kind: "link", ref: entry.ref })
434
434
  const base = await this.linkState(session, entry.ref)
435
- const ownedByReplacement =
436
- replacement.previous?.rowsByEntity.has(key) || replacement.candidate.rowsByEntity.has(key)
435
+ const ownedByReplacement = replacement.owned.has(key)
437
436
  links.push({
438
437
  ref: base.ref,
439
438
  candidateSource: ownedByReplacement
@@ -788,6 +787,7 @@ export class InMemoryOntologyMaterializationStorage implements OntologyMateriali
788
787
  }
789
788
  )
790
789
  }
790
+ activateSourceRoots(this.state, candidate, activation)
791
791
  this.state.sourceMaterializations.set(candidateKey, {
792
792
  ...candidate,
793
793
  status: "active",
@@ -872,7 +872,7 @@ export class InMemoryOntologyMaterializationStorage implements OntologyMateriali
872
872
  const replacement: ReplacementSessionState = {
873
873
  sourceId,
874
874
  candidateMaterializationId: input.candidateMaterializationId,
875
- previous,
875
+ owned: new Set(),
876
876
  candidate,
877
877
  objects: new Map(),
878
878
  links: new Map(),
@@ -886,9 +886,12 @@ export class InMemoryOntologyMaterializationStorage implements OntologyMateriali
886
886
  linkStreamCompleted: false,
887
887
  linksExpanded: false,
888
888
  }
889
- for (const materialization of [previous, candidate]) {
890
- if (!materialization) continue
891
- for (const row of materialization.rowsByEntity.values()) {
889
+ for (const rows of [
890
+ previousSourceRows(this.state, candidate),
891
+ candidate.rowsByEntity.values(),
892
+ ]) {
893
+ for (const row of rows) {
894
+ replacement.owned.add(projectionEntityKey(row.assertion))
892
895
  if (row.assertion.kind === "object") {
893
896
  const ref = row.assertion.ref
894
897
  replacement.objects.set(objectRefKey(ref), { ref, sortKey: objectRefSortKey(ref) })
@@ -915,54 +918,54 @@ export class InMemoryOntologyMaterializationStorage implements OntologyMateriali
915
918
  incident.has(objectRefKey(ref.source)) || incident.has(objectRefKey(ref.target))
916
919
 
917
920
  const adapter = getInMemoryObjectMaterializerAdapter(this.objects)
918
- adapter.visitExactLinks(projectId, (row) => {
919
- const ref = linkRef(row)
920
- if (touchesIncident(ref)) addReplacementLink(replacement, ref, true)
921
- })
922
- for (const override of this.state.linkOverrides.values()) {
923
- if (override.projectId !== projectId) continue
924
- if (touchesIncident(override.ref)) addReplacementLink(replacement, override.ref, true)
925
- }
926
- for (const override of this.state.linkSlotOverrides.values()) {
927
- if (override.projectId !== projectId) continue
928
- const ref = {
929
- source: override.ref.source,
930
- linkId: override.ref.linkId,
931
- target: override.value.target,
921
+ if (incident.size > 0) {
922
+ adapter.visitExactLinks(projectId, (row) => {
923
+ const ref = linkRef(row)
924
+ if (touchesIncident(ref)) addReplacementLink(replacement, ref, true)
925
+ })
926
+ for (const override of this.state.linkOverrides.values()) {
927
+ if (override.projectId !== projectId) continue
928
+ if (touchesIncident(override.ref)) addReplacementLink(replacement, override.ref, true)
932
929
  }
933
- if (touchesIncident(ref)) addReplacementLink(replacement, ref, true)
934
- }
935
- for (const active of this.state.sourceMaterializations.values()) {
936
- if (active.projectId !== projectId || active.status !== "active") continue
937
- for (const row of active.rowsByEntity.values()) {
938
- if (row.assertion.kind === "link" && touchesIncident(row.assertion.ref)) {
939
- addReplacementLink(replacement, row.assertion.ref, true)
930
+ for (const override of this.state.linkSlotOverrides.values()) {
931
+ if (override.projectId !== projectId) continue
932
+ const ref = {
933
+ source: override.ref.source,
934
+ linkId: override.ref.linkId,
935
+ target: override.value.target,
940
936
  }
937
+ if (touchesIncident(ref)) addReplacementLink(replacement, ref, true)
941
938
  }
942
- }
943
-
944
- adapter.visitExactLinks(projectId, (row) => {
945
- const ref = linkRef(row)
946
- if (replacement.affectedScopes.has(linkScopeSortKey(ref.source, ref.linkId))) {
947
- addReplacementLink(replacement, ref, false)
948
- }
949
- })
950
- for (const override of this.state.linkSlotOverrides.values()) {
951
- if (
952
- override.projectId === projectId &&
953
- replacement.affectedScopes.has(linkScopeSortKey(override.ref.source, override.ref.linkId))
954
- ) {
955
- addReplacementLink(
956
- replacement,
957
- {
958
- source: override.ref.source,
959
- linkId: override.ref.linkId,
960
- target: override.value.target,
961
- },
962
- false
963
- )
939
+ for (const [scopeKey, rows] of this.state.activeSourceLinkScopes) {
940
+ if (JSON.parse(scopeKey)[0] !== projectId) continue
941
+ for (const row of rows.values()) {
942
+ if (row.assertion.kind === "link" && touchesIncident(row.assertion.ref)) {
943
+ addReplacementLink(replacement, row.assertion.ref, true)
944
+ }
945
+ }
964
946
  }
965
947
  }
948
+ const scopes = new Map<string, { source: OntologyObjectRef; linkId: string }>()
949
+ for (const { ref } of replacement.links.values()) {
950
+ const key = linkScopeSortKey(ref.source, ref.linkId)
951
+ if (replacement.affectedScopes.has(key)) scopes.set(key, ref)
952
+ }
953
+ for (const scope of scopes.values()) {
954
+ adapter.visitExactScopeLinks(
955
+ projectId,
956
+ scope.source.objectTypeId,
957
+ scope.source.primaryId,
958
+ scope.linkId,
959
+ (row) => {
960
+ addReplacementLink(replacement, linkRef(row), false)
961
+ }
962
+ )
963
+ const override = this.state.linkSlotOverrides.get(
964
+ projectEntityKey(projectId, linkScopeKey(scope.source, scope.linkId))
965
+ )
966
+ if (override)
967
+ addReplacementLink(replacement, { ...scope, target: override.value.target }, false)
968
+ }
966
969
  replacement.linksExpanded = true
967
970
  replacement.orderedLinks = null
968
971
  }
@@ -1206,31 +1209,15 @@ export class InMemoryOntologyMaterializationStorage implements OntologyMateriali
1206
1209
  source: OntologyObjectRef,
1207
1210
  linkId: string
1208
1211
  ): StoredSourceLinkAssertion | null {
1209
- let found: StoredSourceLinkAssertion | null = null
1210
- for (const active of this.state.sourceMaterializations.values()) {
1211
- if (active.projectId !== projectId || active.status !== "active") continue
1212
- for (const row of active.rowsByEntity.values()) {
1213
- if (
1214
- row.assertion.kind !== "link" ||
1215
- objectRefKey(row.assertion.ref.source) !== objectRefKey(source) ||
1216
- row.assertion.ref.linkId !== linkId
1217
- ) {
1218
- continue
1219
- }
1220
- if (found) {
1221
- throw new MaterializationConflictError(
1222
- "source-materialization",
1223
- `Multiple active source links assert cardinality-one scope '${source.objectTypeId}.${linkId}'.`
1224
- )
1225
- }
1226
- found = storedSource(
1227
- active.source.projectionId,
1228
- active.materializationId,
1229
- row
1230
- ) as StoredSourceLinkAssertion
1231
- }
1232
- }
1233
- return structuredClone(found)
1212
+ const rows = this.state.activeSourceLinkScopes.get(
1213
+ projectEntityKey(projectId, linkScopeSortKey(source, linkId))
1214
+ )
1215
+ if (rows && rows.size > 1)
1216
+ throw new MaterializationConflictError(
1217
+ "source-materialization",
1218
+ `Multiple active source links assert cardinality-one scope '${source.objectTypeId}.${linkId}'.`
1219
+ )
1220
+ return structuredClone(rows?.values().next().value ?? null)
1234
1221
  }
1235
1222
 
1236
1223
  private findActiveObjectSource(
@@ -1250,19 +1237,13 @@ export class InMemoryOntologyMaterializationStorage implements OntologyMateriali
1250
1237
  }
1251
1238
 
1252
1239
  private findActiveSource(projectId: string, entityKey: string): StoredSourceAssertion | null {
1253
- let found: StoredSourceAssertion | null = null
1254
- for (const active of this.state.sourceMaterializations.values()) {
1255
- if (active.projectId !== projectId || active.status !== "active") continue
1256
- const row = active.rowsByEntity.get(entityKey)
1257
- if (!row) continue
1258
- if (found)
1259
- throw new MaterializationConflictError(
1260
- "source-materialization",
1261
- `Multiple active sources assert ${entityKey}.`
1262
- )
1263
- found = storedSource(active.source.projectionId, active.materializationId, row)
1264
- }
1265
- return structuredClone(found)
1240
+ const rows = this.state.activeSourceRows.get(projectEntityKey(projectId, entityKey))
1241
+ if (rows && rows.size > 1)
1242
+ throw new MaterializationConflictError(
1243
+ "source-materialization",
1244
+ `Multiple active sources assert ${entityKey}.`
1245
+ )
1246
+ return structuredClone(rows?.values().next().value ?? null)
1266
1247
  }
1267
1248
 
1268
1249
  private incidentLinkRefs(
@@ -1307,9 +1288,9 @@ export class InMemoryOntologyMaterializationStorage implements OntologyMateriali
1307
1288
  target: override.value.target,
1308
1289
  })
1309
1290
  }
1310
- for (const active of this.state.sourceMaterializations.values()) {
1311
- if (active.projectId !== projectId || active.status !== "active") continue
1312
- for (const row of active.rowsByEntity.values()) {
1291
+ for (const [scopeKey, rows] of this.state.activeSourceLinkScopes) {
1292
+ if (JSON.parse(scopeKey)[0] !== projectId) continue
1293
+ for (const row of rows.values()) {
1313
1294
  if (row.assertion.kind === "link") consider(row.assertion.ref)
1314
1295
  }
1315
1296
  }
@@ -2,6 +2,7 @@ import { MaterializationValidationError } from "../../../materialization/errors"
2
2
  import type {
3
3
  LinkSlotOverride,
4
4
  OntologyMaterializationOrigin,
5
+ ProjectionEntityRef,
5
6
  } from "../../../materialization/model"
6
7
  import type { OntologyCommitOriginSelector, OntologyCommitRecord } from "../commits"
7
8
  import type {
@@ -11,9 +12,24 @@ import type {
11
12
  StoredObjectOverride,
12
13
  } from "../materializations"
13
14
  import type { OntologyOutboxRecord } from "../outbox"
14
- import type { OntologySourceRecord, StageSourceAssertion } from "../sources"
15
+ import type {
16
+ OntologySourceRecord,
17
+ StageSourceAssertion,
18
+ StoredSourceAssertion,
19
+ StoredSourceLinkAssertion,
20
+ } from "../sources"
21
+
22
+ export interface InMemorySourceRoot {
23
+ readonly root: ProjectionEntityRef
24
+ readonly stagingOrdinal: number
25
+ readonly deleted: boolean
26
+ readonly entityKeys: Set<string>
27
+ active: boolean
28
+ retiredAt: string | null
29
+ }
15
30
 
16
31
  export interface InMemorySourceMaterialization extends OntologySourceRecord {
32
+ readonly roots: Map<string, InMemorySourceRoot>
17
33
  readonly rowsByEntity: Map<string, StageSourceAssertion>
18
34
  readonly rootOrdinals: Map<string, number>
19
35
  readonly ordinalRoots: Map<number, string>
@@ -37,6 +53,10 @@ export interface InMemoryOntologyState {
37
53
  readonly commitIdByIdempotency: Map<string, string>
38
54
  readonly commitIdByOrigin: Map<string, string>
39
55
  readonly sourceMaterializations: Map<string, InMemorySourceMaterialization>
56
+ readonly activeSourceHeads: Map<string, string>
57
+ readonly activeSourceRoots: Map<string, Map<string, string>>
58
+ readonly activeSourceRows: Map<string, Map<string, StoredSourceAssertion>>
59
+ readonly activeSourceLinkScopes: Map<string, Map<string, StoredSourceLinkAssertion>>
40
60
  readonly objectOverrides: Map<string, InMemoryStoredObjectOverride>
41
61
  readonly linkOverrides: Map<string, InMemoryStoredLinkOverride>
42
62
  readonly linkSlotOverrides: Map<string, InMemoryStoredLinkSlotOverride>
@@ -57,6 +77,10 @@ export function createInMemoryOntologyState(): InMemoryOntologyState {
57
77
  commitIdByIdempotency: new Map(),
58
78
  commitIdByOrigin: new Map(),
59
79
  sourceMaterializations: new Map(),
80
+ activeSourceHeads: new Map(),
81
+ activeSourceRoots: new Map(),
82
+ activeSourceRows: new Map(),
83
+ activeSourceLinkScopes: new Map(),
60
84
  objectOverrides: new Map(),
61
85
  linkOverrides: new Map(),
62
86
  linkSlotOverrides: new Map(),
@@ -83,6 +107,7 @@ export function sourceMaterializationRecord(
83
107
  rowsByEntity: _rows,
84
108
  rootOrdinals: _roots,
85
109
  ordinalRoots: _ordinals,
110
+ roots: _sourceRoots,
86
111
  ...record
87
112
  } = materialization
88
113
  return structuredClone(record)
@@ -151,9 +176,16 @@ export function insertBounded<T>(
151
176
  limit: number,
152
177
  compare: (left: T, right: T) => number
153
178
  ): void {
154
- let index = values.findIndex((candidate) => compare(value, candidate) < 0)
155
- if (index < 0) index = values.length
156
- values.splice(index, 0, value)
179
+ if (limit <= 0) return
180
+ if (values.length >= limit && compare(value, values[values.length - 1]!) >= 0) return
181
+ let low = 0
182
+ let high = values.length
183
+ while (low < high) {
184
+ const middle = (low + high) >>> 1
185
+ if (compare(value, values[middle]!) < 0) high = middle
186
+ else low = middle + 1
187
+ }
188
+ values.splice(low, 0, value)
157
189
  if (values.length > limit) values.pop()
158
190
  }
159
191
 
@@ -0,0 +1,123 @@
1
+ import { MaterializationConflictError } from "../../../materialization/errors"
2
+ import { linkScopeSortKey, projectionEntityKey } from "../../../materialization/refs"
3
+ import type { SourceActivationWrite } from "../materializations"
4
+ import type { StoredSourceAssertion, StoredSourceLinkAssertion } from "../sources"
5
+ import { storedSource } from "./materializations-state"
6
+ import {
7
+ type InMemoryOntologyState,
8
+ type InMemorySourceMaterialization,
9
+ projectEntityKey,
10
+ sourceMaterializationKey,
11
+ } from "./shared-state"
12
+
13
+ export function* previousSourceRows(
14
+ state: InMemoryOntologyState,
15
+ candidate: InMemorySourceMaterialization
16
+ ): Iterable<StoredSourceAssertion> {
17
+ const sourceKey = projectEntityKey(candidate.projectId, candidate.source.projectionId)
18
+ const active = state.activeSourceRoots.get(sourceKey)
19
+ if (!active) return
20
+ for (const rootKey of candidate.base ? candidate.roots.keys() : active.keys()) {
21
+ const materializationId = active.get(rootKey)
22
+ if (!materializationId) continue
23
+ const materialization = state.sourceMaterializations.get(
24
+ sourceMaterializationKey(
25
+ candidate.projectId,
26
+ candidate.source.projectionId,
27
+ materializationId
28
+ )
29
+ )!
30
+ for (const entityKey of materialization.roots.get(rootKey)!.entityKeys) {
31
+ yield storedSource(
32
+ candidate.source.projectionId,
33
+ materializationId,
34
+ materialization.rowsByEntity.get(entityKey)!
35
+ )
36
+ }
37
+ }
38
+ }
39
+
40
+ export function activateSourceRoots(
41
+ state: InMemoryOntologyState,
42
+ candidate: InMemorySourceMaterialization,
43
+ activation: SourceActivationWrite
44
+ ): void {
45
+ if (
46
+ candidate.base &&
47
+ (candidate.base.materializationId !== activation.expected.activeMaterializationId ||
48
+ candidate.base.lastCommitId !== activation.expected.lastCommitId)
49
+ ) {
50
+ throw new MaterializationConflictError(
51
+ "projection-fence",
52
+ "Source delta base changed before activation."
53
+ )
54
+ }
55
+ const sourceKey = projectEntityKey(candidate.projectId, candidate.source.projectionId)
56
+ const active = state.activeSourceRoots.get(sourceKey) ?? new Map<string, string>()
57
+ for (const key of candidate.base ? candidate.roots.keys() : [...active.keys()]) {
58
+ const materializationId = active.get(key)
59
+ if (!materializationId) continue
60
+ const old = state.sourceMaterializations.get(
61
+ sourceMaterializationKey(
62
+ candidate.projectId,
63
+ candidate.source.projectionId,
64
+ materializationId
65
+ )
66
+ )!
67
+ const root = old.roots.get(key)!
68
+ root.active = false
69
+ root.retiredAt = activation.updatedAt
70
+ active.delete(key)
71
+ for (const entityKey of root.entityKeys) {
72
+ const row = old.rowsByEntity.get(entityKey)!
73
+ const indexKey = projectEntityKey(candidate.projectId, entityKey)
74
+ const sources = state.activeSourceRows.get(indexKey)!
75
+ sources.delete(candidate.source.projectionId)
76
+ if (sources.size === 0) state.activeSourceRows.delete(indexKey)
77
+ if (row.assertion.kind === "link") {
78
+ const scopeKey = projectEntityKey(
79
+ candidate.projectId,
80
+ linkScopeSortKey(row.assertion.ref.source, row.assertion.ref.linkId)
81
+ )
82
+ const scope = state.activeSourceLinkScopes.get(scopeKey)!
83
+ scope.delete(JSON.stringify([candidate.source.projectionId, entityKey]))
84
+ if (scope.size === 0) state.activeSourceLinkScopes.delete(scopeKey)
85
+ }
86
+ }
87
+ }
88
+ for (const [rootKey, root] of candidate.roots) {
89
+ root.active = !root.deleted
90
+ root.retiredAt = root.deleted ? activation.updatedAt : null
91
+ if (root.deleted) continue
92
+ active.set(rootKey, candidate.materializationId)
93
+ for (const entityKey of root.entityKeys) {
94
+ // These are internal immutable assertions. Share their payload between indexes;
95
+ // read methods clone returned values and transaction snapshots preserve aliases.
96
+ const row = {
97
+ source: candidate.source,
98
+ materializationId: candidate.materializationId,
99
+ ...candidate.rowsByEntity.get(entityKey)!,
100
+ } as StoredSourceAssertion
101
+ const indexKey = projectEntityKey(candidate.projectId, projectionEntityKey(row.assertion))
102
+ const sources =
103
+ state.activeSourceRows.get(indexKey) ?? new Map<string, StoredSourceAssertion>()
104
+ sources.set(candidate.source.projectionId, row)
105
+ state.activeSourceRows.set(indexKey, sources)
106
+ if (row.assertion.kind === "link") {
107
+ const scopeKey = projectEntityKey(
108
+ candidate.projectId,
109
+ linkScopeSortKey(row.assertion.ref.source, row.assertion.ref.linkId)
110
+ )
111
+ const scope =
112
+ state.activeSourceLinkScopes.get(scopeKey) ?? new Map<string, StoredSourceLinkAssertion>()
113
+ scope.set(
114
+ JSON.stringify([candidate.source.projectionId, entityKey]),
115
+ row as StoredSourceLinkAssertion
116
+ )
117
+ state.activeSourceLinkScopes.set(scopeKey, scope)
118
+ }
119
+ }
120
+ }
121
+ state.activeSourceRoots.set(sourceKey, active)
122
+ state.activeSourceHeads.set(sourceKey, candidate.materializationId)
123
+ }