@knpkv/control-center 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (664) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +309 -0
  3. package/dist/client/.vite/manifest.json +452 -0
  4. package/dist/client/assets/ActiveWorkPage-Bvji6Tys.js +2 -0
  5. package/dist/client/assets/ActiveWorkPage-Bvji6Tys.js.map +1 -0
  6. package/dist/client/assets/ActiveWorkPage-CxNa23uW.css +1 -0
  7. package/dist/client/assets/AgentPage-Bom41la2.js +3 -0
  8. package/dist/client/assets/AgentPage-Bom41la2.js.map +1 -0
  9. package/dist/client/assets/AgentPage-f6WXQA21.css +1 -0
  10. package/dist/client/assets/AtlassianOAuthCallbackPage-Cqqgj2o3.css +1 -0
  11. package/dist/client/assets/AtlassianOAuthCallbackPage-dr-B9-DD.js +2 -0
  12. package/dist/client/assets/AtlassianOAuthCallbackPage-dr-B9-DD.js.map +1 -0
  13. package/dist/client/assets/AuthorizedSharePage-C-P-PNfm.js +2 -0
  14. package/dist/client/assets/AuthorizedSharePage-C-P-PNfm.js.map +1 -0
  15. package/dist/client/assets/AuthorizedSharePage-DzE_yvHI.css +1 -0
  16. package/dist/client/assets/BrowserCrypto-BPiuCuW-.js +2 -0
  17. package/dist/client/assets/BrowserCrypto-BPiuCuW-.js.map +1 -0
  18. package/dist/client/assets/BrowserSessionHydrator-C8F_LGhg.js +2 -0
  19. package/dist/client/assets/BrowserSessionHydrator-C8F_LGhg.js.map +1 -0
  20. package/dist/client/assets/CommandSearch-D6iFcdvj.js +2 -0
  21. package/dist/client/assets/CommandSearch-D6iFcdvj.js.map +1 -0
  22. package/dist/client/assets/CommandSearch-Df36xGJc.css +1 -0
  23. package/dist/client/assets/Dialog-DwSIPb-B-DVn37afM.js +42 -0
  24. package/dist/client/assets/Dialog-DwSIPb-B-DVn37afM.js.map +1 -0
  25. package/dist/client/assets/ItemsPage-DsQCbQ11.css +1 -0
  26. package/dist/client/assets/ItemsPage-x39U11an.js +2 -0
  27. package/dist/client/assets/ItemsPage-x39U11an.js.map +1 -0
  28. package/dist/client/assets/PairPage-D5vlz4OG.js +2 -0
  29. package/dist/client/assets/PairPage-D5vlz4OG.js.map +1 -0
  30. package/dist/client/assets/PortfolioOverview-DSUabOmm.js +2 -0
  31. package/dist/client/assets/PortfolioOverview-DSUabOmm.js.map +1 -0
  32. package/dist/client/assets/PortfolioOverview-nrb6Ebbh.css +1 -0
  33. package/dist/client/assets/ReleaseRoute-DyDm5s85.js +2 -0
  34. package/dist/client/assets/ReleaseRoute-DyDm5s85.js.map +1 -0
  35. package/dist/client/assets/ReleaseRoute-R3GdFaGc.css +1 -0
  36. package/dist/client/assets/ReleaseWorkset-6gGnZPS8.css +1 -0
  37. package/dist/client/assets/ReleaseWorkset-BhGacsgb.js +2 -0
  38. package/dist/client/assets/ReleaseWorkset-BhGacsgb.js.map +1 -0
  39. package/dist/client/assets/ServicesPage-CoMVH2Si.js +2 -0
  40. package/dist/client/assets/ServicesPage-CoMVH2Si.js.map +1 -0
  41. package/dist/client/assets/ServicesPage-D76DN13E.css +1 -0
  42. package/dist/client/assets/TimelinePage-38jhMz_L.css +1 -0
  43. package/dist/client/assets/TimelinePage-D8Fj_351.js +2 -0
  44. package/dist/client/assets/TimelinePage-D8Fj_351.js.map +1 -0
  45. package/dist/client/assets/WorkspaceEntityLink-BRifdJHn.js +2 -0
  46. package/dist/client/assets/WorkspaceEntityLink-BRifdJHn.js.map +1 -0
  47. package/dist/client/assets/WorkspaceEntityRoute-BwpujSqk.css +1 -0
  48. package/dist/client/assets/WorkspaceEntityRoute-DPci8Q8I.js +30 -0
  49. package/dist/client/assets/WorkspaceEntityRoute-DPci8Q8I.js.map +1 -0
  50. package/dist/client/assets/WorkspaceReleaseLayout-CMg2-6IQ.css +1 -0
  51. package/dist/client/assets/WorkspaceReleaseLayout-DDLdY0rU.js +2 -0
  52. package/dist/client/assets/WorkspaceReleaseLayout-DDLdY0rU.js.map +1 -0
  53. package/dist/client/assets/authenticatedMutationClient-D5yD0rch.js +2 -0
  54. package/dist/client/assets/authenticatedMutationClient-D5yD0rch.js.map +1 -0
  55. package/dist/client/assets/authorizedShareTransport-Dyj53kJf.js +2 -0
  56. package/dist/client/assets/authorizedShareTransport-Dyj53kJf.js.map +1 -0
  57. package/dist/client/assets/client-OmvShYdC.js +12 -0
  58. package/dist/client/assets/client-OmvShYdC.js.map +1 -0
  59. package/dist/client/assets/connectionTestTransport-c25QXx7A.js +2 -0
  60. package/dist/client/assets/connectionTestTransport-c25QXx7A.js.map +1 -0
  61. package/dist/client/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  62. package/dist/client/assets/geist-mono-latin-wght-normal-B_7UjwxQ.woff2 +0 -0
  63. package/dist/client/assets/index-CkslINEH.css +1 -0
  64. package/dist/client/assets/index-DLoOV6Hp.js +11 -0
  65. package/dist/client/assets/index-DLoOV6Hp.js.map +1 -0
  66. package/dist/client/assets/jsx-runtime-n5LQ9ujS.js +2 -0
  67. package/dist/client/assets/jsx-runtime-n5LQ9ujS.js.map +1 -0
  68. package/dist/client/assets/patterns-DEbg7R-A-Cw0A2uKS.js +2 -0
  69. package/dist/client/assets/patterns-DEbg7R-A-Cw0A2uKS.js.map +1 -0
  70. package/dist/client/assets/presentPortfolio-CkRqd_zz.js +2 -0
  71. package/dist/client/assets/presentPortfolio-CkRqd_zz.js.map +1 -0
  72. package/dist/client/assets/presentWorkspaceItems-BU__8LcC.js +2 -0
  73. package/dist/client/assets/presentWorkspaceItems-BU__8LcC.js.map +1 -0
  74. package/dist/client/assets/releasePaths-s-fSbIM-.js +2 -0
  75. package/dist/client/assets/releasePaths-s-fSbIM-.js.map +1 -0
  76. package/dist/client/assets/releaseRoutes-DSWkTh-E.js +2 -0
  77. package/dist/client/assets/releaseRoutes-DSWkTh-E.js.map +1 -0
  78. package/dist/client/assets/serviceOnboarding-B9pvdyWf.js +2 -0
  79. package/dist/client/assets/serviceOnboarding-B9pvdyWf.js.map +1 -0
  80. package/dist/client/assets/useCompactReleasePreview-Ch3XxgJU.js +2 -0
  81. package/dist/client/assets/useCompactReleasePreview-Ch3XxgJU.js.map +1 -0
  82. package/dist/client/assets/useWorkspaceItems-D0FuHGto.js +2 -0
  83. package/dist/client/assets/useWorkspaceItems-D0FuHGto.js.map +1 -0
  84. package/dist/client/assets/workspaceEntityPaths-xAl2jRFm.js +2 -0
  85. package/dist/client/assets/workspaceEntityPaths-xAl2jRFm.js.map +1 -0
  86. package/dist/client/assets/workspaceEntityRoutes-CRcfSq7c.js +2 -0
  87. package/dist/client/assets/workspaceEntityRoutes-CRcfSq7c.js.map +1 -0
  88. package/dist/client/build-graph.json +1465 -0
  89. package/dist/client/index.html +17 -0
  90. package/dist/server/api/agent.d.ts +652 -0
  91. package/dist/server/api/agent.d.ts.map +1 -0
  92. package/dist/server/api/client.d.ts +17 -0
  93. package/dist/server/api/client.d.ts.map +1 -0
  94. package/dist/server/api/controlCenterApi.d.ts +16 -0
  95. package/dist/server/api/controlCenterApi.d.ts.map +1 -0
  96. package/dist/server/api/deliveryGraph.d.ts +8714 -0
  97. package/dist/server/api/deliveryGraph.d.ts.map +1 -0
  98. package/dist/server/api/errors.d.ts +87 -0
  99. package/dist/server/api/errors.d.ts.map +1 -0
  100. package/dist/server/api/index.d.ts +14 -0
  101. package/dist/server/api/index.d.ts.map +1 -0
  102. package/dist/server/api/index.js +12 -0
  103. package/dist/server/api/index.js.map +1 -0
  104. package/dist/server/api/liveEvents.d.ts +1120 -0
  105. package/dist/server/api/liveEvents.d.ts.map +1 -0
  106. package/dist/server/api/media.d.ts +30 -0
  107. package/dist/server/api/media.d.ts.map +1 -0
  108. package/dist/server/api/plugins.d.ts +1853 -0
  109. package/dist/server/api/plugins.d.ts.map +1 -0
  110. package/dist/server/api/portfolio.d.ts +742 -0
  111. package/dist/server/api/portfolio.d.ts.map +1 -0
  112. package/dist/server/api/session.d.ts +204 -0
  113. package/dist/server/api/session.d.ts.map +1 -0
  114. package/dist/server/api/shares.d.ts +422 -0
  115. package/dist/server/api/shares.d.ts.map +1 -0
  116. package/dist/server/api/timeline.d.ts +86 -0
  117. package/dist/server/api/timeline.d.ts.map +1 -0
  118. package/dist/server/api/wire.d.ts +4 -0
  119. package/dist/server/api/wire.d.ts.map +1 -0
  120. package/dist/server/assets/BindConfig-BjK10BEb.js +15440 -0
  121. package/dist/server/assets/BindConfig-BjK10BEb.js.map +1 -0
  122. package/dist/server/assets/controlCenterApi-tZPvRPRH.js +1430 -0
  123. package/dist/server/assets/controlCenterApi-tZPvRPRH.js.map +1 -0
  124. package/dist/server/assets/domainEvent-x7yeq-gU.js +2130 -0
  125. package/dist/server/assets/domainEvent-x7yeq-gU.js.map +1 -0
  126. package/dist/server/assets/firstPartyServices-Y41P8uke.js +49 -0
  127. package/dist/server/assets/firstPartyServices-Y41P8uke.js.map +1 -0
  128. package/dist/server/assets/manualPluginSynchronization-C0aHB4UM.js +1805 -0
  129. package/dist/server/assets/manualPluginSynchronization-C0aHB4UM.js.map +1 -0
  130. package/dist/server/assets/portfolioInvalidation-Ds9Xm4_P.js +15463 -0
  131. package/dist/server/assets/portfolioInvalidation-Ds9Xm4_P.js.map +1 -0
  132. package/dist/server/assets/readiness-CzU3vjYQ.js +1012 -0
  133. package/dist/server/assets/readiness-CzU3vjYQ.js.map +1 -0
  134. package/dist/server/build-graph.json +3948 -0
  135. package/dist/server/domain/actors.d.ts +147 -0
  136. package/dist/server/domain/actors.d.ts.map +1 -0
  137. package/dist/server/domain/authorizedShare.d.ts +24 -0
  138. package/dist/server/domain/authorizedShare.d.ts.map +1 -0
  139. package/dist/server/domain/deliveryGraph.d.ts +848 -0
  140. package/dist/server/domain/deliveryGraph.d.ts.map +1 -0
  141. package/dist/server/domain/domainEvent.d.ts +50 -0
  142. package/dist/server/domain/domainEvent.d.ts.map +1 -0
  143. package/dist/server/domain/firstPartyServices.d.ts +60 -0
  144. package/dist/server/domain/firstPartyServices.d.ts.map +1 -0
  145. package/dist/server/domain/freshness.d.ts +367 -0
  146. package/dist/server/domain/freshness.d.ts.map +1 -0
  147. package/dist/server/domain/governedAction/bindings.d.ts +264 -0
  148. package/dist/server/domain/governedAction/bindings.d.ts.map +1 -0
  149. package/dist/server/domain/governedAction/index.d.ts +6 -0
  150. package/dist/server/domain/governedAction/index.d.ts.map +1 -0
  151. package/dist/server/domain/governedAction/lifecycle.d.ts +71 -0
  152. package/dist/server/domain/governedAction/lifecycle.d.ts.map +1 -0
  153. package/dist/server/domain/governedAction/model.d.ts +357 -0
  154. package/dist/server/domain/governedAction/model.d.ts.map +1 -0
  155. package/dist/server/domain/governedAction/stateMachine.d.ts +450 -0
  156. package/dist/server/domain/governedAction/stateMachine.d.ts.map +1 -0
  157. package/dist/server/domain/identifiers.d.ts +110 -0
  158. package/dist/server/domain/identifiers.d.ts.map +1 -0
  159. package/dist/server/domain/index.d.ts +26 -0
  160. package/dist/server/domain/index.d.ts.map +1 -0
  161. package/dist/server/domain/index.js +52 -0
  162. package/dist/server/domain/index.js.map +1 -0
  163. package/dist/server/domain/normalizedIssue.d.ts +223 -0
  164. package/dist/server/domain/normalizedIssue.d.ts.map +1 -0
  165. package/dist/server/domain/plugins/actions.d.ts +246 -0
  166. package/dist/server/domain/plugins/actions.d.ts.map +1 -0
  167. package/dist/server/domain/plugins/bounds.d.ts +12 -0
  168. package/dist/server/domain/plugins/bounds.d.ts.map +1 -0
  169. package/dist/server/domain/plugins/descriptor.d.ts +205 -0
  170. package/dist/server/domain/plugins/descriptor.d.ts.map +1 -0
  171. package/dist/server/domain/plugins/discovery.d.ts +39 -0
  172. package/dist/server/domain/plugins/discovery.d.ts.map +1 -0
  173. package/dist/server/domain/plugins/events.d.ts +232 -0
  174. package/dist/server/domain/plugins/events.d.ts.map +1 -0
  175. package/dist/server/domain/plugins/index.d.ts +11 -0
  176. package/dist/server/domain/plugins/index.d.ts.map +1 -0
  177. package/dist/server/domain/readiness/evaluate.d.ts +4 -0
  178. package/dist/server/domain/readiness/evaluate.d.ts.map +1 -0
  179. package/dist/server/domain/readiness/index.d.ts +7 -0
  180. package/dist/server/domain/readiness/index.d.ts.map +1 -0
  181. package/dist/server/domain/readiness/material.d.ts +114 -0
  182. package/dist/server/domain/readiness/material.d.ts.map +1 -0
  183. package/dist/server/domain/readiness/model.d.ts +1736 -0
  184. package/dist/server/domain/readiness/model.d.ts.map +1 -0
  185. package/dist/server/domain/readiness/policy.d.ts +73 -0
  186. package/dist/server/domain/readiness/policy.d.ts.map +1 -0
  187. package/dist/server/domain/readiness/rollup.d.ts +6 -0
  188. package/dist/server/domain/readiness/rollup.d.ts.map +1 -0
  189. package/dist/server/domain/relationshipRepair.d.ts +97 -0
  190. package/dist/server/domain/relationshipRepair.d.ts.map +1 -0
  191. package/dist/server/domain/release.d.ts +191 -0
  192. package/dist/server/domain/release.d.ts.map +1 -0
  193. package/dist/server/domain/releaseRelay.d.ts +44 -0
  194. package/dist/server/domain/releaseRelay.d.ts.map +1 -0
  195. package/dist/server/domain/sourceRevision.d.ts +39 -0
  196. package/dist/server/domain/sourceRevision.d.ts.map +1 -0
  197. package/dist/server/domain/timeline.d.ts +105 -0
  198. package/dist/server/domain/timeline.d.ts.map +1 -0
  199. package/dist/server/domain/utcTimestamp.d.ts +9 -0
  200. package/dist/server/domain/utcTimestamp.d.ts.map +1 -0
  201. package/dist/server/index.d.ts +8 -0
  202. package/dist/server/index.d.ts.map +1 -0
  203. package/dist/server/index.js +7 -0
  204. package/dist/server/server/DataRootProtocol.d.ts +80 -0
  205. package/dist/server/server/DataRootProtocol.d.ts.map +1 -0
  206. package/dist/server/server/agent/AgentJobWorker.d.ts +48 -0
  207. package/dist/server/server/agent/AgentJobWorker.d.ts.map +1 -0
  208. package/dist/server/server/agent/AgentRuntimeRegistry.d.ts +17 -0
  209. package/dist/server/server/agent/AgentRuntimeRegistry.d.ts.map +1 -0
  210. package/dist/server/server/agent/index.d.ts +4 -0
  211. package/dist/server/server/agent/index.d.ts.map +1 -0
  212. package/dist/server/server/api/ApiConfiguration.d.ts +24 -0
  213. package/dist/server/server/api/ApiConfiguration.d.ts.map +1 -0
  214. package/dist/server/server/api/ApiMiddleware.d.ts +14 -0
  215. package/dist/server/server/api/ApiMiddleware.d.ts.map +1 -0
  216. package/dist/server/server/api/ApplicationServices.d.ts +320 -0
  217. package/dist/server/server/api/ApplicationServices.d.ts.map +1 -0
  218. package/dist/server/server/api/ControlCenterApiServer.d.ts +11 -0
  219. package/dist/server/server/api/ControlCenterApiServer.d.ts.map +1 -0
  220. package/dist/server/server/api/ErrorMapping.d.ts +29 -0
  221. package/dist/server/server/api/ErrorMapping.d.ts.map +1 -0
  222. package/dist/server/server/api/Handlers.d.ts +24 -0
  223. package/dist/server/server/api/Handlers.d.ts.map +1 -0
  224. package/dist/server/server/api/LiveStreamAdmission.d.ts +34 -0
  225. package/dist/server/server/api/LiveStreamAdmission.d.ts.map +1 -0
  226. package/dist/server/server/api/RequestBoundary.d.ts +17 -0
  227. package/dist/server/server/api/RequestBoundary.d.ts.map +1 -0
  228. package/dist/server/server/api/RequestContext.d.ts +38 -0
  229. package/dist/server/server/api/RequestContext.d.ts.map +1 -0
  230. package/dist/server/server/api/RequestLimits.d.ts +79 -0
  231. package/dist/server/server/api/RequestLimits.d.ts.map +1 -0
  232. package/dist/server/server/api/index.d.ts +9 -0
  233. package/dist/server/server/api/index.d.ts.map +1 -0
  234. package/dist/server/server/application/authorizedShares.d.ts +29 -0
  235. package/dist/server/server/application/authorizedShares.d.ts.map +1 -0
  236. package/dist/server/server/application/awsResourceDiscovery.d.ts +18 -0
  237. package/dist/server/server/application/awsResourceDiscovery.d.ts.map +1 -0
  238. package/dist/server/server/application/connectionOwnership.d.ts +50 -0
  239. package/dist/server/server/application/connectionOwnership.d.ts.map +1 -0
  240. package/dist/server/server/application/deliveryGraphInspection.d.ts +59 -0
  241. package/dist/server/server/application/deliveryGraphInspection.d.ts.map +1 -0
  242. package/dist/server/server/application/errors.d.ts +10 -0
  243. package/dist/server/server/application/errors.d.ts.map +1 -0
  244. package/dist/server/server/application/fakeReleaseNormalization.d.ts +152 -0
  245. package/dist/server/server/application/fakeReleaseNormalization.d.ts.map +1 -0
  246. package/dist/server/server/application/index.d.ts +17 -0
  247. package/dist/server/server/application/index.d.ts.map +1 -0
  248. package/dist/server/server/application/liveEvents.d.ts +22 -0
  249. package/dist/server/server/application/liveEvents.d.ts.map +1 -0
  250. package/dist/server/server/application/manualPluginSynchronization.d.ts +41 -0
  251. package/dist/server/server/application/manualPluginSynchronization.d.ts.map +1 -0
  252. package/dist/server/server/application/mediaReads.d.ts +14 -0
  253. package/dist/server/server/application/mediaReads.d.ts.map +1 -0
  254. package/dist/server/server/application/normalizedPluginPageMaterialization.d.ts +109 -0
  255. package/dist/server/server/application/normalizedPluginPageMaterialization.d.ts.map +1 -0
  256. package/dist/server/server/application/pluginAdministration.d.ts +1318 -0
  257. package/dist/server/server/application/pluginAdministration.d.ts.map +1 -0
  258. package/dist/server/server/application/pluginSynchronizationAuthority.d.ts +22 -0
  259. package/dist/server/server/application/pluginSynchronizationAuthority.d.ts.map +1 -0
  260. package/dist/server/server/application/portfolioInvalidation.d.ts +35 -0
  261. package/dist/server/server/application/portfolioInvalidation.d.ts.map +1 -0
  262. package/dist/server/server/application/portfolioSnapshots.d.ts +12 -0
  263. package/dist/server/server/application/portfolioSnapshots.d.ts.map +1 -0
  264. package/dist/server/server/application/readinessDigests.d.ts +3 -0
  265. package/dist/server/server/application/readinessDigests.d.ts.map +1 -0
  266. package/dist/server/server/application/relationshipInference.d.ts +57 -0
  267. package/dist/server/server/application/relationshipInference.d.ts.map +1 -0
  268. package/dist/server/server/application/relationshipInferenceMaterialization.d.ts +26 -0
  269. package/dist/server/server/application/relationshipInferenceMaterialization.d.ts.map +1 -0
  270. package/dist/server/server/application/relationshipRepairProposals.d.ts +41 -0
  271. package/dist/server/server/application/relationshipRepairProposals.d.ts.map +1 -0
  272. package/dist/server/server/application/releaseAgent.d.ts +30 -0
  273. package/dist/server/server/application/releaseAgent.d.ts.map +1 -0
  274. package/dist/server/server/application/releaseAgentJobs.d.ts +26 -0
  275. package/dist/server/server/application/releaseAgentJobs.d.ts.map +1 -0
  276. package/dist/server/server/application/releaseSynchronization.d.ts +55 -0
  277. package/dist/server/server/application/releaseSynchronization.d.ts.map +1 -0
  278. package/dist/server/server/application/timelineExportAudits.d.ts +22 -0
  279. package/dist/server/server/application/timelineExportAudits.d.ts.map +1 -0
  280. package/dist/server/server/application/timelineExports.d.ts +46 -0
  281. package/dist/server/server/application/timelineExports.d.ts.map +1 -0
  282. package/dist/server/server/application/timelineReads.d.ts +29 -0
  283. package/dist/server/server/application/timelineReads.d.ts.map +1 -0
  284. package/dist/server/server/auth/Auth.d.ts +169 -0
  285. package/dist/server/server/auth/Auth.d.ts.map +1 -0
  286. package/dist/server/server/auth/AuthRepository.d.ts +160 -0
  287. package/dist/server/server/auth/AuthRepository.d.ts.map +1 -0
  288. package/dist/server/server/auth/TerminalRecovery.d.ts +35 -0
  289. package/dist/server/server/auth/TerminalRecovery.d.ts.map +1 -0
  290. package/dist/server/server/auth/errors.d.ts +31 -0
  291. package/dist/server/server/auth/errors.d.ts.map +1 -0
  292. package/dist/server/server/auth/index.d.ts +5 -0
  293. package/dist/server/server/auth/index.d.ts.map +1 -0
  294. package/dist/server/server/auth/models.d.ts +63 -0
  295. package/dist/server/server/auth/models.d.ts.map +1 -0
  296. package/dist/server/server/cli.d.ts +3 -0
  297. package/dist/server/server/cli.d.ts.map +1 -0
  298. package/dist/server/server/cli.js +669 -0
  299. package/dist/server/server/cli.js.map +1 -0
  300. package/dist/server/server/cliArguments.d.ts +21 -0
  301. package/dist/server/server/cliArguments.d.ts.map +1 -0
  302. package/dist/server/server/cliConfiguration.d.ts +20 -0
  303. package/dist/server/server/cliConfiguration.d.ts.map +1 -0
  304. package/dist/server/server/governance/governedActionAuthority.d.ts +54 -0
  305. package/dist/server/server/governance/governedActionAuthority.d.ts.map +1 -0
  306. package/dist/server/server/governance/governedActionDigests.d.ts +1348 -0
  307. package/dist/server/server/governance/governedActionDigests.d.ts.map +1 -0
  308. package/dist/server/server/governance/internal/GovernedActionExecutionEngine.d.ts +55 -0
  309. package/dist/server/server/governance/internal/GovernedActionExecutionEngine.d.ts.map +1 -0
  310. package/dist/server/server/governance/internal/GovernedActionExecutionStore.d.ts +116 -0
  311. package/dist/server/server/governance/internal/GovernedActionExecutionStore.d.ts.map +1 -0
  312. package/dist/server/server/governance/internal/GovernedActionPolicyEvaluator.d.ts +120 -0
  313. package/dist/server/server/governance/internal/GovernedActionPolicyEvaluator.d.ts.map +1 -0
  314. package/dist/server/server/governance/internal/execution-store/begin.d.ts +17 -0
  315. package/dist/server/server/governance/internal/execution-store/begin.d.ts.map +1 -0
  316. package/dist/server/server/governance/internal/execution-store/current-evidence.d.ts +33 -0
  317. package/dist/server/server/governance/internal/execution-store/current-evidence.d.ts.map +1 -0
  318. package/dist/server/server/governance/internal/execution-store/current-session.d.ts +29 -0
  319. package/dist/server/server/governance/internal/execution-store/current-session.d.ts.map +1 -0
  320. package/dist/server/server/governance/internal/execution-store/current-target.d.ts +28 -0
  321. package/dist/server/server/governance/internal/execution-store/current-target.d.ts.map +1 -0
  322. package/dist/server/server/governance/internal/execution-store/dispatch-inbox.d.ts +20 -0
  323. package/dist/server/server/governance/internal/execution-store/dispatch-inbox.d.ts.map +1 -0
  324. package/dist/server/server/governance/internal/execution-store/dispatch-outcome.d.ts +78 -0
  325. package/dist/server/server/governance/internal/execution-store/dispatch-outcome.d.ts.map +1 -0
  326. package/dist/server/server/governance/internal/execution-store/inspect.d.ts +17 -0
  327. package/dist/server/server/governance/internal/execution-store/inspect.d.ts.map +1 -0
  328. package/dist/server/server/governance/internal/execution-store/live.d.ts +6 -0
  329. package/dist/server/server/governance/internal/execution-store/live.d.ts.map +1 -0
  330. package/dist/server/server/governance/internal/execution-store/preparation.d.ts +42 -0
  331. package/dist/server/server/governance/internal/execution-store/preparation.d.ts.map +1 -0
  332. package/dist/server/server/governance/internal/execution-store/provider-outcome-fold.d.ts +33 -0
  333. package/dist/server/server/governance/internal/execution-store/provider-outcome-fold.d.ts.map +1 -0
  334. package/dist/server/server/governance/internal/execution-store/reconciliation-inbox.d.ts +20 -0
  335. package/dist/server/server/governance/internal/execution-store/reconciliation-inbox.d.ts.map +1 -0
  336. package/dist/server/server/governance/internal/execution-store/reconciliation-locator.d.ts +5 -0
  337. package/dist/server/server/governance/internal/execution-store/reconciliation-locator.d.ts.map +1 -0
  338. package/dist/server/server/governance/internal/execution-store/reconciliation-outcome.d.ts +123 -0
  339. package/dist/server/server/governance/internal/execution-store/reconciliation-outcome.d.ts.map +1 -0
  340. package/dist/server/server/governance/internal/execution-store/record-blocked.d.ts +13 -0
  341. package/dist/server/server/governance/internal/execution-store/record-blocked.d.ts.map +1 -0
  342. package/dist/server/server/governance/internal/execution-store/record-dispatch.d.ts +12 -0
  343. package/dist/server/server/governance/internal/execution-store/record-dispatch.d.ts.map +1 -0
  344. package/dist/server/server/governance/internal/execution-store/record-reconciliation.d.ts +12 -0
  345. package/dist/server/server/governance/internal/execution-store/record-reconciliation.d.ts.map +1 -0
  346. package/dist/server/server/governance/internal/execution-store/record-recovery-unavailable.d.ts +11 -0
  347. package/dist/server/server/governance/internal/execution-store/record-recovery-unavailable.d.ts.map +1 -0
  348. package/dist/server/server/governance/internal/execution-store/record-unknown.d.ts +11 -0
  349. package/dist/server/server/governance/internal/execution-store/record-unknown.d.ts.map +1 -0
  350. package/dist/server/server/governance/internal/execution-store/recovery-candidates.d.ts +12 -0
  351. package/dist/server/server/governance/internal/execution-store/recovery-candidates.d.ts.map +1 -0
  352. package/dist/server/server/governance/internal/execution-store/recovery-claim-expiry.d.ts +9 -0
  353. package/dist/server/server/governance/internal/execution-store/recovery-claim-expiry.d.ts.map +1 -0
  354. package/dist/server/server/governance/internal/execution-store/recovery-claim.d.ts +465 -0
  355. package/dist/server/server/governance/internal/execution-store/recovery-claim.d.ts.map +1 -0
  356. package/dist/server/server/governance/internal/execution-store/tokens.d.ts +52 -0
  357. package/dist/server/server/governance/internal/execution-store/tokens.d.ts.map +1 -0
  358. package/dist/server/server/http/StaticApplication.d.ts +8 -0
  359. package/dist/server/server/http/StaticApplication.d.ts.map +1 -0
  360. package/dist/server/server/http/index.d.ts +4 -0
  361. package/dist/server/server/http/index.d.ts.map +1 -0
  362. package/dist/server/server/http/security/HttpLimits.d.ts +22 -0
  363. package/dist/server/server/http/security/HttpLimits.d.ts.map +1 -0
  364. package/dist/server/server/http/security/RequestPolicy.d.ts +26 -0
  365. package/dist/server/server/http/security/RequestPolicy.d.ts.map +1 -0
  366. package/dist/server/server/http/security/RichDocument.d.ts +154 -0
  367. package/dist/server/server/http/security/RichDocument.d.ts.map +1 -0
  368. package/dist/server/server/http/security/SecurityHeaders.d.ts +7 -0
  369. package/dist/server/server/http/security/SecurityHeaders.d.ts.map +1 -0
  370. package/dist/server/server/http/security/StaticAssetStore.d.ts +43 -0
  371. package/dist/server/server/http/security/StaticAssetStore.d.ts.map +1 -0
  372. package/dist/server/server/http/security/UrlPolicy.d.ts +30 -0
  373. package/dist/server/server/http/security/UrlPolicy.d.ts.map +1 -0
  374. package/dist/server/server/http/security/index.d.ts +8 -0
  375. package/dist/server/server/http/security/index.d.ts.map +1 -0
  376. package/dist/server/server/index.d.ts +18 -0
  377. package/dist/server/server/index.d.ts.map +1 -0
  378. package/dist/server/server/index.js +583 -0
  379. package/dist/server/server/index.js.map +1 -0
  380. package/dist/server/server/observability.d.ts +13 -0
  381. package/dist/server/server/observability.d.ts.map +1 -0
  382. package/dist/server/server/persistence/ContentStore.d.ts +86 -0
  383. package/dist/server/server/persistence/ContentStore.d.ts.map +1 -0
  384. package/dist/server/server/persistence/Database.d.ts +26 -0
  385. package/dist/server/server/persistence/Database.d.ts.map +1 -0
  386. package/dist/server/server/persistence/Persistence.d.ts +7042 -0
  387. package/dist/server/server/persistence/Persistence.d.ts.map +1 -0
  388. package/dist/server/server/persistence/PersistenceConfig.d.ts +27 -0
  389. package/dist/server/server/persistence/PersistenceConfig.d.ts.map +1 -0
  390. package/dist/server/server/persistence/backup/BackupArchive.d.ts +32 -0
  391. package/dist/server/server/persistence/backup/BackupArchive.d.ts.map +1 -0
  392. package/dist/server/server/persistence/backup/BackupArchiveCore.d.ts +23 -0
  393. package/dist/server/server/persistence/backup/BackupArchiveCore.d.ts.map +1 -0
  394. package/dist/server/server/persistence/backup/BackupManifest.d.ts +136 -0
  395. package/dist/server/server/persistence/backup/BackupManifest.d.ts.map +1 -0
  396. package/dist/server/server/persistence/backup/DatabaseSnapshot.d.ts +53 -0
  397. package/dist/server/server/persistence/backup/DatabaseSnapshot.d.ts.map +1 -0
  398. package/dist/server/server/persistence/backup/errors.d.ts +53 -0
  399. package/dist/server/server/persistence/backup/errors.d.ts.map +1 -0
  400. package/dist/server/server/persistence/backup/index.d.ts +4 -0
  401. package/dist/server/server/persistence/backup/index.d.ts.map +1 -0
  402. package/dist/server/server/persistence/errors.d.ts +99 -0
  403. package/dist/server/server/persistence/errors.d.ts.map +1 -0
  404. package/dist/server/server/persistence/governedActionReconciliationLocator.d.ts +14 -0
  405. package/dist/server/server/persistence/governedActionReconciliationLocator.d.ts.map +1 -0
  406. package/dist/server/server/persistence/index.d.ts +11 -0
  407. package/dist/server/server/persistence/index.d.ts.map +1 -0
  408. package/dist/server/server/persistence/object-store/BlobDigest.d.ts +6 -0
  409. package/dist/server/server/persistence/object-store/BlobDigest.d.ts.map +1 -0
  410. package/dist/server/server/persistence/object-store/BlobPath.d.ts +12 -0
  411. package/dist/server/server/persistence/object-store/BlobPath.d.ts.map +1 -0
  412. package/dist/server/server/persistence/object-store/BlobPublisher.d.ts +8 -0
  413. package/dist/server/server/persistence/object-store/BlobPublisher.d.ts.map +1 -0
  414. package/dist/server/server/persistence/object-store/BlobRef.d.ts +16 -0
  415. package/dist/server/server/persistence/object-store/BlobRef.d.ts.map +1 -0
  416. package/dist/server/server/persistence/object-store/BlobStore.d.ts +37 -0
  417. package/dist/server/server/persistence/object-store/BlobStore.d.ts.map +1 -0
  418. package/dist/server/server/persistence/object-store/BlobStoreError.d.ts +57 -0
  419. package/dist/server/server/persistence/object-store/BlobStoreError.d.ts.map +1 -0
  420. package/dist/server/server/persistence/object-store/BlobStoreTypes.d.ts +28 -0
  421. package/dist/server/server/persistence/object-store/BlobStoreTypes.d.ts.map +1 -0
  422. package/dist/server/server/persistence/object-store/OpenedBlob.d.ts +21 -0
  423. package/dist/server/server/persistence/object-store/OpenedBlob.d.ts.map +1 -0
  424. package/dist/server/server/persistence/object-store/PinnedDirectory.d.ts +21 -0
  425. package/dist/server/server/persistence/object-store/PinnedDirectory.d.ts.map +1 -0
  426. package/dist/server/server/persistence/repositories/agentJobModels.d.ts +142 -0
  427. package/dist/server/server/persistence/repositories/agentJobModels.d.ts.map +1 -0
  428. package/dist/server/server/persistence/repositories/agentJobRepository.d.ts +134 -0
  429. package/dist/server/server/persistence/repositories/agentJobRepository.d.ts.map +1 -0
  430. package/dist/server/server/persistence/repositories/authorizedShareRepository.d.ts +92 -0
  431. package/dist/server/server/persistence/repositories/authorizedShareRepository.d.ts.map +1 -0
  432. package/dist/server/server/persistence/repositories/contentBlobMetadataRepository.d.ts +67 -0
  433. package/dist/server/server/persistence/repositories/contentBlobMetadataRepository.d.ts.map +1 -0
  434. package/dist/server/server/persistence/repositories/delivery-graph/contract.d.ts +2989 -0
  435. package/dist/server/server/persistence/repositories/delivery-graph/contract.d.ts.map +1 -0
  436. package/dist/server/server/persistence/repositories/delivery-graph/decode.d.ts +566 -0
  437. package/dist/server/server/persistence/repositories/delivery-graph/decode.d.ts.map +1 -0
  438. package/dist/server/server/persistence/repositories/delivery-graph/integrity.d.ts +16 -0
  439. package/dist/server/server/persistence/repositories/delivery-graph/integrity.d.ts.map +1 -0
  440. package/dist/server/server/persistence/repositories/delivery-graph/quarantine.d.ts +22 -0
  441. package/dist/server/server/persistence/repositories/delivery-graph/quarantine.d.ts.map +1 -0
  442. package/dist/server/server/persistence/repositories/delivery-graph/read.d.ts +2147 -0
  443. package/dist/server/server/persistence/repositories/delivery-graph/read.d.ts.map +1 -0
  444. package/dist/server/server/persistence/repositories/delivery-graph/release-slice.d.ts +16 -0
  445. package/dist/server/server/persistence/repositories/delivery-graph/release-slice.d.ts.map +1 -0
  446. package/dist/server/server/persistence/repositories/delivery-graph/rows.d.ts +683 -0
  447. package/dist/server/server/persistence/repositories/delivery-graph/rows.d.ts.map +1 -0
  448. package/dist/server/server/persistence/repositories/delivery-graph/write.d.ts +946 -0
  449. package/dist/server/server/persistence/repositories/delivery-graph/write.d.ts.map +1 -0
  450. package/dist/server/server/persistence/repositories/deliveryGraphRepository.d.ts +2121 -0
  451. package/dist/server/server/persistence/repositories/deliveryGraphRepository.d.ts.map +1 -0
  452. package/dist/server/server/persistence/repositories/domainEventModels.d.ts +89 -0
  453. package/dist/server/server/persistence/repositories/domainEventModels.d.ts.map +1 -0
  454. package/dist/server/server/persistence/repositories/domainEventRepository.d.ts +85 -0
  455. package/dist/server/server/persistence/repositories/domainEventRepository.d.ts.map +1 -0
  456. package/dist/server/server/persistence/repositories/entityRepository.d.ts +134 -0
  457. package/dist/server/server/persistence/repositories/entityRepository.d.ts.map +1 -0
  458. package/dist/server/server/persistence/repositories/governed-action/codec.d.ts +1478 -0
  459. package/dist/server/server/persistence/repositories/governed-action/codec.d.ts.map +1 -0
  460. package/dist/server/server/persistence/repositories/governed-action/contract.d.ts +858 -0
  461. package/dist/server/server/persistence/repositories/governed-action/contract.d.ts.map +1 -0
  462. package/dist/server/server/persistence/repositories/governed-action/quarantine.d.ts +22 -0
  463. package/dist/server/server/persistence/repositories/governed-action/quarantine.d.ts.map +1 -0
  464. package/dist/server/server/persistence/repositories/governed-action/read.d.ts +452 -0
  465. package/dist/server/server/persistence/repositories/governed-action/read.d.ts.map +1 -0
  466. package/dist/server/server/persistence/repositories/governed-action/rows.d.ts +115 -0
  467. package/dist/server/server/persistence/repositories/governed-action/rows.d.ts.map +1 -0
  468. package/dist/server/server/persistence/repositories/governed-action/transaction.d.ts +457 -0
  469. package/dist/server/server/persistence/repositories/governed-action/transaction.d.ts.map +1 -0
  470. package/dist/server/server/persistence/repositories/governed-action/write-preparation.d.ts +518 -0
  471. package/dist/server/server/persistence/repositories/governed-action/write-preparation.d.ts.map +1 -0
  472. package/dist/server/server/persistence/repositories/governed-action/write-replay.d.ts +702 -0
  473. package/dist/server/server/persistence/repositories/governed-action/write-replay.d.ts.map +1 -0
  474. package/dist/server/server/persistence/repositories/governed-action/write.d.ts +618 -0
  475. package/dist/server/server/persistence/repositories/governed-action/write.d.ts.map +1 -0
  476. package/dist/server/server/persistence/repositories/governedActionRepository.d.ts +467 -0
  477. package/dist/server/server/persistence/repositories/governedActionRepository.d.ts.map +1 -0
  478. package/dist/server/server/persistence/repositories/index.d.ts +26 -0
  479. package/dist/server/server/persistence/repositories/index.d.ts.map +1 -0
  480. package/dist/server/server/persistence/repositories/internal.d.ts +38 -0
  481. package/dist/server/server/persistence/repositories/internal.d.ts.map +1 -0
  482. package/dist/server/server/persistence/repositories/models.d.ts +420 -0
  483. package/dist/server/server/persistence/repositories/models.d.ts.map +1 -0
  484. package/dist/server/server/persistence/repositories/peopleRepository.d.ts +407 -0
  485. package/dist/server/server/persistence/repositories/peopleRepository.d.ts.map +1 -0
  486. package/dist/server/server/persistence/repositories/persistedRowQuarantine.d.ts +20 -0
  487. package/dist/server/server/persistence/repositories/persistedRowQuarantine.d.ts.map +1 -0
  488. package/dist/server/server/persistence/repositories/pluginConfigurationModels.d.ts +76 -0
  489. package/dist/server/server/persistence/repositories/pluginConfigurationModels.d.ts.map +1 -0
  490. package/dist/server/server/persistence/repositories/pluginConfigurationRepository.d.ts +179 -0
  491. package/dist/server/server/persistence/repositories/pluginConfigurationRepository.d.ts.map +1 -0
  492. package/dist/server/server/persistence/repositories/pluginConnectionRepository.d.ts +123 -0
  493. package/dist/server/server/persistence/repositories/pluginConnectionRepository.d.ts.map +1 -0
  494. package/dist/server/server/persistence/repositories/pluginRuntimeModels.d.ts +195 -0
  495. package/dist/server/server/persistence/repositories/pluginRuntimeModels.d.ts.map +1 -0
  496. package/dist/server/server/persistence/repositories/pluginRuntimeRepository.d.ts +431 -0
  497. package/dist/server/server/persistence/repositories/pluginRuntimeRepository.d.ts.map +1 -0
  498. package/dist/server/server/persistence/repositories/providerAccountRepository.d.ts +150 -0
  499. package/dist/server/server/persistence/repositories/providerAccountRepository.d.ts.map +1 -0
  500. package/dist/server/server/persistence/repositories/quarantineRepository.d.ts +42 -0
  501. package/dist/server/server/persistence/repositories/quarantineRepository.d.ts.map +1 -0
  502. package/dist/server/server/persistence/repositories/readiness/assessments.d.ts +2679 -0
  503. package/dist/server/server/persistence/repositories/readiness/assessments.d.ts.map +1 -0
  504. package/dist/server/server/persistence/repositories/readiness/codec.d.ts +1368 -0
  505. package/dist/server/server/persistence/repositories/readiness/codec.d.ts.map +1 -0
  506. package/dist/server/server/persistence/repositories/readiness/contract.d.ts +3315 -0
  507. package/dist/server/server/persistence/repositories/readiness/contract.d.ts.map +1 -0
  508. package/dist/server/server/persistence/repositories/readiness/materialization.d.ts +459 -0
  509. package/dist/server/server/persistence/repositories/readiness/materialization.d.ts.map +1 -0
  510. package/dist/server/server/persistence/repositories/readiness/quarantine.d.ts +22 -0
  511. package/dist/server/server/persistence/repositories/readiness/quarantine.d.ts.map +1 -0
  512. package/dist/server/server/persistence/repositories/readiness/queue.d.ts +112 -0
  513. package/dist/server/server/persistence/repositories/readiness/queue.d.ts.map +1 -0
  514. package/dist/server/server/persistence/repositories/readiness/rows.d.ts +169 -0
  515. package/dist/server/server/persistence/repositories/readiness/rows.d.ts.map +1 -0
  516. package/dist/server/server/persistence/repositories/readiness/rules.d.ts +85 -0
  517. package/dist/server/server/persistence/repositories/readiness/rules.d.ts.map +1 -0
  518. package/dist/server/server/persistence/repositories/readinessRepository.d.ts +1722 -0
  519. package/dist/server/server/persistence/repositories/readinessRepository.d.ts.map +1 -0
  520. package/dist/server/server/persistence/repositories/relationshipRepairProposalRepository.d.ts +294 -0
  521. package/dist/server/server/persistence/repositories/relationshipRepairProposalRepository.d.ts.map +1 -0
  522. package/dist/server/server/persistence/repositories/releaseRepository.d.ts +1062 -0
  523. package/dist/server/server/persistence/repositories/releaseRepository.d.ts.map +1 -0
  524. package/dist/server/server/persistence/repositories/timelineExportAuditRepository.d.ts +39 -0
  525. package/dist/server/server/persistence/repositories/timelineExportAuditRepository.d.ts.map +1 -0
  526. package/dist/server/server/persistence/repositories/timelineRepository.d.ts +84 -0
  527. package/dist/server/server/persistence/repositories/timelineRepository.d.ts.map +1 -0
  528. package/dist/server/server/persistence/repositories/workspaceRepository.d.ts +52 -0
  529. package/dist/server/server/persistence/repositories/workspaceRepository.d.ts.map +1 -0
  530. package/dist/server/server/persistence/schema.d.ts +17 -0
  531. package/dist/server/server/persistence/schema.d.ts.map +1 -0
  532. package/dist/server/server/persistence/schemas.d.ts +14 -0
  533. package/dist/server/server/persistence/schemas.d.ts.map +1 -0
  534. package/dist/server/server/plugins/AtlassianBasicAuth.d.ts +2 -0
  535. package/dist/server/server/plugins/AtlassianBasicAuth.d.ts.map +1 -0
  536. package/dist/server/server/plugins/PluginCapabilityCodecs.d.ts +357 -0
  537. package/dist/server/server/plugins/PluginCapabilityCodecs.d.ts.map +1 -0
  538. package/dist/server/server/plugins/PluginConnection.d.ts +28 -0
  539. package/dist/server/server/plugins/PluginConnection.d.ts.map +1 -0
  540. package/dist/server/server/plugins/PluginConnectionMap.d.ts +22 -0
  541. package/dist/server/server/plugins/PluginConnectionMap.d.ts.map +1 -0
  542. package/dist/server/server/plugins/PluginDefinition.d.ts +9 -0
  543. package/dist/server/server/plugins/PluginDefinition.d.ts.map +1 -0
  544. package/dist/server/server/plugins/PluginDefinitionV1.d.ts +11 -0
  545. package/dist/server/server/plugins/PluginDefinitionV1.d.ts.map +1 -0
  546. package/dist/server/server/plugins/PluginExecutor.d.ts +14 -0
  547. package/dist/server/server/plugins/PluginExecutor.d.ts.map +1 -0
  548. package/dist/server/server/plugins/atlassian/AtlassianOAuthGrants.d.ts +35 -0
  549. package/dist/server/server/plugins/atlassian/AtlassianOAuthGrants.d.ts.map +1 -0
  550. package/dist/server/server/plugins/atlassian/AtlassianProfiles.d.ts +39 -0
  551. package/dist/server/server/plugins/atlassian/AtlassianProfiles.d.ts.map +1 -0
  552. package/dist/server/server/plugins/catalog/firstPartyServiceCatalog.d.ts +13 -0
  553. package/dist/server/server/plugins/catalog/firstPartyServiceCatalog.d.ts.map +1 -0
  554. package/dist/server/server/plugins/clockify/ClockifyReadPlugin.d.ts +78 -0
  555. package/dist/server/server/plugins/clockify/ClockifyReadPlugin.d.ts.map +1 -0
  556. package/dist/server/server/plugins/clockify/ClockifyReadProvider.d.ts +2 -0
  557. package/dist/server/server/plugins/clockify/ClockifyReadProvider.d.ts.map +1 -0
  558. package/dist/server/server/plugins/clockify/ClockifyTimeEntryNormalization.d.ts +2 -0
  559. package/dist/server/server/plugins/clockify/ClockifyTimeEntryNormalization.d.ts.map +1 -0
  560. package/dist/server/server/plugins/clockify/index.d.ts +3 -0
  561. package/dist/server/server/plugins/clockify/index.d.ts.map +1 -0
  562. package/dist/server/server/plugins/codecommit/CodeCommitPluginDefinition.d.ts +4 -0
  563. package/dist/server/server/plugins/codecommit/CodeCommitPluginDefinition.d.ts.map +1 -0
  564. package/dist/server/server/plugins/codecommit/index.d.ts +3 -0
  565. package/dist/server/server/plugins/codecommit/index.d.ts.map +1 -0
  566. package/dist/server/server/plugins/codepipeline/CodePipelinePluginDefinition.d.ts +4 -0
  567. package/dist/server/server/plugins/codepipeline/CodePipelinePluginDefinition.d.ts.map +1 -0
  568. package/dist/server/server/plugins/codepipeline/CodePipelineReadClient.d.ts +2 -0
  569. package/dist/server/server/plugins/codepipeline/CodePipelineReadClient.d.ts.map +1 -0
  570. package/dist/server/server/plugins/codepipeline/CodePipelineReadProvider.d.ts +2 -0
  571. package/dist/server/server/plugins/codepipeline/CodePipelineReadProvider.d.ts.map +1 -0
  572. package/dist/server/server/plugins/codepipeline/index.d.ts +3 -0
  573. package/dist/server/server/plugins/codepipeline/index.d.ts.map +1 -0
  574. package/dist/server/server/plugins/confluence/ConfluencePageAdapter.d.ts +2 -0
  575. package/dist/server/server/plugins/confluence/ConfluencePageAdapter.d.ts.map +1 -0
  576. package/dist/server/server/plugins/confluence/ConfluencePageClient.d.ts +2 -0
  577. package/dist/server/server/plugins/confluence/ConfluencePageClient.d.ts.map +1 -0
  578. package/dist/server/server/plugins/confluence/ConfluencePagePluginDefinition.d.ts +44 -0
  579. package/dist/server/server/plugins/confluence/ConfluencePagePluginDefinition.d.ts.map +1 -0
  580. package/dist/server/server/plugins/confluence/ConfluencePageSchemas.d.ts +2 -0
  581. package/dist/server/server/plugins/confluence/ConfluencePageSchemas.d.ts.map +1 -0
  582. package/dist/server/server/plugins/confluence/SafeConfluenceMarkdown.d.ts +2 -0
  583. package/dist/server/server/plugins/confluence/SafeConfluenceMarkdown.d.ts.map +1 -0
  584. package/dist/server/server/plugins/failures.d.ts +79 -0
  585. package/dist/server/server/plugins/failures.d.ts.map +1 -0
  586. package/dist/server/server/plugins/fake/FakePluginDefinition.d.ts +17 -0
  587. package/dist/server/server/plugins/fake/FakePluginDefinition.d.ts.map +1 -0
  588. package/dist/server/server/plugins/fake/FakePluginProbe.d.ts +40 -0
  589. package/dist/server/server/plugins/fake/FakePluginProbe.d.ts.map +1 -0
  590. package/dist/server/server/plugins/fake/FakePluginScenario.d.ts +46 -0
  591. package/dist/server/server/plugins/fake/FakePluginScenario.d.ts.map +1 -0
  592. package/dist/server/server/plugins/firstPartySynchronization.d.ts +7 -0
  593. package/dist/server/server/plugins/firstPartySynchronization.d.ts.map +1 -0
  594. package/dist/server/server/plugins/index.d.ts +21 -0
  595. package/dist/server/server/plugins/index.d.ts.map +1 -0
  596. package/dist/server/server/plugins/internal/AuthorizedPluginExecutor.d.ts +8 -0
  597. package/dist/server/server/plugins/internal/AuthorizedPluginExecutor.d.ts.map +1 -0
  598. package/dist/server/server/plugins/internal/AuthorizedPluginExecutorMap.d.ts +27 -0
  599. package/dist/server/server/plugins/internal/AuthorizedPluginExecutorMap.d.ts.map +1 -0
  600. package/dist/server/server/plugins/internal/FirstPartyPluginRuntimeRegistry.d.ts +2 -0
  601. package/dist/server/server/plugins/internal/FirstPartyPluginRuntimeRegistry.d.ts.map +1 -0
  602. package/dist/server/server/plugins/internal/PluginRuntime.d.ts +13 -0
  603. package/dist/server/server/plugins/internal/PluginRuntime.d.ts.map +1 -0
  604. package/dist/server/server/plugins/internal/PluginRuntimeAuthority.d.ts +154 -0
  605. package/dist/server/server/plugins/internal/PluginRuntimeAuthority.d.ts.map +1 -0
  606. package/dist/server/server/plugins/internal/PluginRuntimeAuthorityRepository.d.ts +131 -0
  607. package/dist/server/server/plugins/internal/PluginRuntimeAuthorityRepository.d.ts.map +1 -0
  608. package/dist/server/server/plugins/internal/PluginRuntimeAuthoritySource.d.ts +23 -0
  609. package/dist/server/server/plugins/internal/PluginRuntimeAuthoritySource.d.ts.map +1 -0
  610. package/dist/server/server/plugins/internal/PluginRuntimeMap.d.ts +23 -0
  611. package/dist/server/server/plugins/internal/PluginRuntimeMap.d.ts.map +1 -0
  612. package/dist/server/server/plugins/internal/PluginRuntimeRegistry.d.ts +21 -0
  613. package/dist/server/server/plugins/internal/PluginRuntimeRegistry.d.ts.map +1 -0
  614. package/dist/server/server/plugins/jira/JiraIssueNormalization.d.ts +2 -0
  615. package/dist/server/server/plugins/jira/JiraIssueNormalization.d.ts.map +1 -0
  616. package/dist/server/server/plugins/jira/JiraReadPlugin.d.ts +74 -0
  617. package/dist/server/server/plugins/jira/JiraReadPlugin.d.ts.map +1 -0
  618. package/dist/server/server/plugins/jira/JiraReadProvider.d.ts +7 -0
  619. package/dist/server/server/plugins/jira/JiraReadProvider.d.ts.map +1 -0
  620. package/dist/server/server/plugins/jira/index.d.ts +3 -0
  621. package/dist/server/server/plugins/jira/index.d.ts.map +1 -0
  622. package/dist/server/server/plugins/negotiation.d.ts +75 -0
  623. package/dist/server/server/plugins/negotiation.d.ts.map +1 -0
  624. package/dist/server/server/plugins/retryPolicy.d.ts +28 -0
  625. package/dist/server/server/plugins/retryPolicy.d.ts.map +1 -0
  626. package/dist/server/server/readinessDigests.d.ts +103 -0
  627. package/dist/server/server/readinessDigests.d.ts.map +1 -0
  628. package/dist/server/server/runtime/Bootstrap.d.ts +39 -0
  629. package/dist/server/server/runtime/Bootstrap.d.ts.map +1 -0
  630. package/dist/server/server/runtime/ControlCenterServer.d.ts +57 -0
  631. package/dist/server/server/runtime/ControlCenterServer.d.ts.map +1 -0
  632. package/dist/server/server/runtime/DatabaseDrain.d.ts +6 -0
  633. package/dist/server/server/runtime/DatabaseDrain.d.ts.map +1 -0
  634. package/dist/server/server/runtime/DomainEventWakeups.d.ts +22 -0
  635. package/dist/server/server/runtime/DomainEventWakeups.d.ts.map +1 -0
  636. package/dist/server/server/runtime/FirstPartyPluginRuntime.d.ts +2 -0
  637. package/dist/server/server/runtime/FirstPartyPluginRuntime.d.ts.map +1 -0
  638. package/dist/server/server/runtime/GovernedActionExecutionStartup.d.ts +35 -0
  639. package/dist/server/server/runtime/GovernedActionExecutionStartup.d.ts.map +1 -0
  640. package/dist/server/server/runtime/NodeTransport.d.ts +57 -0
  641. package/dist/server/server/runtime/NodeTransport.d.ts.map +1 -0
  642. package/dist/server/server/runtime/ReleaseSynchronizationStartup.d.ts +44 -0
  643. package/dist/server/server/runtime/ReleaseSynchronizationStartup.d.ts.map +1 -0
  644. package/dist/server/server/runtime/RequestUrlBoundary.d.ts +4 -0
  645. package/dist/server/server/runtime/RequestUrlBoundary.d.ts.map +1 -0
  646. package/dist/server/server/runtime/ServerLifecycle.d.ts +74 -0
  647. package/dist/server/server/runtime/ServerLifecycle.d.ts.map +1 -0
  648. package/dist/server/server/runtime/index.d.ts +9 -0
  649. package/dist/server/server/runtime/index.d.ts.map +1 -0
  650. package/dist/server/server/secrets/SecretRef.d.ts +6 -0
  651. package/dist/server/server/secrets/SecretRef.d.ts.map +1 -0
  652. package/dist/server/server/secrets/SecretStore.d.ts +39 -0
  653. package/dist/server/server/secrets/SecretStore.d.ts.map +1 -0
  654. package/dist/server/server/secrets/SecretStoreError.d.ts +41 -0
  655. package/dist/server/server/secrets/SecretStoreError.d.ts.map +1 -0
  656. package/dist/server/server/secrets/index.d.ts +5 -0
  657. package/dist/server/server/secrets/index.d.ts.map +1 -0
  658. package/dist/server/server/security/BindConfig.d.ts +51 -0
  659. package/dist/server/server/security/BindConfig.d.ts.map +1 -0
  660. package/dist/server/server/security/RequestSecurity.d.ts +84 -0
  661. package/dist/server/server/security/RequestSecurity.d.ts.map +1 -0
  662. package/dist/server/server/security/index.d.ts +3 -0
  663. package/dist/server/server/security/index.d.ts.map +1 -0
  664. package/package.json +101 -0
@@ -0,0 +1,1805 @@
1
+ import { Cr as EntityId, Dr as EvidenceId, Er as EvidenceClaimId, F as EvidenceValue, Fr as PersonId, H as RelationshipKind, Hr as ReleaseId, It as deriveReleaseRelay, N as EvidencePredicate, Nr as GraphNodeId, R as LedgerRevision, Vt as Person, dr as PluginHealth, mt as NegotiatedPluginDescriptorV1, pr as NormalizationSchemaVersion, qt as derivePersonInitials, rt as NormalizedIssueAttributes, vr as VendorImmutableId, wr as EnvironmentId, xt as Release, zr as RelationshipId } from "./domainEvent-x7yeq-gU.js";
2
+ import { Ct as PluginCheckpointV1, jt as PluginSyncRequestV1 } from "./readiness-CzU3vjYQ.js";
3
+ import { Kn as PersistenceOperationError, L as Persistence, Ot as DeliveryGraphWriteBatch, Q as PluginMalformedResponseFailure, S as ApplicationInvalidRequest, T as ApplicationServiceUnavailable, Z as PluginConflictFailure, i as supportsFirstPartySynchronization, it as pluginFailureClass, n as DomainEventWakeups, r as firstPartySyncStreamKey, st as PluginStreamKey, t as appendPortfolioInvalidation, v as PluginConnection, w as ApplicationResourceNotFound } from "./portfolioInvalidation-Ds9Xm4_P.js";
4
+ import * as Schema from "effect/Schema";
5
+ import * as DateTime from "effect/DateTime";
6
+ import * as Effect from "effect/Effect";
7
+ import * as Result from "effect/Result";
8
+ import * as Context from "effect/Context";
9
+ import * as Encoding from "effect/Encoding";
10
+ import * as Option from "effect/Option";
11
+ import * as Predicate from "effect/Predicate";
12
+ import * as Stream from "effect/Stream";
13
+ import * as Crypto from "effect/Crypto";
14
+ import * as Clock from "effect/Clock";
15
+ //#region src/server/application/pluginSynchronizationAuthority.ts
16
+ var conflict = () => new PluginConflictFailure({
17
+ operation: "manual-sync",
18
+ diagnosticCode: "manual-sync-runtime-authority-changed"
19
+ });
20
+ var authorityFor = Effect.fn("PluginSynchronizationAuthority.forConnection")(function* (persistence, connection) {
21
+ const configuration = yield* persistence.pluginConfigurations.get(connection.workspaceId, connection.pluginConnectionId);
22
+ return {
23
+ workspaceId: connection.workspaceId,
24
+ pluginConnectionId: connection.pluginConnectionId,
25
+ providerId: connection.providerId,
26
+ connectionRevision: connection.revision,
27
+ configurationRevision: Option.isSome(configuration) ? configuration.value.revision : null
28
+ };
29
+ });
30
+ /** Capture connection and configuration revisions in one durable read transaction. */
31
+ var capturePluginSynchronizationAuthority = Effect.fn("PluginSynchronizationAuthority.capture")(function* (persistence, workspaceId, pluginConnectionId) {
32
+ return yield* persistence.transact(Effect.gen(function* () {
33
+ const connection = yield* persistence.pluginConnections.get(workspaceId, pluginConnectionId);
34
+ return {
35
+ connection,
36
+ authority: yield* authorityFor(persistence, connection)
37
+ };
38
+ }));
39
+ });
40
+ /** Reject a write transaction when its runtime no longer owns current connection authority. */
41
+ var verifyPluginSynchronizationAuthority = Effect.fn("PluginSynchronizationAuthority.verify")(function* (persistence, expected) {
42
+ const connection = yield* persistence.pluginConnections.get(expected.workspaceId, expected.pluginConnectionId).pipe(Effect.catchTag("RecordNotFoundError", () => conflict()));
43
+ const current = yield* authorityFor(persistence, connection);
44
+ if (!connection.isEnabled || current.providerId !== expected.providerId || current.connectionRevision !== expected.connectionRevision || current.configurationRevision !== expected.configurationRevision) return yield* conflict();
45
+ });
46
+ //#endregion
47
+ //#region src/server/application/relationshipInference.ts
48
+ var MAXIMUM_INFERENCE_CANDIDATES = 2e3;
49
+ var addCandidate = (accumulator, candidate) => {
50
+ if (accumulator.candidates.length >= MAXIMUM_INFERENCE_CANDIDATES) {
51
+ accumulator.truncated = true;
52
+ return;
53
+ }
54
+ accumulator.candidates.push(candidate);
55
+ };
56
+ var OWNED_RULE_IDS = /* @__PURE__ */ new Set([
57
+ "codepipeline-trigger-revision-v1",
58
+ "confluence-jira-link-v1",
59
+ "confluence-release-link-v1",
60
+ "jira-key-in-clockify-description-v1",
61
+ "jira-key-in-confluence-metadata-v1",
62
+ "jira-key-in-pull-request-metadata-v1",
63
+ "release-in-confluence-metadata-v1"
64
+ ]);
65
+ var present = (entity) => entity.projection.entityState === "present";
66
+ var resolved = (kind, nodeId) => ({
67
+ _tag: "resolved",
68
+ kind,
69
+ nodeId
70
+ });
71
+ var missing = (kind, missingKey, identityKey) => ({
72
+ _tag: "missing",
73
+ identityKey,
74
+ kind,
75
+ missingKey
76
+ });
77
+ var currentRelationship = (relationship) => relationship.lifecycle._tag !== "missing" && relationship.lifecycle._tag !== "rejected" && relationship.lifecycle._tag !== "superseded";
78
+ var currentExternalRelationship = (relationship) => currentRelationship(relationship) && !(relationship.lifecycle._tag === "inferred" && relationship.provenance._tag === "rule" && OWNED_RULE_IDS.has(relationship.provenance.ruleId));
79
+ var currentOwnedRelationship = (relationship) => currentRelationship(relationship) && relationship.lifecycle._tag === "inferred" && relationship.provenance._tag === "rule" && OWNED_RULE_IDS.has(relationship.provenance.ruleId);
80
+ var currentInferenceRelationship = (relationship) => relationship.lifecycle._tag !== "rejected" && relationship.lifecycle._tag !== "superseded" && relationship.provenance._tag === "rule" && (relationship.provenance.ruleId === "delivery-gap-v1" || OWNED_RULE_IDS.has(relationship.provenance.ruleId));
81
+ var relationshipInRelease = (relationship, releaseId) => relationship.scope?._tag === "release" && relationship.scope.releaseId === releaseId;
82
+ var containsToken = (text, token) => {
83
+ const normalizedText = text.toUpperCase();
84
+ const normalizedToken = token.toUpperCase();
85
+ let offset = normalizedText.indexOf(normalizedToken);
86
+ while (offset >= 0) {
87
+ const before = normalizedText[offset - 1];
88
+ const after = normalizedText[offset + normalizedToken.length];
89
+ const boundary = (character) => character === void 0 || !/[A-Z0-9]/u.test(character);
90
+ if (boundary(before) && boundary(after)) return true;
91
+ offset = normalizedText.indexOf(normalizedToken, offset + normalizedToken.length);
92
+ }
93
+ return false;
94
+ };
95
+ var containsReleaseVersion = (text, version) => {
96
+ const normalizedText = text.toUpperCase();
97
+ const normalizedVersion = version.toUpperCase();
98
+ let offset = normalizedText.indexOf(normalizedVersion);
99
+ while (offset >= 0) {
100
+ const before = normalizedText[offset - 1];
101
+ const after = normalizedText[offset + normalizedVersion.length];
102
+ const boundary = (character) => character === void 0 || !/[A-Z0-9._+-]/u.test(character);
103
+ if (boundary(before) && boundary(after)) return true;
104
+ offset = normalizedText.indexOf(normalizedVersion, offset + normalizedVersion.length);
105
+ }
106
+ return false;
107
+ };
108
+ var metadata = (entity) => {
109
+ const details = entity.projection.details;
110
+ return details._tag === "pull-request" ? [
111
+ entity.projection.title,
112
+ entity.projection.displayKey,
113
+ details.sourceBranch,
114
+ details.targetBranch
115
+ ].join("\n") : [entity.projection.title, entity.projection.displayKey].join("\n");
116
+ };
117
+ var observationKey = (...entities) => entities.map(({ projection }) => `${projection.entityId}@${String(projection.projectionRevision)}`).sort().join("+");
118
+ var inferred = (input) => ({
119
+ ...input,
120
+ lifecycle: "inferred"
121
+ });
122
+ var gap = (input) => ({
123
+ ...input,
124
+ confidence: null,
125
+ evidenceEntityId: null,
126
+ lifecycle: "missing",
127
+ observationKey: input.identityKey,
128
+ ruleId: "delivery-gap-v1"
129
+ });
130
+ var candidateIdentity = (kind, releaseId, source, target) => `relationship:${kind}:${releaseId}:${source}:${target}`;
131
+ var issueGapIdentity = (releaseId, issueNodeId) => `gap:implements:${releaseId}:${issueNodeId}`;
132
+ var pipelineGapIdentity = (releaseId, pullRequestNodeId) => `gap:delivered-by:${releaseId}:${pullRequestNodeId}`;
133
+ var candidateGapKey = (candidate) => {
134
+ if (candidate.lifecycle !== "missing") return null;
135
+ if (candidate.kind === "implements" && candidate.target._tag === "resolved") return `${candidate.kind}:${candidate.releaseId}:${candidate.target.nodeId}`;
136
+ if (candidate.kind === "delivered-by" && candidate.source._tag === "resolved") return `${candidate.kind}:${candidate.releaseId}:${candidate.source.nodeId}`;
137
+ return null;
138
+ };
139
+ var relationshipGapKey = (relationship) => {
140
+ if (relationship.lifecycle._tag !== "missing" || relationship.provenance._tag !== "rule" || relationship.provenance.ruleId !== "delivery-gap-v1" || relationship.scope?._tag !== "release") return null;
141
+ if (relationship.kind === "implements") return `${relationship.kind}:${relationship.scope.releaseId}:${relationship.targetNodeId}`;
142
+ if (relationship.kind === "delivered-by") return `${relationship.kind}:${relationship.scope.releaseId}:${relationship.sourceNodeId}`;
143
+ return null;
144
+ };
145
+ var hasRelationship = (relationships, releaseId, kind, sourceNodeId, targetNodeId) => relationships.some((relationship) => currentExternalRelationship(relationship) && relationshipInRelease(relationship, releaseId) && relationship.kind === kind && (sourceNodeId === null || relationship.sourceNodeId === sourceNodeId) && (targetNodeId === null || relationship.targetNodeId === targetNodeId));
146
+ var addIssueAndTimeCandidates = (entities, accumulator) => {
147
+ const issues = entities.filter((entity) => entity.projection.details._tag === "issue");
148
+ const timeEntries = entities.filter((entity) => entity.projection.details._tag === "time-entry");
149
+ for (const timeEntry of timeEntries) for (const issue of issues) {
150
+ const details = issue.projection.details;
151
+ if (details._tag !== "issue" || !containsToken(metadata(timeEntry), details.key)) continue;
152
+ for (const releaseId of issue.releaseIds) addCandidate(accumulator, inferred({
153
+ confidence: {
154
+ score: .95,
155
+ rationale: `The Clockify description contains Jira key ${details.key}.`
156
+ },
157
+ evidenceEntityId: timeEntry.projection.entityId,
158
+ identityKey: candidateIdentity("tracks-time-for", releaseId, timeEntry.nodeId, issue.nodeId),
159
+ kind: "tracks-time-for",
160
+ observationKey: observationKey(timeEntry, issue),
161
+ releaseId,
162
+ ruleId: "jira-key-in-clockify-description-v1",
163
+ source: resolved("time-entry", timeEntry.nodeId),
164
+ target: resolved("issue", issue.nodeId)
165
+ }));
166
+ }
167
+ };
168
+ var addDocumentationCandidates = (entities, releases, accumulator) => {
169
+ const issues = entities.filter((entity) => entity.projection.details._tag === "issue");
170
+ const releaseVersionCounts = /* @__PURE__ */ new Map();
171
+ for (const release of releases) {
172
+ const version = release.version.toUpperCase();
173
+ releaseVersionCounts.set(version, (releaseVersionCounts.get(version) ?? 0) + 1);
174
+ }
175
+ const pages = entities.filter((entity) => entity.projection.details._tag === "page" && entity.projection.details.status === "current");
176
+ for (const page of pages) {
177
+ const pageDetails = page.projection.details;
178
+ if (pageDetails._tag !== "page") continue;
179
+ const pageMetadata = metadata(page);
180
+ for (const issue of issues) {
181
+ const details = issue.projection.details;
182
+ if (details._tag !== "issue") continue;
183
+ const explicitLink = pageDetails.linkedIssueKeys?.some((key) => key.toUpperCase() === details.key.toUpperCase()) ?? false;
184
+ if (!explicitLink && !containsToken(pageMetadata, details.key)) continue;
185
+ for (const releaseId of issue.releaseIds) addCandidate(accumulator, inferred({
186
+ confidence: {
187
+ score: explicitLink ? .97 : .9,
188
+ rationale: explicitLink ? `Confluence metadata links Jira key ${details.key}.` : `Confluence page metadata contains Jira key ${details.key}.`
189
+ },
190
+ evidenceEntityId: page.projection.entityId,
191
+ identityKey: candidateIdentity("documented-by", releaseId, issue.nodeId, page.nodeId),
192
+ kind: "documented-by",
193
+ observationKey: observationKey(page, issue),
194
+ releaseId,
195
+ ruleId: explicitLink ? "confluence-jira-link-v1" : "jira-key-in-confluence-metadata-v1",
196
+ source: resolved("issue", issue.nodeId),
197
+ target: resolved("page", page.nodeId)
198
+ }));
199
+ }
200
+ for (const release of releases) {
201
+ if ((releaseVersionCounts.get(release.version.toUpperCase()) ?? 0) > 1) continue;
202
+ const explicitLink = pageDetails.linkedReleaseVersions?.some((version) => version.toUpperCase() === release.version.toUpperCase()) ?? false;
203
+ if (!explicitLink && !containsReleaseVersion(pageMetadata, release.version)) continue;
204
+ addCandidate(accumulator, inferred({
205
+ confidence: {
206
+ score: explicitLink ? .96 : .88,
207
+ rationale: explicitLink ? `Confluence metadata links release ${release.version}.` : `Confluence page metadata contains release ${release.version}.`
208
+ },
209
+ evidenceEntityId: page.projection.entityId,
210
+ identityKey: candidateIdentity("documented-by", release.releaseId, release.nodeId, page.nodeId),
211
+ kind: "documented-by",
212
+ observationKey: observationKey(page),
213
+ releaseId: release.releaseId,
214
+ ruleId: explicitLink ? "confluence-release-link-v1" : "release-in-confluence-metadata-v1",
215
+ source: resolved("release", release.nodeId),
216
+ target: resolved("page", page.nodeId)
217
+ }));
218
+ }
219
+ }
220
+ };
221
+ /**
222
+ * Infer a deterministic relationship set from current canonical facts. Rules
223
+ * only propose `inferred` or `missing`; confirmation remains governed.
224
+ */
225
+ var deriveRelationshipInference = (input) => {
226
+ const entities = input.entities.filter(present).map((entity) => ({
227
+ ...entity,
228
+ releaseIds: entity.releaseIds.filter((releaseId) => {
229
+ const touchesEntity = (relationship) => relationshipInRelease(relationship, releaseId) && (relationship.sourceNodeId === entity.nodeId || relationship.targetNodeId === entity.nodeId);
230
+ return !input.relationships.some((relationship) => currentInferenceRelationship(relationship) && touchesEntity(relationship)) || input.relationships.some((relationship) => currentExternalRelationship(relationship) && touchesEntity(relationship));
231
+ })
232
+ }));
233
+ const issues = entities.filter((entity) => entity.projection.details._tag === "issue");
234
+ const pullRequests = entities.filter((entity) => entity.projection.details._tag === "pull-request");
235
+ const pipelines = entities.filter((entity) => entity.projection.details._tag === "pipeline-execution");
236
+ const accumulator = {
237
+ candidates: [],
238
+ truncated: false
239
+ };
240
+ const obsoleteGaps = /* @__PURE__ */ new Set();
241
+ const inferredIssueLinks = /* @__PURE__ */ new Set();
242
+ const pullRequestReleases = /* @__PURE__ */ new Map();
243
+ for (const pullRequest of pullRequests) {
244
+ if (pullRequest.projection.details._tag !== "pull-request") continue;
245
+ const releaseIds = new Set(pullRequest.releaseIds.filter((releaseId) => {
246
+ const touchesPullRequest = (relationship) => relationshipInRelease(relationship, releaseId) && (relationship.sourceNodeId === pullRequest.nodeId || relationship.targetNodeId === pullRequest.nodeId);
247
+ return !input.relationships.some((relationship) => currentOwnedRelationship(relationship) && touchesPullRequest(relationship)) || input.relationships.some((relationship) => currentExternalRelationship(relationship) && touchesPullRequest(relationship));
248
+ }));
249
+ for (const issue of issues) {
250
+ const issueDetails = issue.projection.details;
251
+ if (issueDetails._tag !== "issue" || !containsToken(metadata(pullRequest), issueDetails.key)) continue;
252
+ for (const releaseId of issue.releaseIds) {
253
+ const identityKey = candidateIdentity("implements", releaseId, pullRequest.nodeId, issue.nodeId);
254
+ if (!(input.rejectedCandidateIdentityKeys?.has(identityKey) ?? false)) {
255
+ releaseIds.add(releaseId);
256
+ inferredIssueLinks.add(`${releaseId}:${issue.nodeId}`);
257
+ obsoleteGaps.add(issueGapIdentity(releaseId, issue.nodeId));
258
+ }
259
+ addCandidate(accumulator, inferred({
260
+ confidence: {
261
+ score: containsToken(pullRequest.projection.title, issueDetails.key) ? .98 : .94,
262
+ rationale: `The immutable pull-request metadata contains Jira key ${issueDetails.key}.`
263
+ },
264
+ evidenceEntityId: pullRequest.projection.entityId,
265
+ identityKey,
266
+ kind: "implements",
267
+ observationKey: observationKey(pullRequest, issue),
268
+ releaseId,
269
+ ruleId: "jira-key-in-pull-request-metadata-v1",
270
+ source: resolved("pull-request", pullRequest.nodeId),
271
+ target: resolved("issue", issue.nodeId)
272
+ }));
273
+ }
274
+ }
275
+ for (const relationship of input.relationships) if (currentExternalRelationship(relationship) && relationship.kind === "implements" && relationship.sourceNodeId === pullRequest.nodeId && relationship.scope?._tag === "release") releaseIds.add(relationship.scope.releaseId);
276
+ pullRequestReleases.set(pullRequest.nodeId, releaseIds);
277
+ }
278
+ for (const issue of issues) for (const releaseId of issue.releaseIds) {
279
+ const identityKey = issueGapIdentity(releaseId, issue.nodeId);
280
+ if (inferredIssueLinks.has(`${releaseId}:${issue.nodeId}`) || hasRelationship(input.relationships, releaseId, "implements", null, issue.nodeId)) obsoleteGaps.add(identityKey);
281
+ else {
282
+ const details = issue.projection.details;
283
+ if (details._tag !== "issue") continue;
284
+ addCandidate(accumulator, gap({
285
+ identityKey,
286
+ kind: "implements",
287
+ releaseId,
288
+ source: missing("pull-request", `${details.key}:pull-request`, issue.nodeId),
289
+ target: resolved("issue", issue.nodeId)
290
+ }));
291
+ }
292
+ }
293
+ const inferredPipelineLinks = /* @__PURE__ */ new Set();
294
+ for (const pullRequest of pullRequests) {
295
+ const pullRequestDetails = pullRequest.projection.details;
296
+ if (pullRequestDetails._tag !== "pull-request") continue;
297
+ for (const pipeline of pipelines) {
298
+ const pipelineDetails = pipeline.projection.details;
299
+ if (pipelineDetails._tag !== "pipeline-execution" || pipelineDetails.triggerRevision !== pullRequestDetails.headRevision) continue;
300
+ for (const releaseId of pullRequestReleases.get(pullRequest.nodeId) ?? []) {
301
+ const identityKey = candidateIdentity("delivered-by", releaseId, pullRequest.nodeId, pipeline.nodeId);
302
+ if (!(input.rejectedCandidateIdentityKeys?.has(identityKey) ?? false)) {
303
+ inferredPipelineLinks.add(`${releaseId}:${pullRequest.nodeId}`);
304
+ obsoleteGaps.add(pipelineGapIdentity(releaseId, pullRequest.nodeId));
305
+ }
306
+ addCandidate(accumulator, inferred({
307
+ confidence: {
308
+ score: .99,
309
+ rationale: `The pipeline trigger revision exactly matches pull-request head ${pullRequestDetails.headRevision}.`
310
+ },
311
+ evidenceEntityId: pipeline.projection.entityId,
312
+ identityKey,
313
+ kind: "delivered-by",
314
+ observationKey: observationKey(pullRequest, pipeline),
315
+ releaseId,
316
+ ruleId: "codepipeline-trigger-revision-v1",
317
+ source: resolved("pull-request", pullRequest.nodeId),
318
+ target: resolved("pipeline-execution", pipeline.nodeId)
319
+ }));
320
+ }
321
+ }
322
+ }
323
+ for (const pullRequest of pullRequests) for (const releaseId of pullRequestReleases.get(pullRequest.nodeId) ?? []) {
324
+ const identityKey = pipelineGapIdentity(releaseId, pullRequest.nodeId);
325
+ if (inferredPipelineLinks.has(`${releaseId}:${pullRequest.nodeId}`) || hasRelationship(input.relationships, releaseId, "delivered-by", pullRequest.nodeId, null) || hasRelationship(input.relationships, releaseId, "verified-by", pullRequest.nodeId, null)) obsoleteGaps.add(identityKey);
326
+ else addCandidate(accumulator, gap({
327
+ identityKey,
328
+ kind: "delivered-by",
329
+ releaseId,
330
+ source: resolved("pull-request", pullRequest.nodeId),
331
+ target: missing("pipeline-execution", `${pullRequest.projection.displayKey}:pipeline-execution`, pullRequest.nodeId)
332
+ }));
333
+ }
334
+ addIssueAndTimeCandidates(entities, accumulator);
335
+ addDocumentationCandidates(entities, input.releases, accumulator);
336
+ const unique = new Map(accumulator.candidates.map((candidate) => [candidate.identityKey, candidate]));
337
+ const candidateEdges = new Set([...unique.values()].flatMap((candidate) => candidate.lifecycle === "inferred" && candidate.source._tag === "resolved" && candidate.target._tag === "resolved" ? [`${candidate.kind}:${candidate.releaseId}:${candidate.source.nodeId}:${candidate.target.nodeId}`] : []));
338
+ const candidateGaps = new Set([...unique.values()].flatMap((candidate) => {
339
+ const key = candidateGapKey(candidate);
340
+ return key === null ? [] : [key];
341
+ }));
342
+ const obsoleteRelationshipIds = input.relationships.flatMap((relationship) => {
343
+ const gapKey = relationshipGapKey(relationship);
344
+ const obsoleteInference = relationship.lifecycle._tag === "inferred" && relationship.provenance._tag === "rule" && OWNED_RULE_IDS.has(relationship.provenance.ruleId) && relationship.scope?._tag === "release" && !candidateEdges.has(`${relationship.kind}:${relationship.scope.releaseId}:${relationship.sourceNodeId}:${relationship.targetNodeId}`);
345
+ const obsoleteGap = gapKey !== null && !candidateGaps.has(gapKey);
346
+ return obsoleteInference || obsoleteGap ? [relationship.relationshipId] : [];
347
+ });
348
+ return {
349
+ candidates: [...unique.values()].sort((left, right) => left.identityKey.localeCompare(right.identityKey)),
350
+ obsoleteGapIdentityKeys: [...obsoleteGaps].sort(),
351
+ obsoleteRelationshipIds: [...new Set(obsoleteRelationshipIds)].sort(),
352
+ truncated: accumulator.truncated
353
+ };
354
+ };
355
+ //#endregion
356
+ //#region src/server/application/relationshipInferenceMaterialization.ts
357
+ var MAXIMUM_INFERENCE_ENTITIES = 500;
358
+ var MAXIMUM_INFERENCE_RELEASES = 50;
359
+ var MAXIMUM_INFERENCE_RELATIONSHIPS = 2e3;
360
+ var COMPONENT = "relationship-inference";
361
+ var readRelationship = Effect.fn("RelationshipInferenceMaterialization.readRelationship")(function* (persistence, workspaceId, relationshipId) {
362
+ const result = yield* persistence.deliveryGraph.read(workspaceId, {
363
+ _tag: "relationship",
364
+ relationshipId,
365
+ revision: null
366
+ }).pipe(Effect.result);
367
+ if (Result.isFailure(result)) {
368
+ if (result.failure._tag === "RecordNotFoundError") return null;
369
+ return yield* result.failure;
370
+ }
371
+ return result.success._tag === "relationship" ? result.success.value : null;
372
+ });
373
+ var nodeExists = Effect.fn("RelationshipInferenceMaterialization.nodeExists")(function* (persistence, workspaceId, nodeId) {
374
+ const result = yield* persistence.deliveryGraph.read(workspaceId, {
375
+ _tag: "node",
376
+ nodeId
377
+ }).pipe(Effect.result);
378
+ if (Result.isSuccess(result)) return true;
379
+ if (result.failure._tag === "RecordNotFoundError") return false;
380
+ return yield* result.failure;
381
+ });
382
+ var writeGraph$1 = Effect.fn("RelationshipInferenceMaterialization.writeGraph")(function* (persistence, workspaceId, batch) {
383
+ const encoded = yield* Schema.encodeEffect(DeliveryGraphWriteBatch)(batch).pipe(Effect.mapError(() => new PersistenceOperationError({ operation: "relationship-inference.encode" })));
384
+ return yield* persistence.deliveryGraph.write(workspaceId, encoded);
385
+ });
386
+ var relationshipIdentity = (workspaceId, identityKey) => `${workspaceId}\u0000relationship-inference\u0000relationship\u0000${identityKey}`;
387
+ var missingNodeIdentity = (workspaceId, endpointKind, missingKey) => `${workspaceId}\u0000relationship-inference\u0000missing-node\u0000${endpointKind}\u0000${missingKey}`;
388
+ var evidenceIdentity = (workspaceId, identityKey, observationKey, kind) => `${workspaceId}\u0000relationship-inference\u0000evidence-${kind}\u0000${identityKey}\u0000${observationKey}`;
389
+ var entityNodeIdentity = (workspaceId, entity) => {
390
+ const source = entity.sourceRevision;
391
+ return `${workspaceId}\u0000${source.pluginConnectionId}\u0000${source.providerId}\u0000entity-node\u0000${source.vendorImmutableId}`;
392
+ };
393
+ var releaseNodeIdentity = (workspaceId, pluginConnectionId, providerId, vendorImmutableId) => `${workspaceId}\u0000${pluginConnectionId}\u0000${providerId}\u0000release-node\u0000${vendorImmutableId}`;
394
+ var relationshipIdFor = (identity, workspaceId, identityKey) => identity(relationshipIdentity(workspaceId, identityKey)).pipe(Effect.map(RelationshipId.make));
395
+ var endpointNode = (identity, scope, endpoint) => endpoint._tag === "resolved" ? Effect.succeed({
396
+ node: null,
397
+ nodeId: endpoint.nodeId
398
+ }) : identity(missingNodeIdentity(scope.workspaceId, endpoint.kind, endpoint.identityKey)).pipe(Effect.map((value) => {
399
+ const nodeId = GraphNodeId.make(value);
400
+ return {
401
+ nodeId,
402
+ node: {
403
+ workspaceId: scope.workspaceId,
404
+ nodeId,
405
+ endpointKind: endpoint.kind,
406
+ resolution: {
407
+ _tag: "missing",
408
+ expectedKind: "entity",
409
+ expectedEntityKind: endpoint.kind,
410
+ missingKey: endpoint.missingKey
411
+ },
412
+ createdAt: scope.committedAt
413
+ }
414
+ };
415
+ }));
416
+ var evidenceFor = Effect.fn("RelationshipInferenceMaterialization.evidenceFor")(function* (persistence, identity, scope, candidate, sourceNodeId, targetNodeId, entity) {
417
+ const evidenceId = EvidenceId.make(yield* identity(evidenceIdentity(scope.workspaceId, candidate.identityKey, candidate.observationKey, "item")));
418
+ const evidenceClaimId = EvidenceClaimId.make(yield* identity(evidenceIdentity(scope.workspaceId, candidate.identityKey, candidate.observationKey, "claim")));
419
+ const source = entity.sourceRevision;
420
+ const sourceStreamKey = yield* Schema.decodeUnknownEffect(PluginStreamKey)(firstPartySyncStreamKey(source.providerId)).pipe(Effect.mapError(() => new PersistenceOperationError({ operation: "relationship-inference.source-stream" })));
421
+ const pluginHealth = yield* persistence.pluginRuntime.getLastSuccessfulHealth(scope.workspaceId, source.pluginConnectionId, sourceStreamKey);
422
+ if (pluginHealth === null) return yield* new PersistenceOperationError({ operation: "relationship-inference.source-health" });
423
+ const sourceAgeSeconds = Math.max(0, (DateTime.toEpochMillis(scope.committedAt) - DateTime.toEpochMillis(source.lastObservedAt)) / 1e3);
424
+ return {
425
+ item: {
426
+ workspaceId: scope.workspaceId,
427
+ evidenceId,
428
+ schemaVersion: 1,
429
+ attribution: {
430
+ _tag: "system",
431
+ component: COMPONENT
432
+ },
433
+ verifier: {
434
+ _tag: "system",
435
+ component: COMPONENT
436
+ },
437
+ observedAt: source.lastObservedAt,
438
+ recordedAt: scope.committedAt,
439
+ validUntil: null,
440
+ freshness: {
441
+ _tag: "current",
442
+ evaluatedAt: scope.committedAt,
443
+ pluginHealth,
444
+ provenance: {
445
+ _tag: "provider",
446
+ sourceRevision: source
447
+ },
448
+ sourceObservedAt: source.lastObservedAt,
449
+ staleAfterSeconds: Math.max(1, Math.ceil(sourceAgeSeconds) + 86400),
450
+ synchronizedAt: source.synchronizedAt
451
+ },
452
+ retention: {
453
+ classification: "evidence",
454
+ retainUntil: null,
455
+ legalHold: false
456
+ }
457
+ },
458
+ claim: {
459
+ workspaceId: scope.workspaceId,
460
+ evidenceClaimId,
461
+ evidenceId,
462
+ subjectNodeId: sourceNodeId,
463
+ predicate: "relationship-observed",
464
+ value: {
465
+ _tag: "reference",
466
+ targetNodeId
467
+ },
468
+ recordedAt: scope.committedAt,
469
+ supersedesEvidenceClaimId: null
470
+ }
471
+ };
472
+ });
473
+ var unchanged = (previous, candidate, sourceNodeId, targetNodeId, claimId) => previous !== null && previous.kind === candidate.kind && previous.sourceNodeId === sourceNodeId && previous.targetNodeId === targetNodeId && previous.scope?._tag === "release" && previous.scope.releaseId === candidate.releaseId && previous.lifecycle._tag === candidate.lifecycle && (claimId === null || previous.evidenceClaimIds.includes(claimId));
474
+ var protectedByDecision = (previous) => previous?.lifecycle._tag === "governed" || previous?.lifecycle._tag === "verified" || previous?.lifecycle._tag === "rejected";
475
+ var materializeCandidate = Effect.fn("RelationshipInferenceMaterialization.materializeCandidate")(function* (persistence, identity, scope, candidate, entityById) {
476
+ const relationshipId = yield* relationshipIdFor(identity, scope.workspaceId, candidate.identityKey);
477
+ const previous = yield* readRelationship(persistence, scope.workspaceId, relationshipId);
478
+ if (protectedByDecision(previous)) return {
479
+ evidenceClaimCount: 0,
480
+ evidenceItemCount: 0,
481
+ nodeCount: 0,
482
+ relationshipCount: 0,
483
+ skippedDueToBounds: false
484
+ };
485
+ const source = yield* endpointNode(identity, scope, candidate.source);
486
+ const target = yield* endpointNode(identity, scope, candidate.target);
487
+ const evidenceEntity = candidate.evidenceEntityId === null ? null : entityById.get(candidate.evidenceEntityId) ?? null;
488
+ const evidence = evidenceEntity === null ? null : yield* evidenceFor(persistence, identity, scope, candidate, source.nodeId, target.nodeId, evidenceEntity);
489
+ if (unchanged(previous, candidate, source.nodeId, target.nodeId, evidence?.claim.evidenceClaimId ?? null)) return {
490
+ evidenceClaimCount: 0,
491
+ evidenceItemCount: 0,
492
+ nodeCount: 0,
493
+ relationshipCount: 0,
494
+ skippedDueToBounds: false
495
+ };
496
+ const nodes = [];
497
+ if (source.node !== null && !(yield* nodeExists(persistence, scope.workspaceId, source.nodeId))) nodes.push(source.node);
498
+ if (target.node !== null && !(yield* nodeExists(persistence, scope.workspaceId, target.nodeId))) nodes.push(target.node);
499
+ const confidence = candidate.confidence === null ? {
500
+ _tag: "unknown",
501
+ rationale: "No matching provider evidence is currently synchronized."
502
+ } : {
503
+ _tag: "inferred",
504
+ ...candidate.confidence
505
+ };
506
+ const relationship = {
507
+ workspaceId: scope.workspaceId,
508
+ relationshipId,
509
+ relationshipSchemaVersion: 1,
510
+ revision: LedgerRevision.make((previous?.revision ?? 0) + 1),
511
+ supersedesRevision: previous?.revision ?? null,
512
+ kind: candidate.kind,
513
+ sourceNodeId: source.nodeId,
514
+ sourceNodeKind: candidate.source.kind,
515
+ targetNodeId: target.nodeId,
516
+ targetNodeKind: candidate.target.kind,
517
+ scope: {
518
+ _tag: "release",
519
+ releaseId: candidate.releaseId
520
+ },
521
+ lifecycle: candidate.lifecycle === "missing" ? {
522
+ _tag: "missing",
523
+ effectiveAt: scope.committedAt,
524
+ reason: "No synchronized provider evidence currently resolves this required delivery link."
525
+ } : {
526
+ _tag: "inferred",
527
+ effectiveAt: scope.committedAt
528
+ },
529
+ confidence,
530
+ provenance: {
531
+ _tag: "rule",
532
+ ruleId: candidate.ruleId,
533
+ ruleVersion: 1,
534
+ rationale: candidate.confidence?.rationale ?? "Required delivery link has no synchronized match."
535
+ },
536
+ recordedBy: {
537
+ _tag: "system",
538
+ component: COMPONENT
539
+ },
540
+ evidenceClaimIds: evidence === null ? [] : [evidence.claim.evidenceClaimId],
541
+ recordedAt: scope.committedAt
542
+ };
543
+ return {
544
+ ...yield* writeGraph$1(persistence, scope.workspaceId, {
545
+ entityProjections: [],
546
+ nodes,
547
+ evidenceItems: evidence === null ? [] : [evidence.item],
548
+ evidenceClaims: evidence === null ? [] : [evidence.claim],
549
+ relationships: [relationship]
550
+ }),
551
+ skippedDueToBounds: false
552
+ };
553
+ });
554
+ var supersedeObsoleteGap = Effect.fn("RelationshipInferenceMaterialization.supersedeObsoleteGap")(function* (persistence, identity, scope, identityKey) {
555
+ const relationshipId = yield* relationshipIdFor(identity, scope.workspaceId, identityKey);
556
+ const previous = yield* readRelationship(persistence, scope.workspaceId, relationshipId);
557
+ if (previous?.lifecycle._tag !== "missing") return 0;
558
+ const relationship = {
559
+ ...previous,
560
+ revision: LedgerRevision.make(previous.revision + 1),
561
+ supersedesRevision: previous.revision,
562
+ lifecycle: {
563
+ _tag: "superseded",
564
+ effectiveAt: scope.committedAt,
565
+ reason: "New synchronized evidence resolved the previously missing link."
566
+ },
567
+ recordedAt: scope.committedAt
568
+ };
569
+ return (yield* writeGraph$1(persistence, scope.workspaceId, {
570
+ entityProjections: [],
571
+ nodes: [],
572
+ evidenceItems: [],
573
+ evidenceClaims: [],
574
+ relationships: [relationship]
575
+ })).relationshipCount;
576
+ });
577
+ var supersedeObsoleteRelationship = Effect.fn("RelationshipInferenceMaterialization.supersedeObsoleteRelationship")(function* (persistence, scope, relationshipId, reason) {
578
+ const previous = yield* readRelationship(persistence, scope.workspaceId, relationshipId);
579
+ if (previous?.lifecycle._tag !== "inferred" && previous?.lifecycle._tag !== "missing") return 0;
580
+ const relationship = {
581
+ ...previous,
582
+ revision: LedgerRevision.make(previous.revision + 1),
583
+ supersedesRevision: previous.revision,
584
+ lifecycle: {
585
+ _tag: "superseded",
586
+ effectiveAt: scope.committedAt,
587
+ reason: reason ?? (previous.lifecycle._tag === "missing" ? "The entity is no longer in the release scope that required this missing link." : "Current synchronized metadata no longer supports this inferred link.")
588
+ },
589
+ recordedAt: scope.committedAt
590
+ };
591
+ return (yield* writeGraph$1(persistence, scope.workspaceId, {
592
+ entityProjections: [],
593
+ nodes: [],
594
+ evidenceItems: [],
595
+ evidenceClaims: [],
596
+ relationships: [relationship]
597
+ })).relationshipCount;
598
+ });
599
+ var emptyReceipt = (skippedDueToBounds) => ({
600
+ evidenceClaimCount: 0,
601
+ evidenceItemCount: 0,
602
+ nodeCount: 0,
603
+ relationshipCount: 0,
604
+ skippedDueToBounds
605
+ });
606
+ var retireInferenceForReleases = Effect.fn("RelationshipInferenceMaterialization.retireInferenceForReleases")(function* (persistence, scope, releaseIds, reason) {
607
+ const reads = yield* Effect.forEach(releaseIds ?? [null], (releaseId) => persistence.deliveryGraph.read(scope.workspaceId, {
608
+ _tag: "componentRelationships",
609
+ releaseId,
610
+ component: COMPONENT,
611
+ limit: MAXIMUM_INFERENCE_RELATIONSHIPS
612
+ }));
613
+ if (reads.some((read) => read._tag !== "componentRelationships" || read.value.truncated)) return emptyReceipt(true);
614
+ const relationshipIds = new Set(reads.flatMap((read) => read._tag === "componentRelationships" ? read.value.relationships.map(({ relationshipId }) => relationshipId) : []));
615
+ let relationshipCount = 0;
616
+ for (const relationshipId of relationshipIds) relationshipCount += yield* supersedeObsoleteRelationship(persistence, scope, relationshipId, reason);
617
+ return {
618
+ ...emptyReceipt(true),
619
+ relationshipCount
620
+ };
621
+ });
622
+ var retireInferenceAtEntityBound = Effect.fn("RelationshipInferenceMaterialization.retireInferenceAtEntityBound")(function* (persistence, scope) {
623
+ return yield* retireInferenceForReleases(persistence, scope, null, "Inference inputs exceeded the bounded workspace snapshot, so this relationship can no longer be proven.");
624
+ });
625
+ /** Persist current rule candidates after a normalized page has committed. */
626
+ var materializeRelationshipInference = Effect.fn("RelationshipInferenceMaterialization.reconcile")(function* (persistence, identity, scope) {
627
+ const projectionResult = yield* persistence.deliveryGraph.read(scope.workspaceId, {
628
+ _tag: "workspaceEntityProjections",
629
+ owner: null,
630
+ query: null,
631
+ service: null,
632
+ status: null,
633
+ type: null,
634
+ limit: MAXIMUM_INFERENCE_ENTITIES
635
+ });
636
+ if (projectionResult._tag !== "workspaceEntityProjections") return emptyReceipt(true);
637
+ if (projectionResult.value.truncated) return yield* retireInferenceAtEntityBound(persistence, scope);
638
+ const records = yield* Effect.forEach(projectionResult.value.items, ({ projection }) => persistence.entities.get(scope.workspaceId, projection.entityId), { concurrency: 10 });
639
+ const entityById = new Map(records.map((record) => [record.entityId, record]));
640
+ const entities = [];
641
+ for (const item of projectionResult.value.items) {
642
+ const entity = entityById.get(item.projection.entityId);
643
+ if (entity === void 0) continue;
644
+ entities.push({
645
+ projection: item.projection,
646
+ releaseIds: item.releaseIds,
647
+ nodeId: GraphNodeId.make(yield* identity(entityNodeIdentity(scope.workspaceId, entity)))
648
+ });
649
+ }
650
+ const releases = yield* persistence.releases.list(scope.workspaceId, 51);
651
+ if (releases.length > MAXIMUM_INFERENCE_RELEASES) return yield* retireInferenceAtEntityBound(persistence, scope);
652
+ const inferenceReleases = [];
653
+ for (const { release } of releases) {
654
+ const candidates = yield* Effect.forEach(release.sourceRevisions, (source) => Effect.gen(function* () {
655
+ const nodeId = GraphNodeId.make(yield* identity(releaseNodeIdentity(scope.workspaceId, source.pluginConnectionId, source.providerId, source.vendorImmutableId)));
656
+ return {
657
+ exists: yield* nodeExists(persistence, scope.workspaceId, nodeId),
658
+ nodeId
659
+ };
660
+ }));
661
+ const selected = candidates.find(({ exists }) => exists) ?? candidates[0];
662
+ if (selected === void 0) continue;
663
+ inferenceReleases.push({
664
+ inferenceRelease: {
665
+ nodeId: selected.nodeId,
666
+ releaseId: release.id,
667
+ version: release.version
668
+ },
669
+ node: selected.exists ? null : {
670
+ workspaceId: scope.workspaceId,
671
+ nodeId: selected.nodeId,
672
+ endpointKind: "release",
673
+ resolution: {
674
+ _tag: "resolved",
675
+ target: {
676
+ _tag: "release",
677
+ releaseId: release.id
678
+ }
679
+ },
680
+ createdAt: scope.committedAt
681
+ }
682
+ });
683
+ }
684
+ const releaseIds = releases.map(({ release }) => release.id);
685
+ const slices = yield* Effect.forEach(releaseIds, (releaseId) => persistence.deliveryGraph.read(scope.workspaceId, {
686
+ _tag: "releaseSlice",
687
+ releaseId,
688
+ environmentId: null,
689
+ limit: MAXIMUM_INFERENCE_ENTITIES
690
+ }));
691
+ const truncatedReleaseIds = slices.flatMap((slice, index) => {
692
+ const releaseId = releaseIds[index];
693
+ return releaseId !== void 0 && (slice._tag !== "releaseSlice" || slice.value.truncated) ? [releaseId] : [];
694
+ });
695
+ if (truncatedReleaseIds.length > 0) return yield* retireInferenceForReleases(persistence, scope, truncatedReleaseIds, "The bounded release relationship snapshot was incomplete, so this inference can no longer be proven.");
696
+ const relationships = slices.flatMap((slice) => slice._tag === "releaseSlice" ? slice.value.relationships : []);
697
+ const inferenceInput = {
698
+ entities,
699
+ releases: inferenceReleases.map(({ inferenceRelease }) => inferenceRelease),
700
+ relationships
701
+ };
702
+ const initialInference = deriveRelationshipInference(inferenceInput);
703
+ const rejectedCandidateIdentityKeys = /* @__PURE__ */ new Set();
704
+ for (const candidate of initialInference.candidates) {
705
+ if (candidate.lifecycle !== "inferred") continue;
706
+ const relationshipId = yield* relationshipIdFor(identity, scope.workspaceId, candidate.identityKey);
707
+ if ((yield* readRelationship(persistence, scope.workspaceId, relationshipId))?.lifecycle._tag === "rejected") rejectedCandidateIdentityKeys.add(candidate.identityKey);
708
+ }
709
+ const inference = rejectedCandidateIdentityKeys.size === 0 ? initialInference : deriveRelationshipInference({
710
+ ...inferenceInput,
711
+ rejectedCandidateIdentityKeys
712
+ });
713
+ if (inference.truncated) return yield* retireInferenceAtEntityBound(persistence, scope);
714
+ let receipt = emptyReceipt(false);
715
+ const missingReleaseNodes = inferenceReleases.flatMap(({ node }) => node === null ? [] : [node]);
716
+ if (missingReleaseNodes.length > 0) {
717
+ const current = yield* writeGraph$1(persistence, scope.workspaceId, {
718
+ entityProjections: [],
719
+ nodes: missingReleaseNodes,
720
+ evidenceItems: [],
721
+ evidenceClaims: [],
722
+ relationships: []
723
+ });
724
+ receipt = {
725
+ ...receipt,
726
+ nodeCount: current.nodeCount
727
+ };
728
+ }
729
+ for (const candidate of inference.candidates) {
730
+ const current = yield* materializeCandidate(persistence, identity, scope, candidate, entityById);
731
+ receipt = {
732
+ evidenceClaimCount: receipt.evidenceClaimCount + current.evidenceClaimCount,
733
+ evidenceItemCount: receipt.evidenceItemCount + current.evidenceItemCount,
734
+ nodeCount: receipt.nodeCount + current.nodeCount,
735
+ relationshipCount: receipt.relationshipCount + current.relationshipCount,
736
+ skippedDueToBounds: false
737
+ };
738
+ }
739
+ for (const identityKey of inference.obsoleteGapIdentityKeys) receipt = {
740
+ ...receipt,
741
+ relationshipCount: receipt.relationshipCount + (yield* supersedeObsoleteGap(persistence, identity, scope, identityKey))
742
+ };
743
+ for (const relationshipId of inference.obsoleteRelationshipIds) receipt = {
744
+ ...receipt,
745
+ relationshipCount: receipt.relationshipCount + (yield* supersedeObsoleteRelationship(persistence, scope, relationshipId))
746
+ };
747
+ return receipt;
748
+ });
749
+ //#endregion
750
+ //#region src/server/application/normalizedPluginPageMaterialization.ts
751
+ var OptionalText = Schema.optionalKey(Schema.NullOr(Schema.String));
752
+ var NamedText = Schema.Union([Schema.String, Schema.Struct({ name: Schema.optionalKey(Schema.NullOr(Schema.String)) })]);
753
+ var EntityAttributes = Schema.Struct({
754
+ key: OptionalText,
755
+ status: Schema.optionalKey(Schema.NullOr(NamedText)),
756
+ priority: Schema.optionalKey(Schema.NullOr(NamedText)),
757
+ estimatePoints: Schema.optionalKey(Schema.NullOr(Schema.Number)),
758
+ repository: OptionalText,
759
+ sourceBranch: OptionalText,
760
+ targetBranch: OptionalText,
761
+ headRevision: OptionalText,
762
+ reviewState: OptionalText,
763
+ spaceKey: OptionalText,
764
+ spaceId: OptionalText,
765
+ currentVersion: Schema.optionalKey(Schema.NullOr(Schema.Number)),
766
+ linkedIssueKeys: Schema.optionalKey(Schema.Array(Schema.String)),
767
+ linkedReleaseVersions: Schema.optionalKey(Schema.Array(Schema.String)),
768
+ pipelineName: OptionalText,
769
+ executionId: OptionalText,
770
+ triggerRevision: OptionalText,
771
+ sourceRevisions: Schema.optionalKey(Schema.Array(Schema.Struct({ revisionId: OptionalText }))),
772
+ environmentId: OptionalText,
773
+ revision: OptionalText,
774
+ durationMinutes: Schema.optionalKey(Schema.NullOr(Schema.Number)),
775
+ billable: Schema.optionalKey(Schema.Boolean),
776
+ approvalState: OptionalText,
777
+ interval: Schema.optionalKey(Schema.Struct({
778
+ duration: OptionalText,
779
+ state: OptionalText
780
+ }))
781
+ });
782
+ var LegacyIssueAttributes = Schema.Struct({
783
+ key: OptionalText,
784
+ status: Schema.optionalKey(Schema.NullOr(NamedText)),
785
+ priority: Schema.optionalKey(Schema.NullOr(NamedText)),
786
+ estimatePoints: Schema.optionalKey(Schema.NullOr(Schema.Number))
787
+ });
788
+ var LegacyIssueAttributeKeys = /* @__PURE__ */ new Set([
789
+ "key",
790
+ "status",
791
+ "priority",
792
+ "estimatePoints",
793
+ "schemaVersion",
794
+ "summary"
795
+ ]);
796
+ var ReleaseAttributes = Schema.Struct({
797
+ serviceName: Schema.String.check(Schema.isTrimmed(), Schema.isNonEmpty(), Schema.isMaxLength(200)),
798
+ version: Schema.String.check(Schema.isTrimmed(), Schema.isNonEmpty(), Schema.isMaxLength(100)),
799
+ lifecycle: Schema.Literals([
800
+ "assembling",
801
+ "candidate",
802
+ "deploying",
803
+ "released",
804
+ "cancelled"
805
+ ])
806
+ });
807
+ var JiraIssueRelationshipSnapshot = Schema.Struct({
808
+ fixVersions: Schema.Array(Schema.Struct({ sourceId: Schema.NullOr(Schema.String) })),
809
+ truncatedFields: Schema.Array(Schema.String)
810
+ });
811
+ var EvidenceData = Schema.Struct({
812
+ predicate: Schema.optionalKey(EvidencePredicate),
813
+ value: Schema.optionalKey(EvidenceValue)
814
+ });
815
+ /** Redacted failure raised before a normalized page can become a canonical projection. */
816
+ var NormalizedPluginPageMaterializationError = class extends Schema.TaggedErrorClass()("NormalizedPluginPageMaterializationError", {
817
+ diagnosticCode: Schema.String.check(Schema.isTrimmed(), Schema.isNonEmpty(), Schema.isMaxLength(100)),
818
+ eventId: Schema.NullOr(Schema.String.check(Schema.isTrimmed(), Schema.isNonEmpty(), Schema.isMaxLength(512)))
819
+ }) {};
820
+ var malformed = (diagnosticCode, eventId = null) => new NormalizedPluginPageMaterializationError({
821
+ diagnosticCode,
822
+ eventId
823
+ });
824
+ var decodedAttributes = Effect.fn("NormalizedPluginPageMaterialization.decodeAttributes")(function* (event) {
825
+ return yield* Schema.decodeUnknownEffect(EntityAttributes)(event.attributes).pipe(Effect.mapError(() => malformed("normalized-entity-attributes-invalid", event.eventId)));
826
+ });
827
+ var bounded = (value, fallback, maximum) => {
828
+ const normalized = value?.trim();
829
+ return (normalized === void 0 || normalized.length === 0 ? fallback : normalized).slice(0, maximum);
830
+ };
831
+ var namedText = (value) => typeof value === "string" ? value : value?.name ?? null;
832
+ var decodedIssueAttributes = Effect.fn("NormalizedPluginPageMaterialization.decodeIssueAttributes")(function* (event) {
833
+ const normalized = Schema.decodeUnknownResult(NormalizedIssueAttributes)(event.attributes);
834
+ if (Result.isSuccess(normalized)) return normalized.success;
835
+ if (Object.keys(event.attributes).some((key) => !LegacyIssueAttributeKeys.has(key))) return yield* malformed("normalized-issue-attributes-invalid", event.eventId);
836
+ const legacy = yield* Schema.decodeUnknownEffect(LegacyIssueAttributes)(event.attributes).pipe(Effect.mapError(() => malformed("normalized-issue-attributes-invalid", event.eventId)));
837
+ const key = bounded(legacy.key, event.vendorImmutableId, 100);
838
+ return yield* Schema.decodeUnknownEffect(NormalizedIssueAttributes)({
839
+ key,
840
+ status: bounded(namedText(legacy.status), "unknown", 100),
841
+ priority: legacy.priority === null || legacy.priority === void 0 ? null : bounded(namedText(legacy.priority), "unknown", 100),
842
+ estimatePoints: legacy.estimatePoints ?? null
843
+ }).pipe(Effect.mapError(() => malformed("normalized-issue-attributes-invalid", event.eventId)));
844
+ });
845
+ var canonicalKind = (entityType) => {
846
+ switch (entityType) {
847
+ case "issue":
848
+ case "jira.issue": return "issue";
849
+ case "pull-request": return "pull-request";
850
+ case "page":
851
+ case "confluence-page": return "page";
852
+ case "pipeline-execution":
853
+ case "aws.codepipeline.execution": return "pipeline-execution";
854
+ case "deployment": return "deployment";
855
+ case "time-entry":
856
+ case "clockify.time-entry": return "time-entry";
857
+ default: return null;
858
+ }
859
+ };
860
+ var reviewState = (value) => {
861
+ switch (value?.toLowerCase()) {
862
+ case "requested":
863
+ case "open": return "requested";
864
+ case "changes-requested":
865
+ case "changes requested": return "changes-requested";
866
+ case "approved": return "approved";
867
+ case "merged":
868
+ case "closed": return "merged";
869
+ default: return "not-requested";
870
+ }
871
+ };
872
+ var pipelineStatus = (value) => {
873
+ switch (value?.toLowerCase()) {
874
+ case "inprogress":
875
+ case "in-progress":
876
+ case "running": return "running";
877
+ case "succeeded":
878
+ case "success": return "succeeded";
879
+ case "failed":
880
+ case "failure": return "failed";
881
+ case "stopped":
882
+ case "stopping":
883
+ case "superseded":
884
+ case "abandoned": return "stopped";
885
+ default: return "queued";
886
+ }
887
+ };
888
+ var isoDurationMinutes = (value) => {
889
+ if (value === null || value === void 0) return 0;
890
+ const match = /^PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?$/u.exec(value);
891
+ if (match === null) return 0;
892
+ const hours = Number(match[1] ?? 0);
893
+ const minutes = Number(match[2] ?? 0);
894
+ const seconds = Number(match[3] ?? 0);
895
+ return Math.max(0, Math.round(hours * 60 + minutes + seconds / 60));
896
+ };
897
+ var entityPresentation = Effect.fn("NormalizedPluginPageMaterialization.entityPresentation")(function* (event, kind) {
898
+ const attributes = yield* decodedAttributes(event);
899
+ switch (kind) {
900
+ case "issue": {
901
+ const issueAttributes = yield* decodedIssueAttributes(event);
902
+ return {
903
+ displayKey: issueAttributes.key,
904
+ details: {
905
+ _tag: "issue",
906
+ ...issueAttributes
907
+ }
908
+ };
909
+ }
910
+ case "pull-request": return {
911
+ displayKey: bounded(event.vendorImmutableId, event.vendorImmutableId, 200),
912
+ details: {
913
+ _tag: "pull-request",
914
+ repository: bounded(attributes.repository, "unknown", 200),
915
+ sourceBranch: bounded(attributes.sourceBranch, "unknown", 500),
916
+ targetBranch: bounded(attributes.targetBranch, "unknown", 500),
917
+ headRevision: bounded(attributes.headRevision, event.revision, 512),
918
+ reviewState: reviewState(attributes.reviewState ?? namedText(attributes.status))
919
+ }
920
+ };
921
+ case "page": return {
922
+ displayKey: bounded(event.vendorImmutableId, event.vendorImmutableId, 200),
923
+ details: {
924
+ _tag: "page",
925
+ spaceKey: bounded(attributes.spaceKey ?? attributes.spaceId, "unknown", 100),
926
+ revision: bounded(attributes.currentVersion === null || attributes.currentVersion === void 0 ? attributes.revision : String(attributes.currentVersion), event.revision, 512),
927
+ status: namedText(attributes.status)?.toLowerCase() === "superseded" ? "superseded" : "current",
928
+ linkedIssueKeys: attributes.linkedIssueKeys?.map((key) => key.trim()).filter((key, index, keys) => key.length > 0 && key.length <= 100 && keys.indexOf(key) === index).slice(0, 100),
929
+ linkedReleaseVersions: attributes.linkedReleaseVersions?.map((version) => version.trim()).filter((version, index, versions) => version.length > 0 && version.length <= 100 && versions.indexOf(version) === index).slice(0, 100)
930
+ }
931
+ };
932
+ case "pipeline-execution": {
933
+ const executionId = bounded(attributes.executionId, event.vendorImmutableId, 512);
934
+ const pipelineName = bounded(attributes.pipelineName, "unknown", 200);
935
+ const sourceRevision = attributes.sourceRevisions?.find(({ revisionId }) => revisionId !== null)?.revisionId;
936
+ return {
937
+ displayKey: bounded(`${pipelineName}/${executionId}`, executionId, 200),
938
+ details: {
939
+ _tag: "pipeline-execution",
940
+ pipelineName,
941
+ executionId,
942
+ status: pipelineStatus(namedText(attributes.status)),
943
+ triggerRevision: bounded(attributes.triggerRevision ?? sourceRevision, event.revision, 512)
944
+ }
945
+ };
946
+ }
947
+ case "deployment": {
948
+ const environmentId = yield* Schema.decodeUnknownEffect(EnvironmentId)(attributes.environmentId).pipe(Effect.mapError(() => malformed("normalized-deployment-environment-invalid", event.eventId)));
949
+ const status = pipelineStatus(namedText(attributes.status));
950
+ return {
951
+ displayKey: bounded(event.vendorImmutableId, event.vendorImmutableId, 200),
952
+ details: {
953
+ _tag: "deployment",
954
+ environmentId,
955
+ revision: bounded(attributes.revision, event.revision, 512),
956
+ status: status === "queued" ? "pending" : status === "running" ? "deploying" : status === "stopped" ? "rolled-back" : status
957
+ }
958
+ };
959
+ }
960
+ case "time-entry": return {
961
+ displayKey: bounded(event.vendorImmutableId, event.vendorImmutableId, 200),
962
+ details: {
963
+ _tag: "time-entry",
964
+ durationMinutes: Math.max(0, Math.round(attributes.durationMinutes ?? isoDurationMinutes(attributes.interval?.duration))),
965
+ billable: attributes.billable ?? false,
966
+ approvalState: attributes.approvalState === "approved" || attributes.approvalState === "rejected" ? attributes.approvalState : attributes.interval?.state === "running" ? "pending" : "not-required"
967
+ }
968
+ };
969
+ }
970
+ });
971
+ var stableUuid = Effect.fn("NormalizedPluginPageMaterialization.stableUuid")(function* (cryptoService, identity, eventId) {
972
+ const bytes = yield* Effect.fromResult(Encoding.decodeBase64(Encoding.encodeBase64(identity))).pipe(Effect.mapError(() => malformed("normalized-identity-encoding-failed", eventId)));
973
+ const digest = yield* cryptoService.digest("SHA-256", bytes).pipe(Effect.mapError(() => malformed("normalized-identity-digest-failed", eventId)));
974
+ const hex = Encoding.encodeHex(digest);
975
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-7${hex.slice(13, 16)}-8${hex.slice(17, 20)}-${hex.slice(20, 32)}`;
976
+ });
977
+ var sourceIdentity = (scope, vendorImmutableId) => ({
978
+ pluginConnectionId: scope.pluginConnectionId,
979
+ providerId: scope.providerId,
980
+ vendorImmutableId
981
+ });
982
+ var findEntity = Effect.fn("NormalizedPluginPageMaterialization.findEntity")(function* (persistence, scope, vendorImmutableId) {
983
+ const found = yield* persistence.entities.findBySourceIdentity(scope.workspaceId, sourceIdentity(scope, vendorImmutableId)).pipe(Effect.result);
984
+ if (Result.isSuccess(found)) return found.success;
985
+ if (found.failure._tag === "RecordNotFoundError") return null;
986
+ return yield* found.failure;
987
+ });
988
+ var readProjection = Effect.fn("NormalizedPluginPageMaterialization.readProjection")(function* (persistence, workspaceId, entityId) {
989
+ const found = yield* persistence.deliveryGraph.read(workspaceId, {
990
+ _tag: "entityProjection",
991
+ entityId,
992
+ revision: null
993
+ }).pipe(Effect.result);
994
+ if (Result.isSuccess(found)) return found.success._tag === "entityProjection" ? found.success.value : null;
995
+ if (found.failure._tag === "RecordNotFoundError") return null;
996
+ return yield* found.failure;
997
+ });
998
+ var materializationKey = (scope, kind, externalId) => `${scope.workspaceId}\u0000${scope.pluginConnectionId}\u0000${scope.providerId}\u0000${kind}\u0000${externalId}`;
999
+ var entityIdFor = Effect.fn("NormalizedPluginPageMaterialization.entityIdFor")(function* (cryptoService, scope, vendorImmutableId, eventId) {
1000
+ return EntityId.make(yield* stableUuid(cryptoService, materializationKey(scope, "entity", vendorImmutableId), eventId));
1001
+ });
1002
+ var nodeIdFor = Effect.fn("NormalizedPluginPageMaterialization.nodeIdFor")(function* (cryptoService, scope, vendorImmutableId, eventId) {
1003
+ return GraphNodeId.make(yield* stableUuid(cryptoService, materializationKey(scope, "entity-node", vendorImmutableId), eventId));
1004
+ });
1005
+ var releaseIdFor = Effect.fn("NormalizedPluginPageMaterialization.releaseIdFor")(function* (cryptoService, scope, vendorImmutableId, eventId) {
1006
+ return ReleaseId.make(yield* stableUuid(cryptoService, materializationKey(scope, "release", vendorImmutableId), eventId));
1007
+ });
1008
+ var releaseNodeIdFor = Effect.fn("NormalizedPluginPageMaterialization.releaseNodeIdFor")(function* (cryptoService, scope, vendorImmutableId, eventId) {
1009
+ return GraphNodeId.make(yield* stableUuid(cryptoService, materializationKey(scope, "release-node", vendorImmutableId), eventId));
1010
+ });
1011
+ var sourceRevision = (scope, event, firstObservedAt, sourceUrl) => ({
1012
+ ...sourceIdentity(scope, event.vendorImmutableId),
1013
+ revision: event.revision,
1014
+ sourceUrl,
1015
+ firstObservedAt,
1016
+ lastObservedAt: event.observedAt,
1017
+ synchronizedAt: scope.committedAt,
1018
+ normalizationSchemaVersion: NormalizationSchemaVersion.make(1)
1019
+ });
1020
+ var laterTimestamp = (left, right) => DateTime.Order(left, right) >= 0 ? left : right;
1021
+ var sameSourceUrl = (left, right) => left?.href === right?.href;
1022
+ var writeGraph = Effect.fn("NormalizedPluginPageMaterialization.writeGraph")(function* (persistence, workspaceId, batch, eventId) {
1023
+ const encoded = yield* Schema.encodeEffect(DeliveryGraphWriteBatch)(batch).pipe(Effect.mapError(() => malformed("normalized-delivery-graph-batch-invalid", eventId)));
1024
+ return yield* persistence.deliveryGraph.write(workspaceId, encoded);
1025
+ });
1026
+ var materializeUpsertEntity = Effect.fn("NormalizedPluginPageMaterialization.upsertEntity")(function* (persistence, cryptoService, scope, event) {
1027
+ const kind = canonicalKind(event.entityType);
1028
+ if (kind === null) return {
1029
+ entityProjectionCount: 0,
1030
+ nodeCount: 0,
1031
+ skippedEntityCount: 1
1032
+ };
1033
+ const presentation = yield* entityPresentation(event, kind);
1034
+ const existing = yield* findEntity(persistence, scope, event.vendorImmutableId);
1035
+ const entityId = existing?.entityId ?? (yield* entityIdFor(cryptoService, scope, event.vendorImmutableId, event.eventId));
1036
+ const currentProjection = existing === null ? null : yield* readProjection(persistence, scope.workspaceId, entityId);
1037
+ if (existing !== null && existing.sourceRevision.revision === event.revision && currentProjection?.projection.entityState === "present") return {
1038
+ entityProjectionCount: 0,
1039
+ nodeCount: 0,
1040
+ skippedEntityCount: 0
1041
+ };
1042
+ const persisted = existing === null ? yield* persistence.entities.create(scope.workspaceId, {
1043
+ entityId,
1044
+ entityType: kind,
1045
+ sourceRevision: sourceRevision(scope, event, event.observedAt, event.sourceUrl),
1046
+ createdAt: scope.committedAt
1047
+ }) : existing.sourceRevision.revision === event.revision ? existing : yield* persistence.entities.updateSourceRevision(scope.workspaceId, entityId, {
1048
+ sourceRevision: sourceRevision(scope, event, existing.sourceRevision.firstObservedAt, event.sourceUrl),
1049
+ expectedRevision: existing.revision,
1050
+ updatedAt: scope.committedAt
1051
+ });
1052
+ const projectionRevision = LedgerRevision.make((currentProjection?.projection.projectionRevision ?? 0) + 1);
1053
+ const nodeId = yield* nodeIdFor(cryptoService, scope, event.vendorImmutableId, event.eventId);
1054
+ const batch = {
1055
+ entityProjections: [{
1056
+ projection: {
1057
+ workspaceId: scope.workspaceId,
1058
+ entityId,
1059
+ projectionRevision,
1060
+ sourceEntityRevision: LedgerRevision.make(persisted.revision),
1061
+ supersedesProjectionRevision: currentProjection?.projection.projectionRevision ?? null,
1062
+ projectionSchemaVersion: 1,
1063
+ entityState: "present",
1064
+ entityType: kind,
1065
+ displayKey: presentation.displayKey,
1066
+ title: event.title,
1067
+ details: presentation.details
1068
+ },
1069
+ recordedAt: scope.committedAt
1070
+ }],
1071
+ nodes: currentProjection === null ? [{
1072
+ workspaceId: scope.workspaceId,
1073
+ nodeId,
1074
+ endpointKind: kind,
1075
+ resolution: {
1076
+ _tag: "resolved",
1077
+ target: {
1078
+ _tag: "entity",
1079
+ entityId,
1080
+ entityKind: kind
1081
+ }
1082
+ },
1083
+ createdAt: scope.committedAt
1084
+ }] : [],
1085
+ evidenceItems: [],
1086
+ evidenceClaims: [],
1087
+ relationships: []
1088
+ };
1089
+ return {
1090
+ ...yield* writeGraph(persistence, scope.workspaceId, batch, event.eventId),
1091
+ skippedEntityCount: 0
1092
+ };
1093
+ });
1094
+ var materializeRelease = Effect.fn("NormalizedPluginPageMaterialization.upsertRelease")(function* (persistence, cryptoService, scope, event) {
1095
+ const attributes = yield* Schema.decodeUnknownEffect(ReleaseAttributes)(event.attributes).pipe(Effect.mapError(() => malformed("normalized-release-attributes-invalid", event.eventId)));
1096
+ const releaseId = yield* releaseIdFor(cryptoService, scope, event.vendorImmutableId, event.eventId);
1097
+ const existing = yield* persistence.releases.get(scope.workspaceId, releaseId).pipe(Effect.result);
1098
+ if (Result.isFailure(existing) && existing.failure._tag !== "RecordNotFoundError") return yield* existing.failure;
1099
+ const previous = Result.isSuccess(existing) ? existing.success : null;
1100
+ const previousSource = previous?.release.sourceRevisions.find(({ pluginConnectionId, providerId, vendorImmutableId }) => pluginConnectionId === scope.pluginConnectionId && providerId === scope.providerId && vendorImmutableId === event.vendorImmutableId);
1101
+ const observedAt = previousSource === void 0 ? event.observedAt : laterTimestamp(previousSource.lastObservedAt, event.observedAt);
1102
+ const refreshedSource = {
1103
+ ...sourceRevision(scope, event, previousSource?.firstObservedAt ?? event.observedAt, event.sourceUrl),
1104
+ lastObservedAt: observedAt
1105
+ };
1106
+ const sourceAgeSeconds = Math.max(0, (DateTime.toEpochMillis(scope.committedAt) - DateTime.toEpochMillis(observedAt)) / 1e3);
1107
+ const release = yield* Schema.decodeUnknownEffect(Schema.toType(Release))({
1108
+ createdAt: previous?.release.createdAt ?? event.observedAt,
1109
+ freshness: {
1110
+ _tag: "current",
1111
+ evaluatedAt: scope.committedAt,
1112
+ pluginHealth: scope.successfulHealth,
1113
+ provenance: {
1114
+ _tag: "provider",
1115
+ sourceRevision: refreshedSource
1116
+ },
1117
+ sourceObservedAt: observedAt,
1118
+ staleAfterSeconds: Math.max(1, Math.ceil(sourceAgeSeconds) + 86400),
1119
+ synchronizedAt: scope.committedAt
1120
+ },
1121
+ id: releaseId,
1122
+ lifecycle: attributes.lifecycle,
1123
+ relay: deriveReleaseRelay(releaseId),
1124
+ roleAssignments: previous?.release.roleAssignments ?? [],
1125
+ serviceName: attributes.serviceName,
1126
+ sourceRevisions: [...previous?.release.sourceRevisions.filter(({ pluginConnectionId, providerId, vendorImmutableId }) => pluginConnectionId !== scope.pluginConnectionId || providerId !== scope.providerId || vendorImmutableId !== event.vendorImmutableId) ?? [], refreshedSource],
1127
+ targetEnvironmentIds: previous?.release.targetEnvironmentIds ?? [],
1128
+ updatedAt: scope.committedAt,
1129
+ version: attributes.version,
1130
+ workspaceId: scope.workspaceId
1131
+ }).pipe(Effect.mapError(() => malformed("normalized-release-invalid", event.eventId)));
1132
+ if (previous === null) yield* persistence.releases.create(scope.workspaceId, release);
1133
+ else if (previousSource === void 0 || previousSource.revision !== refreshedSource.revision || !sameSourceUrl(previousSource.sourceUrl, refreshedSource.sourceUrl) || !DateTime.Equivalence(previousSource.lastObservedAt, refreshedSource.lastObservedAt) || !DateTime.Equivalence(previousSource.synchronizedAt, refreshedSource.synchronizedAt) || previous.release.serviceName !== release.serviceName || previous.release.version !== release.version || previous.release.lifecycle !== release.lifecycle) yield* persistence.releases.append(scope.workspaceId, release, previous.revision);
1134
+ const nodeId = yield* releaseNodeIdFor(cryptoService, scope, event.vendorImmutableId, event.eventId);
1135
+ const existingNode = yield* persistence.deliveryGraph.read(scope.workspaceId, {
1136
+ _tag: "node",
1137
+ nodeId
1138
+ }).pipe(Effect.result);
1139
+ if (Result.isSuccess(existingNode)) return { nodeCount: 0 };
1140
+ if (existingNode.failure._tag !== "RecordNotFoundError") return yield* existingNode.failure;
1141
+ return { nodeCount: (yield* writeGraph(persistence, scope.workspaceId, {
1142
+ entityProjections: [],
1143
+ nodes: [{
1144
+ workspaceId: scope.workspaceId,
1145
+ nodeId,
1146
+ endpointKind: "release",
1147
+ resolution: {
1148
+ _tag: "resolved",
1149
+ target: {
1150
+ _tag: "release",
1151
+ releaseId
1152
+ }
1153
+ },
1154
+ createdAt: scope.committedAt
1155
+ }],
1156
+ evidenceItems: [],
1157
+ evidenceClaims: [],
1158
+ relationships: []
1159
+ }, event.eventId)).nodeCount };
1160
+ });
1161
+ var materializeTombstoneEntity = Effect.fn("NormalizedPluginPageMaterialization.tombstoneEntity")(function* (persistence, scope, event) {
1162
+ const existing = yield* findEntity(persistence, scope, event.vendorImmutableId);
1163
+ if (existing === null) return { entityProjectionCount: 0 };
1164
+ const current = yield* readProjection(persistence, scope.workspaceId, existing.entityId);
1165
+ if (current === null) return yield* malformed("normalized-tombstone-projection-missing", event.eventId);
1166
+ if (existing.sourceRevision.revision === event.revision && current.projection.entityState === "deleted") return { entityProjectionCount: 0 };
1167
+ const persisted = existing.sourceRevision.revision === event.revision ? existing : yield* persistence.entities.updateSourceRevision(scope.workspaceId, existing.entityId, {
1168
+ sourceRevision: sourceRevision(scope, event, existing.sourceRevision.firstObservedAt, existing.sourceRevision.sourceUrl),
1169
+ expectedRevision: existing.revision,
1170
+ updatedAt: scope.committedAt
1171
+ });
1172
+ const projectionRevision = LedgerRevision.make(current.projection.projectionRevision + 1);
1173
+ return { entityProjectionCount: (yield* writeGraph(persistence, scope.workspaceId, {
1174
+ entityProjections: [{
1175
+ projection: {
1176
+ ...current.projection,
1177
+ projectionRevision,
1178
+ sourceEntityRevision: LedgerRevision.make(persisted.revision),
1179
+ supersedesProjectionRevision: current.projection.projectionRevision,
1180
+ entityState: "deleted"
1181
+ },
1182
+ recordedAt: scope.committedAt
1183
+ }],
1184
+ nodes: [],
1185
+ evidenceItems: [],
1186
+ evidenceClaims: [],
1187
+ relationships: []
1188
+ }, event.eventId)).entityProjectionCount };
1189
+ });
1190
+ var materializePerson = Effect.fn("NormalizedPluginPageMaterialization.upsertPerson")(function* (persistence, cryptoService, scope, event) {
1191
+ const identity = {
1192
+ pluginConnectionId: scope.pluginConnectionId,
1193
+ providerId: scope.providerId,
1194
+ vendorPersonId: VendorImmutableId.make(event.vendorPersonId)
1195
+ };
1196
+ const existing = yield* persistence.people.findPersonBySourceIdentity(scope.workspaceId, identity).pipe(Effect.result);
1197
+ if (Result.isFailure(existing) && existing.failure._tag !== "RecordNotFoundError") return yield* existing.failure;
1198
+ const personId = Result.isSuccess(existing) ? existing.success.person.personId : PersonId.make(yield* stableUuid(cryptoService, materializationKey(scope, "person", event.vendorPersonId), event.eventId));
1199
+ const avatar = event.avatarUrl !== null && event.avatarUrl.toString().length <= 500 ? {
1200
+ _tag: "reference",
1201
+ reference: event.avatarUrl.toString()
1202
+ } : {
1203
+ _tag: "initials",
1204
+ text: derivePersonInitials(event.displayName)
1205
+ };
1206
+ const person = yield* Schema.decodeUnknownEffect(Schema.toType(Person))({
1207
+ personId,
1208
+ displayName: event.displayName,
1209
+ avatar,
1210
+ isActive: event.active,
1211
+ sourceIdentities: Result.isSuccess(existing) ? existing.success.person.sourceIdentities : [identity]
1212
+ }).pipe(Effect.mapError(() => malformed("normalized-person-invalid", event.eventId)));
1213
+ if (Result.isSuccess(existing) && existing.success.person.displayName === person.displayName && existing.success.person.isActive === person.isActive && existing.success.person.avatar._tag === person.avatar._tag && (existing.success.person.avatar._tag === "initials" ? existing.success.person.avatar.text === (person.avatar._tag === "initials" ? person.avatar.text : "") : existing.success.person.avatar.reference === (person.avatar._tag === "reference" ? person.avatar.reference : ""))) return 0;
1214
+ if (Result.isSuccess(existing)) yield* persistence.people.updatePerson(scope.workspaceId, person, existing.success.revision, scope.committedAt);
1215
+ else yield* persistence.people.createPerson(scope.workspaceId, person, scope.committedAt);
1216
+ return 1;
1217
+ });
1218
+ var evidencePredicate = (event) => {
1219
+ const decoded = Schema.decodeUnknownResult(EvidencePredicate)(event.evidenceType);
1220
+ if (Result.isSuccess(decoded)) return decoded.success;
1221
+ return "status-observed";
1222
+ };
1223
+ var materializeEvidence = Effect.fn("NormalizedPluginPageMaterialization.appendEvidence")(function* (persistence, cryptoService, scope, event) {
1224
+ const subject = yield* findEntity(persistence, scope, event.subject.vendorImmutableId);
1225
+ if (subject === null) return yield* malformed("normalized-evidence-subject-missing", event.eventId);
1226
+ if (canonicalKind(event.subject.entityType) === null) return yield* malformed("normalized-evidence-subject-unsupported", event.eventId);
1227
+ const nodeId = yield* nodeIdFor(cryptoService, scope, event.subject.vendorImmutableId, event.eventId);
1228
+ const evidenceId = EvidenceId.make(yield* stableUuid(cryptoService, materializationKey(scope, "evidence", event.evidenceId), event.eventId));
1229
+ const evidenceClaimId = EvidenceClaimId.make(yield* stableUuid(cryptoService, materializationKey(scope, "evidence-claim", event.evidenceId), event.eventId));
1230
+ const decodedData = Schema.decodeUnknownResult(EvidenceData)(event.data);
1231
+ const predicate = Result.isSuccess(decodedData) && decodedData.success.predicate !== void 0 ? decodedData.success.predicate : evidencePredicate(event);
1232
+ const value = Result.isSuccess(decodedData) && decodedData.success.value !== void 0 ? decodedData.success.value : {
1233
+ _tag: "state",
1234
+ value: event.summary
1235
+ };
1236
+ const source = subject.sourceRevision;
1237
+ const ageSeconds = Math.max(0, (DateTime.toEpochMillis(scope.committedAt) - DateTime.toEpochMillis(source.lastObservedAt)) / 1e3);
1238
+ const health = scope.successfulHealth._tag === "healthy" ? {
1239
+ _tag: "healthy",
1240
+ checkedAt: scope.committedAt
1241
+ } : {
1242
+ ...scope.successfulHealth,
1243
+ checkedAt: scope.committedAt
1244
+ };
1245
+ const receipt = yield* writeGraph(persistence, scope.workspaceId, {
1246
+ entityProjections: [],
1247
+ nodes: [],
1248
+ evidenceItems: [{
1249
+ workspaceId: scope.workspaceId,
1250
+ evidenceId,
1251
+ schemaVersion: 1,
1252
+ attribution: {
1253
+ _tag: "plugin",
1254
+ pluginConnectionId: scope.pluginConnectionId,
1255
+ sourceEntityId: subject.entityId,
1256
+ sourceEntityRevision: LedgerRevision.make(subject.revision)
1257
+ },
1258
+ verifier: {
1259
+ _tag: "system",
1260
+ component: "normalized-plugin-page-materializer"
1261
+ },
1262
+ observedAt: event.capturedAt,
1263
+ recordedAt: scope.committedAt,
1264
+ validUntil: null,
1265
+ freshness: {
1266
+ _tag: "current",
1267
+ evaluatedAt: scope.committedAt,
1268
+ pluginHealth: health,
1269
+ provenance: {
1270
+ _tag: "provider",
1271
+ sourceRevision: source
1272
+ },
1273
+ sourceObservedAt: source.lastObservedAt,
1274
+ staleAfterSeconds: Math.max(1, Math.ceil(ageSeconds) + 1),
1275
+ synchronizedAt: scope.committedAt
1276
+ },
1277
+ retention: {
1278
+ classification: "evidence",
1279
+ retainUntil: null,
1280
+ legalHold: false
1281
+ }
1282
+ }],
1283
+ evidenceClaims: [{
1284
+ workspaceId: scope.workspaceId,
1285
+ evidenceClaimId,
1286
+ evidenceId,
1287
+ subjectNodeId: nodeId,
1288
+ predicate,
1289
+ value,
1290
+ recordedAt: scope.committedAt,
1291
+ supersedesEvidenceClaimId: null
1292
+ }],
1293
+ relationships: []
1294
+ }, event.eventId);
1295
+ return {
1296
+ evidenceItemCount: receipt.evidenceItemCount,
1297
+ evidenceClaimCount: receipt.evidenceClaimCount
1298
+ };
1299
+ });
1300
+ var materializeRelationship = Effect.fn("NormalizedPluginPageMaterialization.proposeRelationship")(function* (persistence, cryptoService, scope, event) {
1301
+ const resolveEndpoint = Effect.fn("NormalizedPluginPageMaterialization.resolveRelationshipEndpoint")(function* (reference) {
1302
+ if (reference.entityType === "release") {
1303
+ const releaseId = yield* releaseIdFor(cryptoService, scope, reference.vendorImmutableId, event.eventId);
1304
+ const release = yield* persistence.releases.get(scope.workspaceId, releaseId).pipe(Effect.result);
1305
+ if (Result.isFailure(release)) {
1306
+ if (release.failure._tag === "RecordNotFoundError") return yield* malformed("normalized-relationship-endpoint-missing", event.eventId);
1307
+ return yield* release.failure;
1308
+ }
1309
+ const nodeId = yield* releaseNodeIdFor(cryptoService, scope, reference.vendorImmutableId, event.eventId);
1310
+ const existingNode = yield* persistence.deliveryGraph.read(scope.workspaceId, {
1311
+ _tag: "node",
1312
+ nodeId
1313
+ }).pipe(Effect.result);
1314
+ if (Result.isFailure(existingNode) && existingNode.failure._tag !== "RecordNotFoundError") return yield* existingNode.failure;
1315
+ return {
1316
+ entity: null,
1317
+ kind: "release",
1318
+ node: Result.isSuccess(existingNode) ? null : {
1319
+ workspaceId: scope.workspaceId,
1320
+ nodeId,
1321
+ endpointKind: "release",
1322
+ resolution: {
1323
+ _tag: "resolved",
1324
+ target: {
1325
+ _tag: "release",
1326
+ releaseId
1327
+ }
1328
+ },
1329
+ createdAt: scope.committedAt
1330
+ },
1331
+ nodeId,
1332
+ releaseId
1333
+ };
1334
+ }
1335
+ const entity = yield* findEntity(persistence, scope, reference.vendorImmutableId);
1336
+ const kind = canonicalKind(reference.entityType);
1337
+ if (entity === null) return yield* malformed("normalized-relationship-endpoint-missing", event.eventId);
1338
+ if (kind === null) return yield* malformed("normalized-relationship-endpoint-unsupported", event.eventId);
1339
+ return {
1340
+ entity,
1341
+ kind,
1342
+ node: null,
1343
+ nodeId: yield* nodeIdFor(cryptoService, scope, reference.vendorImmutableId, event.eventId),
1344
+ releaseId: null
1345
+ };
1346
+ });
1347
+ const source = yield* resolveEndpoint(event.from);
1348
+ const target = yield* resolveEndpoint(event.to);
1349
+ const kind = yield* Schema.decodeUnknownEffect(RelationshipKind)(event.relationshipType).pipe(Effect.mapError(() => malformed("normalized-relationship-kind-invalid", event.eventId)));
1350
+ const provenanceEntity = source.entity ?? target.entity;
1351
+ if (provenanceEntity === null) return yield* malformed("normalized-relationship-provenance-entity-missing", event.eventId);
1352
+ const relationshipScope = source.releaseId !== null ? {
1353
+ _tag: "release",
1354
+ releaseId: source.releaseId
1355
+ } : null;
1356
+ const relationshipId = RelationshipId.make(yield* stableUuid(cryptoService, materializationKey(scope, "relationship", event.relationshipId), event.eventId));
1357
+ const existing = yield* persistence.deliveryGraph.read(scope.workspaceId, {
1358
+ _tag: "relationship",
1359
+ relationshipId,
1360
+ revision: null
1361
+ }).pipe(Effect.result);
1362
+ if (Result.isFailure(existing) && existing.failure._tag !== "RecordNotFoundError") return yield* existing.failure;
1363
+ const previous = Result.isSuccess(existing) && existing.success._tag === "relationship" ? existing.success.value : null;
1364
+ const revision = LedgerRevision.make((previous?.revision ?? 0) + 1);
1365
+ const nodes = [];
1366
+ if (source.node !== null) nodes.push(source.node);
1367
+ if (target.node !== null && target.node.nodeId !== source.nodeId) nodes.push(target.node);
1368
+ const receipt = yield* writeGraph(persistence, scope.workspaceId, {
1369
+ entityProjections: [],
1370
+ nodes,
1371
+ evidenceItems: [],
1372
+ evidenceClaims: [],
1373
+ relationships: [{
1374
+ workspaceId: scope.workspaceId,
1375
+ relationshipId,
1376
+ relationshipSchemaVersion: 1,
1377
+ revision,
1378
+ supersedesRevision: previous?.revision ?? null,
1379
+ kind,
1380
+ sourceNodeId: source.nodeId,
1381
+ sourceNodeKind: source.kind,
1382
+ targetNodeId: target.nodeId,
1383
+ targetNodeKind: target.kind,
1384
+ scope: relationshipScope,
1385
+ lifecycle: {
1386
+ _tag: "proposed",
1387
+ effectiveAt: event.observedAt
1388
+ },
1389
+ confidence: {
1390
+ _tag: "inferred",
1391
+ score: event.confidence,
1392
+ rationale: `Proposed by ${scope.providerId} normalized synchronization.`
1393
+ },
1394
+ provenance: {
1395
+ _tag: "plugin",
1396
+ pluginConnectionId: scope.pluginConnectionId,
1397
+ sourceEntityId: provenanceEntity.entityId,
1398
+ sourceEntityRevision: LedgerRevision.make(provenanceEntity.revision)
1399
+ },
1400
+ recordedBy: {
1401
+ _tag: "system",
1402
+ component: "normalized-plugin-page-materializer"
1403
+ },
1404
+ evidenceClaimIds: yield* Effect.forEach(event.evidenceIds, (evidenceId) => stableUuid(cryptoService, materializationKey(scope, "evidence-claim", evidenceId), event.eventId).pipe(Effect.map(EvidenceClaimId.make))),
1405
+ recordedAt: scope.committedAt
1406
+ }]
1407
+ }, event.eventId);
1408
+ return {
1409
+ nodeCount: receipt.nodeCount,
1410
+ relationshipCount: receipt.relationshipCount
1411
+ };
1412
+ });
1413
+ var hasAuthoritativeJiraFixVersions = (event) => {
1414
+ if (event._tag !== "UpsertEntity" || event.entityType !== "jira.issue") return false;
1415
+ const snapshot = Schema.decodeUnknownResult(JiraIssueRelationshipSnapshot)(event.attributes);
1416
+ return Result.isSuccess(snapshot) && !snapshot.success.truncatedFields.includes("fixVersions");
1417
+ };
1418
+ var isReleaseContainmentForIssue = (event, issue) => event._tag === "ProposeRelationship" && event.relationshipType === "contains" && event.from.entityType === "release" && event.to.entityType === issue.entityType && event.to.vendorImmutableId === issue.vendorImmutableId;
1419
+ var retireMissingJiraReleaseContainments = Effect.fn("NormalizedPluginPageMaterialization.retireMissingJiraReleaseContainments")(function* (persistence, cryptoService, scope, acceptedEvents) {
1420
+ let relationshipCount = 0;
1421
+ for (const issue of acceptedEvents) {
1422
+ if (!hasAuthoritativeJiraFixVersions(issue)) continue;
1423
+ const source = yield* findEntity(persistence, scope, issue.vendorImmutableId);
1424
+ if (source === null) return yield* malformed("normalized-relationship-endpoint-missing", issue.eventId);
1425
+ const issueNodeId = yield* nodeIdFor(cryptoService, scope, issue.vendorImmutableId, issue.eventId);
1426
+ const neighborhood = yield* persistence.deliveryGraph.read(scope.workspaceId, {
1427
+ _tag: "nodeRelationships",
1428
+ nodeId: issueNodeId,
1429
+ limit: 500
1430
+ });
1431
+ if (neighborhood._tag !== "nodeRelationships") continue;
1432
+ if (neighborhood.value.truncated) return yield* malformed("normalized-jira-containment-neighborhood-truncated", issue.eventId);
1433
+ const currentRelationshipIds = new Set(yield* Effect.forEach(acceptedEvents.filter((event) => isReleaseContainmentForIssue(event, issue)), ({ relationshipId }) => stableUuid(cryptoService, materializationKey(scope, "relationship", relationshipId), issue.eventId).pipe(Effect.map(RelationshipId.make))));
1434
+ const removed = neighborhood.value.relationships.filter((relationship) => relationship.kind === "contains" && relationship.sourceNodeKind === "release" && relationship.targetNodeId === issueNodeId && relationship.targetNodeKind === "issue" && relationship.provenance._tag === "plugin" && relationship.provenance.pluginConnectionId === scope.pluginConnectionId && relationship.provenance.sourceEntityId === source.entityId && !currentRelationshipIds.has(relationship.relationshipId));
1435
+ if (removed.length === 0) continue;
1436
+ for (const previous of removed) {
1437
+ if (previous.lifecycle._tag === "rejected" || previous.lifecycle._tag === "superseded") continue;
1438
+ const receipt = yield* writeGraph(persistence, scope.workspaceId, {
1439
+ entityProjections: [],
1440
+ nodes: [],
1441
+ evidenceItems: [],
1442
+ evidenceClaims: [],
1443
+ relationships: [{
1444
+ ...previous,
1445
+ revision: LedgerRevision.make(previous.revision + 1),
1446
+ supersedesRevision: previous.revision,
1447
+ lifecycle: {
1448
+ _tag: "superseded",
1449
+ effectiveAt: issue.observedAt,
1450
+ reason: "No longer present in the latest Jira fixVersion observation."
1451
+ },
1452
+ provenance: {
1453
+ _tag: "plugin",
1454
+ pluginConnectionId: scope.pluginConnectionId,
1455
+ sourceEntityId: source.entityId,
1456
+ sourceEntityRevision: LedgerRevision.make(source.revision)
1457
+ },
1458
+ recordedBy: {
1459
+ _tag: "system",
1460
+ component: "normalized-plugin-page-materializer"
1461
+ },
1462
+ recordedAt: scope.committedAt
1463
+ }]
1464
+ }, issue.eventId);
1465
+ relationshipCount += receipt.relationshipCount;
1466
+ }
1467
+ }
1468
+ return relationshipCount;
1469
+ });
1470
+ /**
1471
+ * Commit one decoded page and all accepted canonical projections atomically.
1472
+ * The existing plugin checkpoint transaction nests as a savepoint; only its
1473
+ * newly accepted event identities cross the materialization seam.
1474
+ */
1475
+ var materializeNormalizedPluginPage = Effect.fn("NormalizedPluginPageMaterialization.materializePage")(function* (scope, page) {
1476
+ const cryptoService = yield* Crypto.Crypto;
1477
+ const persistence = yield* Persistence;
1478
+ return yield* persistence.transact(Effect.gen(function* () {
1479
+ if (scope.expectedAuthority !== void 0) yield* verifyPluginSynchronizationAuthority(persistence, scope.expectedAuthority);
1480
+ const committed = yield* persistence.pluginRuntime.commitNormalizedPageReceipt(scope.workspaceId, scope.pluginConnectionId, scope.providerId, scope.streamKey, scope.expectedRevision, page, scope.committedAt, scope.successfulHealth);
1481
+ const accepted = new Set(committed.acceptedEventIds);
1482
+ const events = page.events.filter(({ eventId }) => accepted.has(eventId));
1483
+ let entityProjectionCount = 0;
1484
+ let evidenceClaimCount = 0;
1485
+ let evidenceItemCount = 0;
1486
+ let nodeCount = 0;
1487
+ let personCount = 0;
1488
+ let relationshipCount = 0;
1489
+ let skippedEntityCount = 0;
1490
+ for (const event of events) {
1491
+ if (event._tag !== "UpsertPerson") continue;
1492
+ personCount += yield* materializePerson(persistence, cryptoService, scope, event);
1493
+ }
1494
+ for (const event of events) if (event._tag === "UpsertEntity") {
1495
+ if (event.entityType === "release") {
1496
+ nodeCount += (yield* materializeRelease(persistence, cryptoService, scope, event)).nodeCount;
1497
+ continue;
1498
+ }
1499
+ const receipt = yield* materializeUpsertEntity(persistence, cryptoService, scope, event);
1500
+ entityProjectionCount += receipt.entityProjectionCount;
1501
+ nodeCount += receipt.nodeCount;
1502
+ skippedEntityCount += receipt.skippedEntityCount;
1503
+ } else if (event._tag === "TombstoneEntity") entityProjectionCount += (yield* materializeTombstoneEntity(persistence, scope, event)).entityProjectionCount;
1504
+ for (const event of events) {
1505
+ if (event._tag !== "AppendEvidence") continue;
1506
+ const receipt = yield* materializeEvidence(persistence, cryptoService, scope, event);
1507
+ evidenceItemCount += receipt.evidenceItemCount;
1508
+ evidenceClaimCount += receipt.evidenceClaimCount;
1509
+ }
1510
+ for (const event of events) {
1511
+ if (event._tag !== "ProposeRelationship") continue;
1512
+ const receipt = yield* materializeRelationship(persistence, cryptoService, scope, event);
1513
+ nodeCount += receipt.nodeCount;
1514
+ relationshipCount += receipt.relationshipCount;
1515
+ }
1516
+ relationshipCount += yield* retireMissingJiraReleaseContainments(persistence, cryptoService, scope, events);
1517
+ if (events.length > 0) {
1518
+ const inference = yield* materializeRelationshipInference(persistence, (identity) => stableUuid(cryptoService, identity, "relationship-inference"), scope);
1519
+ evidenceClaimCount += inference.evidenceClaimCount;
1520
+ evidenceItemCount += inference.evidenceItemCount;
1521
+ nodeCount += inference.nodeCount;
1522
+ relationshipCount += inference.relationshipCount;
1523
+ }
1524
+ return {
1525
+ pageCommitted: committed.pageCommitted,
1526
+ acceptedEventCount: events.length,
1527
+ entityProjectionCount,
1528
+ evidenceClaimCount,
1529
+ evidenceItemCount,
1530
+ nodeCount,
1531
+ personCount,
1532
+ relationshipCount,
1533
+ skippedEntityCount
1534
+ };
1535
+ }));
1536
+ });
1537
+ //#endregion
1538
+ //#region src/server/application/manualPluginSynchronization.ts
1539
+ var MAXIMUM_PAGES_PER_INVOCATION = 100;
1540
+ var SYNCHRONIZATION_CLAIM_LIFETIME_MINUTES = 15;
1541
+ var SOURCE_UNAVAILABLE_OUTCOME = "source-unavailable";
1542
+ var SYNCHRONIZED_OUTCOME = "synchronized";
1543
+ var successfulHealthAt = (health, checkedAt) => health._tag === "healthy" ? {
1544
+ _tag: "healthy",
1545
+ checkedAt
1546
+ } : {
1547
+ ...health,
1548
+ checkedAt,
1549
+ retryAt: health.retryAt !== null && DateTime.Order(checkedAt, health.retryAt) <= 0 ? health.retryAt : null
1550
+ };
1551
+ /** Build a deterministic driver registry for production or fixture connections. */
1552
+ var makeManualPluginSyncDriverRegistry = (drivers) => {
1553
+ const byProvider = /* @__PURE__ */ new Map();
1554
+ for (const driver of drivers) byProvider.set(driver.providerId, driver);
1555
+ return { get: (providerId) => Option.fromNullishOr(byProvider.get(providerId)) };
1556
+ };
1557
+ var connectionSync = (connection, request) => connection.sync(request);
1558
+ /** Production drivers for first-party connections that currently negotiate synchronization. */
1559
+ var firstPartyManualPluginSyncDrivers = makeManualPluginSyncDriverRegistry([
1560
+ {
1561
+ providerId: "codecommit",
1562
+ streamKey: firstPartySyncStreamKey("codecommit"),
1563
+ sync: connectionSync
1564
+ },
1565
+ {
1566
+ providerId: "codepipeline",
1567
+ streamKey: firstPartySyncStreamKey("codepipeline"),
1568
+ sync: connectionSync
1569
+ },
1570
+ {
1571
+ providerId: "jira",
1572
+ streamKey: firstPartySyncStreamKey("jira"),
1573
+ sync: connectionSync
1574
+ },
1575
+ {
1576
+ providerId: "clockify",
1577
+ streamKey: firstPartySyncStreamKey("clockify"),
1578
+ sync: connectionSync
1579
+ },
1580
+ {
1581
+ providerId: "confluence",
1582
+ streamKey: firstPartySyncStreamKey("confluence"),
1583
+ sync: connectionSync
1584
+ }
1585
+ ]);
1586
+ var unavailable = () => new ApplicationServiceUnavailable({ retryAt: null });
1587
+ var mapPersistenceRead = (failure) => failure._tag === "RecordNotFoundError" ? new ApplicationResourceNotFound() : unavailable();
1588
+ var pluginFailureTags = /* @__PURE__ */ new Set([
1589
+ "PluginAuthenticationFailure",
1590
+ "PluginAuthorizationFailure",
1591
+ "PluginRateLimitFailure",
1592
+ "PluginTimeoutFailure",
1593
+ "PluginMalformedResponseFailure",
1594
+ "PluginOutageFailure",
1595
+ "PluginCancellationFailure",
1596
+ "PluginConflictFailure",
1597
+ "PluginUnsupportedCapabilityFailure",
1598
+ "PluginConfigurationFailure",
1599
+ "PluginUnknownOutcomeFailure"
1600
+ ]);
1601
+ var isPluginFailure = (failure) => Predicate.hasProperty(failure, "_tag") && typeof failure._tag === "string" && pluginFailureTags.has(failure._tag);
1602
+ var sourceFailure = (failure) => {
1603
+ if (isPluginFailure(failure)) return failure;
1604
+ if (Predicate.hasProperty(failure, "_tag") && failure._tag === "NormalizedPluginPageMaterializationError") return new PluginMalformedResponseFailure({
1605
+ operation: "manual-sync",
1606
+ diagnosticCode: "normalized-plugin-page-rejected"
1607
+ });
1608
+ if (Predicate.hasProperty(failure, "_tag") && failure._tag === "SourceIdentityMismatchError" && Predicate.hasProperty(failure, "recordKind") && (failure.recordKind === "plugin-sync-event" || failure.recordKind === "plugin-sync-page")) return new PluginMalformedResponseFailure({
1609
+ operation: "manual-sync",
1610
+ diagnosticCode: "plugin-sync-source-identity-conflict"
1611
+ });
1612
+ return null;
1613
+ };
1614
+ var safeFailureMessage = (failure) => {
1615
+ switch (failure._tag) {
1616
+ case "PluginAuthenticationFailure": return "Provider authentication failed.";
1617
+ case "PluginAuthorizationFailure": return "Provider permission was denied.";
1618
+ case "PluginRateLimitFailure": return "Provider rate limit was reached.";
1619
+ case "PluginTimeoutFailure": return "Provider request timed out.";
1620
+ case "PluginMalformedResponseFailure": return "Provider returned an invalid response.";
1621
+ case "PluginOutageFailure": return "Provider is temporarily unavailable.";
1622
+ case "PluginCancellationFailure": return "Provider synchronization was cancelled.";
1623
+ case "PluginConflictFailure": return "Provider state changed during synchronization.";
1624
+ case "PluginUnsupportedCapabilityFailure": return "Provider synchronization is not supported.";
1625
+ case "PluginConfigurationFailure": return "Provider configuration is incomplete.";
1626
+ case "PluginUnknownOutcomeFailure": return "Provider synchronization outcome is unknown.";
1627
+ }
1628
+ };
1629
+ var failureHealth = Effect.fn("ManualPluginSynchronization.failureHealth")(function* (failure, checkedAt) {
1630
+ return yield* Schema.decodeUnknownEffect(Schema.toType(PluginHealth))({
1631
+ _tag: "unavailable",
1632
+ checkedAt,
1633
+ failureClass: pluginFailureClass(failure),
1634
+ retryAt: failure._tag === "PluginRateLimitFailure" ? failure.retryAt : null,
1635
+ safeMessage: safeFailureMessage(failure)
1636
+ });
1637
+ });
1638
+ var stateFromAttemptState = (pluginConnectionId, providerId, streamKey, attemptState) => {
1639
+ const lastAttempt = attemptState.latestAttempt ?? void 0;
1640
+ const lastSuccess = attemptState.latestSynchronized ?? void 0;
1641
+ return {
1642
+ pluginConnectionId,
1643
+ providerId,
1644
+ streamKey,
1645
+ lastAttemptAt: lastAttempt?.startedAt ?? null,
1646
+ lastSuccessAt: lastSuccess?.completedAt ?? null,
1647
+ result: lastAttempt === void 0 ? "never" : lastAttempt.outcome === null ? "running" : lastAttempt.outcome,
1648
+ pagesCommitted: lastAttempt?.pagesCommitted ?? 0
1649
+ };
1650
+ };
1651
+ /** Build the bounded synchronization application over a scoped provider runtime map. */
1652
+ var makeManualPluginSynchronization = Effect.fn("ManualPluginSynchronization.make")(function* (connections, drivers = firstPartyManualPluginSyncDrivers) {
1653
+ const persistence = yield* Persistence;
1654
+ const wakeups = yield* DomainEventWakeups;
1655
+ const cryptoService = yield* Crypto.Crypto;
1656
+ const bind = Effect.fn("ManualPluginSynchronization.bind")(function* (input) {
1657
+ const connection = yield* persistence.pluginConnections.get(input.workspaceId, input.pluginConnectionId).pipe(Effect.mapError(mapPersistenceRead));
1658
+ const driver = drivers.get(connection.providerId);
1659
+ if (Option.isNone(driver)) return yield* new ApplicationInvalidRequest();
1660
+ const runtime = yield* persistence.pluginRuntime.getRuntime(input.workspaceId, input.pluginConnectionId).pipe(Effect.mapError(mapPersistenceRead));
1661
+ const descriptor = yield* Schema.decodeUnknownEffect(Schema.fromJsonString(NegotiatedPluginDescriptorV1))(runtime.descriptorJson).pipe(Effect.mapError(() => new ApplicationInvalidRequest()));
1662
+ if (!supportsFirstPartySynchronization(connection.providerId, descriptor)) return yield* new ApplicationInvalidRequest();
1663
+ const streamKey = yield* Schema.decodeUnknownEffect(PluginStreamKey)(driver.value.streamKey).pipe(Effect.mapError(() => new ApplicationInvalidRequest()));
1664
+ return {
1665
+ ...input,
1666
+ providerId: connection.providerId,
1667
+ driver: driver.value,
1668
+ streamKey
1669
+ };
1670
+ });
1671
+ const releaseSynchronization = Effect.fn("ManualPluginSynchronization.releaseSynchronization")(function* (claim) {
1672
+ yield* persistence.pluginRuntime.releaseSyncClaim(claim.workspaceId, claim.pluginConnectionId, claim.streamKey, claim.claimId).pipe(Effect.mapError(() => unavailable()));
1673
+ });
1674
+ const claimSynchronization = Effect.fn("ManualPluginSynchronization.claimSynchronization")(function* (bound) {
1675
+ const claimId = yield* cryptoService.randomUUIDv4.pipe(Effect.mapError(() => unavailable()));
1676
+ const claimedAt = DateTime.makeUnsafe(yield* Effect.clockWith((clock) => clock.currentTimeMillis));
1677
+ const expiresAt = DateTime.add(claimedAt, { minutes: SYNCHRONIZATION_CLAIM_LIFETIME_MINUTES });
1678
+ if (!(yield* persistence.pluginRuntime.claimSync(bound.workspaceId, bound.pluginConnectionId, bound.providerId, bound.streamKey, claimId, claimedAt, expiresAt).pipe(Effect.mapError(() => unavailable())))) return yield* unavailable();
1679
+ return {
1680
+ ...bound,
1681
+ claimId
1682
+ };
1683
+ });
1684
+ const stateFor = Effect.fn("ManualPluginSynchronization.stateFor")(function* (bound) {
1685
+ const attemptState = yield* persistence.pluginRuntime.getSyncAttemptState(bound.workspaceId, bound.pluginConnectionId, bound.streamKey).pipe(Effect.mapError(() => unavailable()));
1686
+ return stateFromAttemptState(bound.pluginConnectionId, bound.providerId, bound.streamKey, attemptState);
1687
+ });
1688
+ const readState = Effect.fn("ManualPluginSynchronization.state")(function* (input) {
1689
+ const bound = yield* bind(input);
1690
+ return yield* stateFor(bound);
1691
+ });
1692
+ const persistHealth = Effect.fn("ManualPluginSynchronization.persistHealth")(function* (bound, authority, health, failed) {
1693
+ const persisted = yield* persistence.transact(Effect.gen(function* () {
1694
+ yield* verifyPluginSynchronizationAuthority(persistence, authority);
1695
+ const runtime = yield* persistence.pluginRuntime.getRuntime(bound.workspaceId, bound.pluginConnectionId);
1696
+ yield* persistence.pluginRuntime.recordHealth(bound.workspaceId, bound.pluginConnectionId, runtime.revision, health, failed ? runtime.consecutiveFailures + 1 : 0);
1697
+ yield* appendPortfolioInvalidation({
1698
+ workspaceId: bound.workspaceId,
1699
+ pluginConnectionId: bound.pluginConnectionId,
1700
+ releaseId: null,
1701
+ occurredAt: health.checkedAt,
1702
+ reason: "plugin-health"
1703
+ }).pipe(Effect.provideService(Crypto.Crypto, cryptoService), Effect.provideService(Persistence, persistence));
1704
+ return true;
1705
+ })).pipe(Effect.catchTag("PluginConflictFailure", () => Effect.succeed(false)), Effect.mapError(() => unavailable()));
1706
+ if (persisted) yield* wakeups.notify(bound.workspaceId);
1707
+ return persisted;
1708
+ });
1709
+ const initialCheckpoint = Effect.fn("ManualPluginSynchronization.initialCheckpoint")(function* (bound) {
1710
+ const current = yield* Effect.result(persistence.pluginRuntime.getStream(bound.workspaceId, bound.pluginConnectionId, bound.streamKey));
1711
+ if (Result.isFailure(current)) {
1712
+ if (current.failure._tag === "RecordNotFoundError") return null;
1713
+ return yield* Effect.fail(current.failure);
1714
+ }
1715
+ return current.success.checkpointJson === null ? null : yield* Schema.decodeUnknownEffect(Schema.fromJsonString(PluginCheckpointV1))(current.success.checkpointJson);
1716
+ });
1717
+ const run = Effect.fn("ManualPluginSynchronization.run")(function* (bound, authority, connection, health) {
1718
+ const checkpoint = yield* initialCheckpoint(bound);
1719
+ const request = yield* Schema.decodeUnknownEffect(PluginSyncRequestV1)({
1720
+ streamKey: bound.streamKey,
1721
+ checkpoint
1722
+ });
1723
+ const initialStream = yield* Effect.result(persistence.pluginRuntime.getStream(bound.workspaceId, bound.pluginConnectionId, bound.streamKey));
1724
+ const revision = Result.isSuccess(initialStream) ? initialStream.success.revision : 0;
1725
+ return yield* Stream.runFoldEffect(bound.driver.sync(connection, request).pipe(Stream.take(MAXIMUM_PAGES_PER_INVOCATION)), () => ({
1726
+ health,
1727
+ isTerminal: false,
1728
+ pagesSeen: 0,
1729
+ pagesCommitted: 0,
1730
+ revision
1731
+ }), (state, page) => Effect.gen(function* () {
1732
+ if (state.isTerminal) return yield* new PluginMalformedResponseFailure({
1733
+ operation: "manual-sync",
1734
+ diagnosticCode: "manual-sync-page-after-terminal"
1735
+ });
1736
+ const committedAt = DateTime.makeUnsafe(yield* Clock.currentTimeMillis);
1737
+ const successfulHealth = successfulHealthAt(state.health, committedAt);
1738
+ const receipt = yield* materializeNormalizedPluginPage({
1739
+ workspaceId: bound.workspaceId,
1740
+ pluginConnectionId: bound.pluginConnectionId,
1741
+ providerId: bound.providerId,
1742
+ streamKey: bound.streamKey,
1743
+ expectedRevision: state.revision,
1744
+ committedAt,
1745
+ successfulHealth,
1746
+ expectedAuthority: authority
1747
+ }, page).pipe(Effect.provideService(Crypto.Crypto, cryptoService), Effect.provideService(Persistence, persistence));
1748
+ const pagesSeen = state.pagesSeen + 1;
1749
+ return {
1750
+ health: successfulHealth,
1751
+ isTerminal: !page.hasMore,
1752
+ pagesSeen,
1753
+ pagesCommitted: state.pagesCommitted + (receipt.pageCommitted ? 1 : 0),
1754
+ revision: state.revision + (receipt.pageCommitted ? 1 : 0)
1755
+ };
1756
+ }));
1757
+ });
1758
+ const synchronizeBound = Effect.fn("ManualPluginSynchronization.synchronizeBound")(function* (input, bound) {
1759
+ const { authority, connection: connectionRecord } = yield* capturePluginSynchronizationAuthority(persistence, bound.workspaceId, bound.pluginConnectionId).pipe(Effect.mapError(mapPersistenceRead));
1760
+ if (!connectionRecord.isEnabled) return yield* new ApplicationInvalidRequest();
1761
+ const startedAt = DateTime.makeUnsafe(yield* Effect.clockWith((clock) => clock.currentTimeMillis));
1762
+ const attempt = yield* persistence.pluginRuntime.beginSyncAttempt(bound.workspaceId, bound.pluginConnectionId, bound.providerId, bound.streamKey, startedAt).pipe(Effect.mapError(() => unavailable()));
1763
+ const synchronized = yield* Effect.result(Effect.scoped(Effect.flatMap(connections.contextEffect({
1764
+ workspaceId: bound.workspaceId,
1765
+ pluginConnectionId: bound.pluginConnectionId
1766
+ }), (context) => Effect.gen(function* () {
1767
+ const connection = Context.get(context, PluginConnection);
1768
+ const health = yield* connection.health;
1769
+ if (health._tag === "unavailable" || health._tag === "disabled") return health;
1770
+ const completed = yield* run(bound, authority, connection, health);
1771
+ if (!completed.isTerminal && (completed.pagesSeen < MAXIMUM_PAGES_PER_INVOCATION || completed.pagesCommitted === 0)) return yield* new PluginMalformedResponseFailure({
1772
+ operation: "manual-sync",
1773
+ diagnosticCode: "manual-sync-terminal-page-missing"
1774
+ });
1775
+ return completed.health;
1776
+ }).pipe(Effect.provide(context)))));
1777
+ const outcome = yield* Effect.gen(function* () {
1778
+ if (Result.isSuccess(synchronized)) {
1779
+ const health = synchronized.success;
1780
+ const sourceUnavailable = health._tag === "unavailable" || health._tag === "disabled";
1781
+ const healthPersisted = yield* persistHealth(bound, authority, health, sourceUnavailable);
1782
+ return sourceUnavailable || !healthPersisted ? SOURCE_UNAVAILABLE_OUTCOME : SYNCHRONIZED_OUTCOME;
1783
+ }
1784
+ const failure = sourceFailure(synchronized.failure);
1785
+ if (failure === null) return yield* unavailable();
1786
+ const health = yield* failureHealth(failure, DateTime.makeUnsafe(yield* Effect.clockWith((clock) => clock.currentTimeMillis))).pipe(Effect.mapError(() => unavailable()));
1787
+ yield* persistHealth(bound, authority, health, true);
1788
+ return SOURCE_UNAVAILABLE_OUTCOME;
1789
+ });
1790
+ const completedAt = DateTime.makeUnsafe(yield* Effect.clockWith((clock) => clock.currentTimeMillis));
1791
+ yield* persistence.pluginRuntime.completeSyncAttempt(bound.workspaceId, bound.pluginConnectionId, bound.streamKey, attempt.attemptSequence, outcome, completedAt).pipe(Effect.mapError(() => unavailable()));
1792
+ return yield* readState(input);
1793
+ });
1794
+ return {
1795
+ state: readState,
1796
+ synchronize: Effect.fn("ManualPluginSynchronization.synchronize")(function* (input) {
1797
+ const bound = yield* bind(input);
1798
+ return yield* Effect.acquireUseRelease(claimSynchronization(bound), () => synchronizeBound(input, bound), releaseSynchronization);
1799
+ })
1800
+ };
1801
+ });
1802
+ //#endregion
1803
+ export { firstPartyManualPluginSyncDrivers, makeManualPluginSyncDriverRegistry, makeManualPluginSynchronization };
1804
+
1805
+ //# sourceMappingURL=manualPluginSynchronization-C0aHB4UM.js.map