@sixb/core 0.1.9 → 0.1.10

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 (279) hide show
  1. package/dist/actions/index.js +8 -8
  2. package/dist/agents/index.js +16 -15
  3. package/dist/agents/index.js.map +1 -1
  4. package/dist/bootstrap/index.js +20 -19
  5. package/dist/bootstrap/index.js.map +1 -1
  6. package/dist/broker/in-memory.d.ts +8 -2
  7. package/dist/broker/in-memory.d.ts.map +1 -1
  8. package/dist/broker/index.d.ts +4 -2
  9. package/dist/broker/index.d.ts.map +1 -1
  10. package/dist/broker/index.js +7 -3
  11. package/dist/broker/index.js.map +1 -1
  12. package/dist/broker/retention.d.ts +4 -0
  13. package/dist/broker/retention.d.ts.map +1 -0
  14. package/dist/broker/subscriber.d.ts +10 -0
  15. package/dist/broker/subscriber.d.ts.map +1 -0
  16. package/dist/broker/types.d.ts +14 -1
  17. package/dist/broker/types.d.ts.map +1 -1
  18. package/dist/{chunk-k3cqkkn2.js → chunk-1824gssz.js} +30 -65
  19. package/dist/chunk-1824gssz.js.map +12 -0
  20. package/dist/{chunk-h1gfhhbh.js → chunk-28ja2cjs.js} +1 -1
  21. package/dist/chunk-2c4j899j.js.map +1 -1
  22. package/dist/{chunk-ppytyr6w.js → chunk-358caqf5.js} +4 -4
  23. package/dist/chunk-358caqf5.js.map +12 -0
  24. package/dist/{chunk-kxwa347f.js → chunk-3qms4nax.js} +2 -2
  25. package/dist/{chunk-kxwa347f.js.map → chunk-3qms4nax.js.map} +3 -3
  26. package/dist/{chunk-emyyk7dx.js → chunk-5c7ga8zz.js} +22 -145
  27. package/dist/chunk-5c7ga8zz.js.map +12 -0
  28. package/dist/{chunk-hpr1r6av.js → chunk-5p1v802y.js} +46 -39
  29. package/dist/{chunk-hpr1r6av.js.map → chunk-5p1v802y.js.map} +4 -4
  30. package/dist/{chunk-zcnq6105.js → chunk-85cd7e8c.js} +2 -1
  31. package/dist/chunk-85cd7e8c.js.map +10 -0
  32. package/dist/{chunk-1enhpacz.js → chunk-976rxdpx.js} +5 -5
  33. package/dist/{chunk-3f7veca0.js → chunk-9x8dybsb.js} +3 -3
  34. package/dist/chunk-9x8dybsb.js.map +10 -0
  35. package/dist/{chunk-r29fxdhn.js → chunk-aa6z4a19.js} +160 -44
  36. package/dist/chunk-aa6z4a19.js.map +12 -0
  37. package/dist/{chunk-r4tfx1sf.js → chunk-agbbygvh.js} +4 -4
  38. package/dist/{chunk-jjy0fhrn.js → chunk-b0ec55a1.js} +20 -3
  39. package/dist/chunk-b0ec55a1.js.map +12 -0
  40. package/dist/{chunk-xfbydgzy.js → chunk-bn138h9w.js} +7 -8
  41. package/dist/{chunk-xfbydgzy.js.map → chunk-bn138h9w.js.map} +3 -3
  42. package/dist/{chunk-an5tt9y0.js → chunk-ftv470j8.js} +42 -4
  43. package/dist/{chunk-an5tt9y0.js.map → chunk-ftv470j8.js.map} +7 -7
  44. package/dist/{chunk-0w35wavj.js → chunk-g7knyczr.js} +1 -1
  45. package/dist/{chunk-x57ycxq0.js → chunk-gqh45d2n.js} +42 -3
  46. package/dist/{chunk-x57ycxq0.js.map → chunk-gqh45d2n.js.map} +3 -3
  47. package/dist/{chunk-0rdrecsb.js → chunk-kfee1h52.js} +116 -32
  48. package/dist/chunk-kfee1h52.js.map +13 -0
  49. package/dist/{chunk-ypbtykv6.js → chunk-nmbxcaqx.js} +1 -1
  50. package/dist/{chunk-3tgwrcyh.js → chunk-nt99sxd6.js} +2 -2
  51. package/dist/{chunk-3tgwrcyh.js.map → chunk-nt99sxd6.js.map} +3 -3
  52. package/dist/{chunk-vf691g1r.js → chunk-p5vcsw9c.js} +2 -2
  53. package/dist/{chunk-mjbk2djy.js → chunk-p6a4npdx.js} +211 -106
  54. package/dist/{chunk-mjbk2djy.js.map → chunk-p6a4npdx.js.map} +9 -8
  55. package/dist/{chunk-3frsnm7x.js → chunk-qma80ych.js} +4 -6
  56. package/dist/chunk-qma80ych.js.map +11 -0
  57. package/dist/{chunk-qhcpj9wc.js → chunk-qyeptdyv.js} +96 -2
  58. package/dist/chunk-qyeptdyv.js.map +15 -0
  59. package/dist/{chunk-52hbv0ak.js → chunk-r7fj830t.js} +101 -48
  60. package/dist/chunk-r7fj830t.js.map +36 -0
  61. package/dist/{chunk-xyr8kppc.js → chunk-rtk71jzp.js} +1 -1
  62. package/dist/{chunk-m3z3x9v0.js → chunk-t1f4f1ve.js} +1 -1
  63. package/dist/chunk-v2vcg0w6.js +151 -0
  64. package/dist/chunk-v2vcg0w6.js.map +11 -0
  65. package/dist/connectors/connections/authorizations.d.ts.map +1 -1
  66. package/dist/connectors/connections/contracts.d.ts +3 -0
  67. package/dist/connectors/connections/contracts.d.ts.map +1 -1
  68. package/dist/connectors/connections/internal.js +1 -1
  69. package/dist/connectors/connections/request.d.ts +3 -1
  70. package/dist/connectors/connections/request.d.ts.map +1 -1
  71. package/dist/connectors/connections/runs.d.ts.map +1 -1
  72. package/dist/connectors/connections/tokens.d.ts.map +1 -1
  73. package/dist/connectors/connections/validation.d.ts +5 -1
  74. package/dist/connectors/connections/validation.d.ts.map +1 -1
  75. package/dist/connectors/types.d.ts +19 -4
  76. package/dist/connectors/types.d.ts.map +1 -1
  77. package/dist/events/execution.d.ts +1 -1
  78. package/dist/events/execution.d.ts.map +1 -1
  79. package/dist/events/index.js +1 -1
  80. package/dist/events/service.d.ts +2 -2
  81. package/dist/events/service.d.ts.map +1 -1
  82. package/dist/execution/agent.js +16 -15
  83. package/dist/execution/agent.js.map +1 -1
  84. package/dist/execution/primitive.js +16 -15
  85. package/dist/execution/primitive.js.map +2 -2
  86. package/dist/execution/request.js +16 -15
  87. package/dist/execution/request.js.map +2 -2
  88. package/dist/index.d.ts +3 -3
  89. package/dist/index.d.ts.map +1 -1
  90. package/dist/index.js +30 -28
  91. package/dist/index.js.map +1 -1
  92. package/dist/lake-storage/changes.d.ts +5 -0
  93. package/dist/lake-storage/changes.d.ts.map +1 -0
  94. package/dist/lake-storage/in-memory.d.ts +2 -1
  95. package/dist/lake-storage/in-memory.d.ts.map +1 -1
  96. package/dist/lake-storage/index.d.ts +2 -1
  97. package/dist/lake-storage/index.d.ts.map +1 -1
  98. package/dist/lake-storage/index.js +4 -2
  99. package/dist/lake-storage/index.js.map +1 -1
  100. package/dist/lake-storage/types.d.ts +36 -0
  101. package/dist/lake-storage/types.d.ts.map +1 -1
  102. package/dist/logging/internal.js +1 -1
  103. package/dist/materialization/index.d.ts +1 -1
  104. package/dist/materialization/index.d.ts.map +1 -1
  105. package/dist/materialization/model.d.ts +12 -1
  106. package/dist/materialization/model.d.ts.map +1 -1
  107. package/dist/materializer/index.d.ts +1 -1
  108. package/dist/materializer/index.d.ts.map +1 -1
  109. package/dist/materializer/index.js +5 -5
  110. package/dist/materializer/materializer.d.ts +5 -1
  111. package/dist/materializer/materializer.d.ts.map +1 -1
  112. package/dist/materializer/projections/entry-validator.d.ts +2 -1
  113. package/dist/materializer/projections/entry-validator.d.ts.map +1 -1
  114. package/dist/materializer/projections/replace.d.ts.map +1 -1
  115. package/dist/materializer/projections/source-materialization.d.ts +4 -3
  116. package/dist/materializer/projections/source-materialization.d.ts.map +1 -1
  117. package/dist/materializer/shared/normalize.d.ts +2 -1
  118. package/dist/materializer/shared/normalize.d.ts.map +1 -1
  119. package/dist/models/execution/index.js +5 -5
  120. package/dist/objects/index.js +9 -9
  121. package/dist/objects/query/index.js +5 -5
  122. package/dist/pipelines/index.js +6 -6
  123. package/dist/pipelines/run-dispatch.d.ts.map +1 -1
  124. package/dist/projections/internal.js +6 -8
  125. package/dist/projections/internal.js.map +1 -1
  126. package/dist/projections/run-dispatch.d.ts.map +1 -1
  127. package/dist/queues/in-memory.d.ts +7 -3
  128. package/dist/queues/in-memory.d.ts.map +1 -1
  129. package/dist/queues/index.js +1 -1
  130. package/dist/queues/indexed-heap.d.ts +15 -0
  131. package/dist/queues/indexed-heap.d.ts.map +1 -0
  132. package/dist/runtime/host.d.ts.map +1 -1
  133. package/dist/runtime/internal.js +1 -1
  134. package/dist/runtime/ontology-mutations.d.ts +3 -1
  135. package/dist/runtime/ontology-mutations.d.ts.map +1 -1
  136. package/dist/shares/internal.js +4 -4
  137. package/dist/storage/connector-connections/in-memory.d.ts.map +1 -1
  138. package/dist/storage/connector-connections/provider/runs.d.ts.map +1 -1
  139. package/dist/storage/connector-connections/provider.js +2 -2
  140. package/dist/storage/connector-connections/provider.js.map +3 -3
  141. package/dist/storage/connector-connections/types.d.ts +3 -2
  142. package/dist/storage/connector-connections/types.d.ts.map +1 -1
  143. package/dist/storage/index.d.ts +1 -1
  144. package/dist/storage/index.d.ts.map +1 -1
  145. package/dist/storage/index.js +4 -4
  146. package/dist/storage/internal.js +1 -1
  147. package/dist/storage/ontology/in-memory/materializations-state.d.ts.map +1 -1
  148. package/dist/storage/ontology/in-memory/materializations.d.ts +1 -1
  149. package/dist/storage/ontology/in-memory/materializations.d.ts.map +1 -1
  150. package/dist/storage/ontology/in-memory/shared-state.d.ts +15 -2
  151. package/dist/storage/ontology/in-memory/shared-state.d.ts.map +1 -1
  152. package/dist/storage/ontology/in-memory/source-roots.d.ts +6 -0
  153. package/dist/storage/ontology/in-memory/source-roots.d.ts.map +1 -0
  154. package/dist/storage/ontology/in-memory/sources.d.ts.map +1 -1
  155. package/dist/storage/ontology/index.d.ts +1 -1
  156. package/dist/storage/ontology/index.d.ts.map +1 -1
  157. package/dist/storage/ontology/provider.d.ts +16 -0
  158. package/dist/storage/ontology/provider.d.ts.map +1 -1
  159. package/dist/storage/ontology/provider.js +4 -2
  160. package/dist/storage/ontology/provider.js.map +1 -1
  161. package/dist/storage/ontology/sources.d.ts +13 -4
  162. package/dist/storage/ontology/sources.d.ts.map +1 -1
  163. package/dist/storage/projection-runs/lifecycle.d.ts.map +1 -1
  164. package/dist/storage/projection-runs/provider.js +2 -2
  165. package/dist/storage/projection-runs/types.d.ts +2 -0
  166. package/dist/storage/projection-runs/types.d.ts.map +1 -1
  167. package/dist/syncs/index.js +8 -7
  168. package/dist/syncs/index.js.map +1 -1
  169. package/dist/syncs/run-dispatch.d.ts.map +1 -1
  170. package/dist/testing/broker-contract.d.ts.map +1 -1
  171. package/dist/testing/connector-connection-storage-contract.d.ts.map +1 -1
  172. package/dist/testing/index.d.ts +1 -0
  173. package/dist/testing/index.d.ts.map +1 -1
  174. package/dist/testing/index.js +1459 -951
  175. package/dist/testing/index.js.map +9 -8
  176. package/dist/testing/lake-changes-contract.d.ts +6 -0
  177. package/dist/testing/lake-changes-contract.d.ts.map +1 -0
  178. package/dist/testing/materializer-storage-contract.d.ts.map +1 -1
  179. package/dist/testing/ontology-storage-contract.d.ts.map +1 -1
  180. package/dist/testing/projection-run-storage-contract.d.ts.map +1 -1
  181. package/dist/webhooks/connections.d.ts +6 -0
  182. package/dist/webhooks/connections.d.ts.map +1 -0
  183. package/dist/webhooks/index.d.ts +1 -1
  184. package/dist/webhooks/index.d.ts.map +1 -1
  185. package/dist/webhooks/internal.d.ts +2 -0
  186. package/dist/webhooks/internal.d.ts.map +1 -1
  187. package/dist/webhooks/internal.js +54 -9
  188. package/dist/webhooks/internal.js.map +4 -3
  189. package/dist/webhooks/registry.d.ts +1 -1
  190. package/dist/webhooks/registry.d.ts.map +1 -1
  191. package/dist/webhooks/types.d.ts +15 -4
  192. package/dist/webhooks/types.d.ts.map +1 -1
  193. package/dist/workflows/index.js +17 -16
  194. package/dist/workflows/index.js.map +1 -1
  195. package/dist/workflows/run-dispatch.d.ts +3 -1
  196. package/dist/workflows/run-dispatch.d.ts.map +1 -1
  197. package/package.json +1 -1
  198. package/src/broker/in-memory.ts +104 -39
  199. package/src/broker/index.ts +4 -1
  200. package/src/broker/retention.ts +28 -0
  201. package/src/broker/subscriber.ts +21 -0
  202. package/src/broker/types.ts +15 -1
  203. package/src/connectors/builders.ts +0 -6
  204. package/src/connectors/connections/authorizations.ts +11 -5
  205. package/src/connectors/connections/contracts.ts +3 -0
  206. package/src/connectors/connections/request.ts +56 -22
  207. package/src/connectors/connections/runs.ts +1 -0
  208. package/src/connectors/connections/tokens.ts +4 -0
  209. package/src/connectors/connections/validation.ts +91 -5
  210. package/src/connectors/types.ts +19 -4
  211. package/src/events/execution.ts +2 -2
  212. package/src/events/service.ts +3 -3
  213. package/src/index.ts +10 -2
  214. package/src/lake-storage/changes.ts +43 -0
  215. package/src/lake-storage/in-memory.ts +73 -0
  216. package/src/lake-storage/index.ts +4 -0
  217. package/src/lake-storage/types.ts +40 -0
  218. package/src/logging/service.ts +1 -1
  219. package/src/materialization/index.ts +2 -0
  220. package/src/materialization/model.ts +14 -1
  221. package/src/materializer/index.ts +2 -0
  222. package/src/materializer/materializer.ts +10 -0
  223. package/src/materializer/projections/entry-validator.ts +19 -1
  224. package/src/materializer/projections/replace.ts +36 -1
  225. package/src/materializer/projections/source-materialization.ts +26 -6
  226. package/src/materializer/shared/normalize.ts +1 -1
  227. package/src/pipelines/run-dispatch.ts +21 -1
  228. package/src/projections/run-dispatch.ts +30 -68
  229. package/src/queues/in-memory.ts +105 -62
  230. package/src/queues/indexed-heap.ts +74 -0
  231. package/src/runtime/host.ts +0 -14
  232. package/src/runtime/ontology-mutations.ts +4 -0
  233. package/src/storage/connector-connections/in-memory.ts +3 -1
  234. package/src/storage/connector-connections/provider/runs.ts +3 -1
  235. package/src/storage/connector-connections/types.ts +3 -2
  236. package/src/storage/index.ts +1 -0
  237. package/src/storage/ontology/in-memory/materializations-state.ts +5 -18
  238. package/src/storage/ontology/in-memory/materializations.ts +73 -92
  239. package/src/storage/ontology/in-memory/shared-state.ts +26 -1
  240. package/src/storage/ontology/in-memory/source-roots.ts +123 -0
  241. package/src/storage/ontology/in-memory/sources.ts +78 -23
  242. package/src/storage/ontology/index.ts +1 -0
  243. package/src/storage/ontology/provider.ts +70 -0
  244. package/src/storage/ontology/sources.ts +14 -3
  245. package/src/storage/projection-runs/lifecycle.ts +5 -2
  246. package/src/storage/projection-runs/types.ts +4 -3
  247. package/src/syncs/run-dispatch.ts +19 -1
  248. package/src/testing/broker-contract.ts +95 -0
  249. package/src/testing/connector-connection-storage-contract.ts +18 -1
  250. package/src/testing/index.ts +1 -0
  251. package/src/testing/lake-changes-contract.ts +240 -0
  252. package/src/testing/materializer-storage-contract.ts +172 -1
  253. package/src/testing/ontology-storage-contract.ts +7 -0
  254. package/src/testing/projection-run-storage-contract.ts +34 -0
  255. package/src/webhooks/connections.ts +56 -0
  256. package/src/webhooks/index.ts +2 -0
  257. package/src/webhooks/internal.ts +2 -0
  258. package/src/webhooks/registry.ts +3 -4
  259. package/src/webhooks/types.ts +17 -4
  260. package/src/workflows/run-dispatch.ts +42 -29
  261. package/dist/chunk-0rdrecsb.js.map +0 -11
  262. package/dist/chunk-3f7veca0.js.map +0 -10
  263. package/dist/chunk-3frsnm7x.js.map +0 -11
  264. package/dist/chunk-52hbv0ak.js.map +0 -36
  265. package/dist/chunk-emyyk7dx.js.map +0 -14
  266. package/dist/chunk-jjy0fhrn.js.map +0 -12
  267. package/dist/chunk-k3cqkkn2.js.map +0 -12
  268. package/dist/chunk-ppytyr6w.js.map +0 -12
  269. package/dist/chunk-qhcpj9wc.js.map +0 -14
  270. package/dist/chunk-r29fxdhn.js.map +0 -11
  271. package/dist/chunk-zcnq6105.js.map +0 -10
  272. /package/dist/{chunk-h1gfhhbh.js.map → chunk-28ja2cjs.js.map} +0 -0
  273. /package/dist/{chunk-1enhpacz.js.map → chunk-976rxdpx.js.map} +0 -0
  274. /package/dist/{chunk-r4tfx1sf.js.map → chunk-agbbygvh.js.map} +0 -0
  275. /package/dist/{chunk-0w35wavj.js.map → chunk-g7knyczr.js.map} +0 -0
  276. /package/dist/{chunk-ypbtykv6.js.map → chunk-nmbxcaqx.js.map} +0 -0
  277. /package/dist/{chunk-vf691g1r.js.map → chunk-p5vcsw9c.js.map} +0 -0
  278. /package/dist/{chunk-xyr8kppc.js.map → chunk-rtk71jzp.js.map} +0 -0
  279. /package/dist/{chunk-m3z3x9v0.js.map → chunk-t1f4f1ve.js.map} +0 -0
@@ -0,0 +1,74 @@
1
+ /** Internal mutable priority index. Updating or removing an entry never leaves stale copies. */
2
+ export class IndexedHeap<T> {
3
+ private readonly items: T[] = []
4
+ private readonly positions = new Map<T, number>()
5
+
6
+ constructor(private readonly compare: (left: T, right: T) => number) {}
7
+
8
+ peek(): T | undefined {
9
+ return this.items[0]
10
+ }
11
+
12
+ pop(): T | undefined {
13
+ const first = this.peek()
14
+ if (first !== undefined) this.delete(first)
15
+ return first
16
+ }
17
+
18
+ set(item: T): void {
19
+ const index = this.positions.get(item)
20
+ if (index === undefined) {
21
+ this.positions.set(item, this.items.length)
22
+ this.items.push(item)
23
+ this.up(this.items.length - 1)
24
+ } else {
25
+ this.down(this.up(index))
26
+ }
27
+ }
28
+
29
+ delete(item: T): void {
30
+ const index = this.positions.get(item)
31
+ if (index === undefined) return
32
+ const last = this.items.pop()!
33
+ this.positions.delete(item)
34
+ if (index === this.items.length) return
35
+ this.items[index] = last
36
+ this.positions.set(last, index)
37
+ this.down(this.up(index))
38
+ }
39
+
40
+ private up(start: number): number {
41
+ let index = start
42
+ while (index > 0) {
43
+ const parent = Math.floor((index - 1) / 2)
44
+ if (this.compare(this.items[parent]!, this.items[index]!) <= 0) break
45
+ this.swap(parent, index)
46
+ index = parent
47
+ }
48
+ return index
49
+ }
50
+
51
+ private down(start: number): void {
52
+ let index = start
53
+ while (index * 2 + 1 < this.items.length) {
54
+ const left = index * 2 + 1
55
+ const right = left + 1
56
+ const child =
57
+ right < this.items.length && this.compare(this.items[right]!, this.items[left]!) < 0
58
+ ? right
59
+ : left
60
+ if (this.compare(this.items[index]!, this.items[child]!) <= 0) break
61
+ this.swap(index, child)
62
+ index = child
63
+ }
64
+ }
65
+
66
+ private swap(left: number, right: number): void {
67
+ const a = this.items[left]!
68
+ const b = this.items[right]!
69
+ this.items[left] = b
70
+ this.items[right] = a
71
+ this.positions.set(a, right)
72
+ this.positions.set(b, left)
73
+ }
74
+ }
@@ -19,7 +19,6 @@ import type { BlobStorage } from "../blob-storage"
19
19
  import type { Broker } from "../broker"
20
20
  import { registerConnectorConnectionCallbackProcess } from "../connectors/connections/capability"
21
21
  import { createConnectorCredentialProtectorFromKey } from "../connectors/credentials"
22
- import { createConnectorCodedError } from "../connectors/errors"
23
22
  import { ConnectorService } from "../connectors/service"
24
23
  import {
25
24
  type ConnectorConnectionOptions,
@@ -185,7 +184,6 @@ export class SixbHost<
185
184
  })
186
185
  validateAuthStrategySecurityReferences(this.auth.getStrategy(), definitions.security)
187
186
  const connectors = definitions.connectors.list()
188
- assertConnectorConnectionSurfaces(connectors)
189
187
  const hasOAuthConnectors = connectors.some(isOAuthConnectorDefinition)
190
188
  const credentialProtector =
191
189
  hasOAuthConnectors && options.connectorConnections?.encryptionKey !== undefined
@@ -386,15 +384,3 @@ function assertWebhookRunStorage(
386
384
  }
387
385
  }
388
386
  }
389
-
390
- function assertConnectorConnectionSurfaces(connectors: readonly ConnectorDefinition[]): void {
391
- for (const connector of connectors) {
392
- if (!isOAuthConnectorDefinition(connector)) continue
393
- if (connector.adapter.webhooks !== undefined) {
394
- throw createConnectorCodedError(
395
- "connector.configuration_invalid",
396
- `OAuth connector '${connector.id}' cannot register webhooks until connection routing is defined.`
397
- )
398
- }
399
- }
400
- }
@@ -3,13 +3,16 @@ import type {
3
3
  OntologyEditCommit,
4
4
  ProjectionCommitResult,
5
5
  ProjectionRunFinishInput,
6
+ ProjectionSourceRef,
6
7
  ProjectionSourceReplacement,
7
8
  TelemetryAppend,
8
9
  TelemetryCommitResult,
9
10
  } from "../materialization/model"
10
11
  import type { BoundOntologyMaterializer } from "../materializer"
12
+ import type { OntologySourceRecord } from "../storage/ontology"
11
13
 
12
14
  export interface OntologyMutationRuntime {
15
+ getProjectionSource?(source: ProjectionSourceRef): Promise<OntologySourceRecord | null>
13
16
  commitEdits(input: OntologyEditCommit): Promise<EditCommitResult>
14
17
  replaceProjection(input: ProjectionSourceReplacement): Promise<ProjectionCommitResult>
15
18
  finishProjection(input: ProjectionRunFinishInput): Promise<void>
@@ -55,6 +58,7 @@ export function createOntologyMutationRuntime(input: {
55
58
  readonly notifyCommittedFacts: () => void
56
59
  }): OntologyMutationRuntime {
57
60
  const runtime: OntologyMutationRuntime = {
61
+ getProjectionSource: (source) => input.materializer.projections.getActive(source),
58
62
  commitEdits: (command) =>
59
63
  commitAndNotify(() => input.materializer.edits.commit(command), input.notifyCommittedFacts),
60
64
  replaceProjection: (command) =>
@@ -147,7 +147,9 @@ export class InMemoryConnectorConnectionStorage implements ConnectorConnectionSt
147
147
  slot: input.slot,
148
148
  initiatedByExecutionId: input.initiatedByExecutionId,
149
149
  stateHash: input.stateHash,
150
- codeVerifier: structuredClone(input.codeVerifier),
150
+ ...(input.codeVerifier === undefined
151
+ ? {}
152
+ : { codeVerifier: structuredClone(input.codeVerifier) }),
151
153
  redirectUri: input.redirectUri,
152
154
  ...(input.connectionRunId === undefined ? {} : { connectionRunId: input.connectionRunId }),
153
155
  ...(input.returnTo === undefined ? {} : { returnTo: input.returnTo }),
@@ -63,7 +63,9 @@ export class DurableConnectorConnectionRuns extends ConnectorConnectionOperation
63
63
  slot: input.slot,
64
64
  initiatedByExecutionId: input.initiatedByExecutionId,
65
65
  stateHash: input.stateHash,
66
- codeVerifier: structuredClone(input.codeVerifier),
66
+ ...(input.codeVerifier === undefined
67
+ ? {}
68
+ : { codeVerifier: structuredClone(input.codeVerifier) }),
67
69
  redirectUri: input.redirectUri,
68
70
  ...(input.connectionRunId === undefined ? {} : { connectionRunId: input.connectionRunId }),
69
71
  ...(input.returnTo === undefined ? {} : { returnTo: input.returnTo }),
@@ -198,7 +198,8 @@ export interface ConnectorAuthorizationAttemptRecord extends ConnectorConnection
198
198
  /** Durable execution that initiated and authorizes completion of this OAuth attempt. */
199
199
  readonly initiatedByExecutionId: string
200
200
  readonly stateHash: string
201
- readonly codeVerifier: SealedConnectorCredential
201
+ /** Absent when the authorization attempt explicitly disabled PKCE. */
202
+ readonly codeVerifier?: SealedConnectorCredential
202
203
  readonly redirectUri: string
203
204
  /** Present only for attempts created by the headless connection-run API. */
204
205
  readonly connectionRunId?: string
@@ -219,7 +220,7 @@ export interface CreateConnectorAuthorizationAttemptInput extends ConnectorConne
219
220
  readonly connectorId: string
220
221
  readonly initiatedByExecutionId: string
221
222
  readonly stateHash: string
222
- readonly codeVerifier: SealedConnectorCredential
223
+ readonly codeVerifier?: SealedConnectorCredential
223
224
  readonly redirectUri: string
224
225
  readonly connectionRunId?: string
225
226
  readonly returnTo?: string
@@ -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)
@@ -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
+ }