@pattern-stack/codegen 0.15.1 → 0.15.2

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 (521) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/dist/chunk-24CWKBK5.js +94 -0
  3. package/dist/chunk-24CWKBK5.js.map +1 -0
  4. package/dist/chunk-2E224ZSN.js +20 -0
  5. package/dist/chunk-2E224ZSN.js.map +1 -0
  6. package/dist/chunk-2FTZLDBP.js +179 -0
  7. package/dist/chunk-2FTZLDBP.js.map +1 -0
  8. package/dist/chunk-2N4UG4VD.js +20 -0
  9. package/dist/chunk-2N4UG4VD.js.map +1 -0
  10. package/dist/chunk-2TVVBC53.js +92 -0
  11. package/dist/chunk-2TVVBC53.js.map +1 -0
  12. package/dist/chunk-2VHZ7EKC.js +37 -0
  13. package/dist/chunk-2VHZ7EKC.js.map +1 -0
  14. package/dist/chunk-32BMMV4H.js +109 -0
  15. package/dist/chunk-32BMMV4H.js.map +1 -0
  16. package/dist/chunk-32DOFN3T.js +4042 -0
  17. package/dist/chunk-32DOFN3T.js.map +1 -0
  18. package/dist/chunk-36U5UGIO.js +107 -0
  19. package/dist/chunk-36U5UGIO.js.map +1 -0
  20. package/dist/chunk-3CJFPU6Q.js +14 -0
  21. package/dist/chunk-3CJFPU6Q.js.map +1 -0
  22. package/dist/chunk-3NMCDN7L.js +90 -0
  23. package/dist/chunk-3NMCDN7L.js.map +1 -0
  24. package/dist/chunk-3SZFUTXE.js +62 -0
  25. package/dist/chunk-3SZFUTXE.js.map +1 -0
  26. package/dist/chunk-4DOJBQTP.js +117 -0
  27. package/dist/chunk-4DOJBQTP.js.map +1 -0
  28. package/dist/chunk-4JLJYWJC.js +308 -0
  29. package/dist/chunk-4JLJYWJC.js.map +1 -0
  30. package/dist/chunk-4KNXX6TI.js +29 -0
  31. package/dist/chunk-4KNXX6TI.js.map +1 -0
  32. package/dist/chunk-4LH67P4U.js +17 -0
  33. package/dist/chunk-4LH67P4U.js.map +1 -0
  34. package/dist/chunk-4MVGAMUA.js +40 -0
  35. package/dist/chunk-4MVGAMUA.js.map +1 -0
  36. package/dist/chunk-4OMHBMZJ.js +75 -0
  37. package/dist/chunk-4OMHBMZJ.js.map +1 -0
  38. package/dist/chunk-4RFHUZXU.js +635 -0
  39. package/dist/chunk-4RFHUZXU.js.map +1 -0
  40. package/dist/chunk-5A432NZJ.js +7 -0
  41. package/dist/chunk-5A432NZJ.js.map +1 -0
  42. package/dist/chunk-5Y7W3XR6.js +356 -0
  43. package/dist/chunk-5Y7W3XR6.js.map +1 -0
  44. package/dist/chunk-6DWFJNIK.js +15 -0
  45. package/dist/chunk-6DWFJNIK.js.map +1 -0
  46. package/dist/chunk-6I7ULIN6.js +15 -0
  47. package/dist/chunk-6I7ULIN6.js.map +1 -0
  48. package/dist/chunk-6XY6ZMMD.js +25 -0
  49. package/dist/chunk-6XY6ZMMD.js.map +1 -0
  50. package/dist/chunk-7B3RYX45.js +63 -0
  51. package/dist/chunk-7B3RYX45.js.map +1 -0
  52. package/dist/chunk-7C3FOSDI.js +1 -0
  53. package/dist/chunk-7C3FOSDI.js.map +1 -0
  54. package/dist/chunk-7KOW6PU6.js +59 -0
  55. package/dist/chunk-7KOW6PU6.js.map +1 -0
  56. package/dist/chunk-7LKAMLV4.js +92 -0
  57. package/dist/chunk-7LKAMLV4.js.map +1 -0
  58. package/dist/chunk-7RELQJIN.js +22 -0
  59. package/dist/chunk-7RELQJIN.js.map +1 -0
  60. package/dist/chunk-AHV4GDYM.js +63 -0
  61. package/dist/chunk-AHV4GDYM.js.map +1 -0
  62. package/dist/chunk-AQFQ4BYM.js +81 -0
  63. package/dist/chunk-AQFQ4BYM.js.map +1 -0
  64. package/dist/chunk-AS3NAZB6.js +14 -0
  65. package/dist/chunk-AS3NAZB6.js.map +1 -0
  66. package/dist/chunk-BGULBWKJ.js +88 -0
  67. package/dist/chunk-BGULBWKJ.js.map +1 -0
  68. package/dist/chunk-BIO6F7YI.js +17 -0
  69. package/dist/chunk-BIO6F7YI.js.map +1 -0
  70. package/dist/chunk-BOPZWRJK.js +36 -0
  71. package/dist/chunk-BOPZWRJK.js.map +1 -0
  72. package/dist/chunk-BPARRK6F.js +14 -0
  73. package/dist/chunk-BPARRK6F.js.map +1 -0
  74. package/dist/chunk-CO6LUM72.js +59 -0
  75. package/dist/chunk-CO6LUM72.js.map +1 -0
  76. package/dist/chunk-COGHTKXY.js +84 -0
  77. package/dist/chunk-COGHTKXY.js.map +1 -0
  78. package/dist/chunk-DCCZB4UC.js +100 -0
  79. package/dist/chunk-DCCZB4UC.js.map +1 -0
  80. package/dist/chunk-DKKFTHHI.js +53 -0
  81. package/dist/chunk-DKKFTHHI.js.map +1 -0
  82. package/dist/chunk-DV4RV2DC.js +59 -0
  83. package/dist/chunk-DV4RV2DC.js.map +1 -0
  84. package/dist/chunk-EDKJU5BO.js +11 -0
  85. package/dist/chunk-EDKJU5BO.js.map +1 -0
  86. package/dist/chunk-EO2QPOKH.js +116 -0
  87. package/dist/chunk-EO2QPOKH.js.map +1 -0
  88. package/dist/chunk-EOLLMEAH.js +155 -0
  89. package/dist/chunk-EOLLMEAH.js.map +1 -0
  90. package/dist/chunk-EWYCWP4H.js +14 -0
  91. package/dist/chunk-EWYCWP4H.js.map +1 -0
  92. package/dist/chunk-EXVDJMIY.js +33 -0
  93. package/dist/chunk-EXVDJMIY.js.map +1 -0
  94. package/dist/chunk-FASRXRX5.js +19 -0
  95. package/dist/chunk-FASRXRX5.js.map +1 -0
  96. package/dist/chunk-FI34KYZ5.js +1 -0
  97. package/dist/chunk-FI34KYZ5.js.map +1 -0
  98. package/dist/chunk-FN2PYDPP.js +1 -0
  99. package/dist/chunk-FN2PYDPP.js.map +1 -0
  100. package/dist/chunk-GM3RMJIJ.js +92 -0
  101. package/dist/chunk-GM3RMJIJ.js.map +1 -0
  102. package/dist/chunk-GYGNEQSC.js +9 -0
  103. package/dist/chunk-GYGNEQSC.js.map +1 -0
  104. package/dist/chunk-H5NH7KPE.js +21 -0
  105. package/dist/chunk-H5NH7KPE.js.map +1 -0
  106. package/dist/chunk-HNWZFNKP.js +168 -0
  107. package/dist/chunk-HNWZFNKP.js.map +1 -0
  108. package/dist/chunk-HUH73XGI.js +1 -0
  109. package/dist/chunk-HUH73XGI.js.map +1 -0
  110. package/dist/chunk-I6MG4M3F.js +201 -0
  111. package/dist/chunk-I6MG4M3F.js.map +1 -0
  112. package/dist/chunk-I6MVCB5A.js +39 -0
  113. package/dist/chunk-I6MVCB5A.js.map +1 -0
  114. package/dist/chunk-IBGER4YK.js +12 -0
  115. package/dist/chunk-IBGER4YK.js.map +1 -0
  116. package/dist/chunk-IF5I3DAA.js +92 -0
  117. package/dist/chunk-IF5I3DAA.js.map +1 -0
  118. package/dist/chunk-IP4OO26U.js +54 -0
  119. package/dist/chunk-IP4OO26U.js.map +1 -0
  120. package/dist/chunk-IWAOY6KC.js +1 -0
  121. package/dist/chunk-IWAOY6KC.js.map +1 -0
  122. package/dist/chunk-J37YWU7Y.js +19 -0
  123. package/dist/chunk-J37YWU7Y.js.map +1 -0
  124. package/dist/chunk-J6KZS54B.js +269 -0
  125. package/dist/chunk-J6KZS54B.js.map +1 -0
  126. package/dist/chunk-J6MN42LG.js +19 -0
  127. package/dist/chunk-J6MN42LG.js.map +1 -0
  128. package/dist/chunk-JRQO2IOF.js +65 -0
  129. package/dist/chunk-JRQO2IOF.js.map +1 -0
  130. package/dist/chunk-JRVNVKN6.js +212 -0
  131. package/dist/chunk-JRVNVKN6.js.map +1 -0
  132. package/dist/chunk-JWNHNUYL.js +96 -0
  133. package/dist/chunk-JWNHNUYL.js.map +1 -0
  134. package/dist/chunk-K2I6XIK5.js +122 -0
  135. package/dist/chunk-K2I6XIK5.js.map +1 -0
  136. package/dist/chunk-KMZCQASO.js +111 -0
  137. package/dist/chunk-KMZCQASO.js.map +1 -0
  138. package/dist/chunk-KVOWSC5S.js +1 -0
  139. package/dist/chunk-KVOWSC5S.js.map +1 -0
  140. package/dist/chunk-KYR3B3OW.js +79 -0
  141. package/dist/chunk-KYR3B3OW.js.map +1 -0
  142. package/dist/chunk-L3LZWWSX.js +61 -0
  143. package/dist/chunk-L3LZWWSX.js.map +1 -0
  144. package/dist/chunk-L4SDDEEU.js +1 -0
  145. package/dist/chunk-L4SDDEEU.js.map +1 -0
  146. package/dist/chunk-L6FTY45T.js +13 -0
  147. package/dist/chunk-L6FTY45T.js.map +1 -0
  148. package/dist/chunk-L7BNNRGI.js +134 -0
  149. package/dist/chunk-L7BNNRGI.js.map +1 -0
  150. package/dist/chunk-LG57S2SC.js +150 -0
  151. package/dist/chunk-LG57S2SC.js.map +1 -0
  152. package/dist/chunk-M6QLSLPO.js +97 -0
  153. package/dist/chunk-M6QLSLPO.js.map +1 -0
  154. package/dist/chunk-MZ6GV4YF.js +21 -0
  155. package/dist/chunk-MZ6GV4YF.js.map +1 -0
  156. package/dist/chunk-N5OTOWTP.js +55 -0
  157. package/dist/chunk-N5OTOWTP.js.map +1 -0
  158. package/dist/chunk-NN7XZEGF.js +14 -0
  159. package/dist/chunk-NN7XZEGF.js.map +1 -0
  160. package/dist/chunk-NPFPZ2HO.js +13 -0
  161. package/dist/chunk-NPFPZ2HO.js.map +1 -0
  162. package/dist/chunk-NXXDZ6ZF.js +42 -0
  163. package/dist/chunk-NXXDZ6ZF.js.map +1 -0
  164. package/dist/chunk-NYBCQZC7.js +11 -0
  165. package/dist/chunk-NYBCQZC7.js.map +1 -0
  166. package/dist/chunk-OFRRBC7M.js +78 -0
  167. package/dist/chunk-OFRRBC7M.js.map +1 -0
  168. package/dist/chunk-OGIZXGPY.js +222 -0
  169. package/dist/chunk-OGIZXGPY.js.map +1 -0
  170. package/dist/chunk-OKXZ63IA.js +168 -0
  171. package/dist/chunk-OKXZ63IA.js.map +1 -0
  172. package/dist/chunk-OSQRXVG2.js +58 -0
  173. package/dist/chunk-OSQRXVG2.js.map +1 -0
  174. package/dist/chunk-OTDN3OUQ.js +215 -0
  175. package/dist/chunk-OTDN3OUQ.js.map +1 -0
  176. package/dist/chunk-OZZJDRGW.js +122 -0
  177. package/dist/chunk-OZZJDRGW.js.map +1 -0
  178. package/dist/chunk-PNZSGAB2.js +114 -0
  179. package/dist/chunk-PNZSGAB2.js.map +1 -0
  180. package/dist/chunk-PRWIX6UW.js +21 -0
  181. package/dist/chunk-PRWIX6UW.js.map +1 -0
  182. package/dist/chunk-PSXUNOVU.js +7 -0
  183. package/dist/chunk-PSXUNOVU.js.map +1 -0
  184. package/dist/chunk-QLTJSCE6.js +44 -0
  185. package/dist/chunk-QLTJSCE6.js.map +1 -0
  186. package/dist/chunk-RC23QROE.js +447 -0
  187. package/dist/chunk-RC23QROE.js.map +1 -0
  188. package/dist/chunk-RFH7N6EP.js +36 -0
  189. package/dist/chunk-RFH7N6EP.js.map +1 -0
  190. package/dist/chunk-RHVN6NA7.js +134 -0
  191. package/dist/chunk-RHVN6NA7.js.map +1 -0
  192. package/dist/chunk-S7C6TIIF.js +21 -0
  193. package/dist/chunk-S7C6TIIF.js.map +1 -0
  194. package/dist/chunk-SNQ3TOWP.js +20 -0
  195. package/dist/chunk-SNQ3TOWP.js.map +1 -0
  196. package/dist/chunk-SOVM2VEK.js +14 -0
  197. package/dist/chunk-SOVM2VEK.js.map +1 -0
  198. package/dist/chunk-SQDOBLBP.js +13 -0
  199. package/dist/chunk-SQDOBLBP.js.map +1 -0
  200. package/dist/chunk-SR7F3TJY.js +130 -0
  201. package/dist/chunk-SR7F3TJY.js.map +1 -0
  202. package/dist/chunk-SZVPIHWE.js +129 -0
  203. package/dist/chunk-SZVPIHWE.js.map +1 -0
  204. package/dist/chunk-T4BIIU5E.js +89 -0
  205. package/dist/chunk-T4BIIU5E.js.map +1 -0
  206. package/dist/chunk-T6C4LFLC.js +112 -0
  207. package/dist/chunk-T6C4LFLC.js.map +1 -0
  208. package/dist/chunk-TNXH7BJS.js +48 -0
  209. package/dist/chunk-TNXH7BJS.js.map +1 -0
  210. package/dist/chunk-U64T4YZE.js +9 -0
  211. package/dist/chunk-U64T4YZE.js.map +1 -0
  212. package/dist/chunk-UQ5EHOH2.js +39 -0
  213. package/dist/chunk-UQ5EHOH2.js.map +1 -0
  214. package/dist/chunk-UTN4GBPQ.js +1 -0
  215. package/dist/chunk-UTN4GBPQ.js.map +1 -0
  216. package/dist/chunk-V4AF6DI4.js +16 -0
  217. package/dist/chunk-V4AF6DI4.js.map +1 -0
  218. package/dist/chunk-W72PRNJY.js +126 -0
  219. package/dist/chunk-W72PRNJY.js.map +1 -0
  220. package/dist/chunk-WEVWJKOW.js +81 -0
  221. package/dist/chunk-WEVWJKOW.js.map +1 -0
  222. package/dist/chunk-WL67FZGF.js +21 -0
  223. package/dist/chunk-WL67FZGF.js.map +1 -0
  224. package/dist/chunk-WPXNN6QS.js +290 -0
  225. package/dist/chunk-WPXNN6QS.js.map +1 -0
  226. package/dist/chunk-WRUUSZDJ.js +29 -0
  227. package/dist/chunk-WRUUSZDJ.js.map +1 -0
  228. package/dist/chunk-X2GMTYPA.js +50 -0
  229. package/dist/chunk-X2GMTYPA.js.map +1 -0
  230. package/dist/chunk-XCEI7NUH.js +41 -0
  231. package/dist/chunk-XCEI7NUH.js.map +1 -0
  232. package/dist/chunk-Y7GDG744.js +88 -0
  233. package/dist/chunk-Y7GDG744.js.map +1 -0
  234. package/dist/chunk-Y7RRSEOC.js +9 -0
  235. package/dist/chunk-Y7RRSEOC.js.map +1 -0
  236. package/dist/chunk-YPWODKD5.js +184 -0
  237. package/dist/chunk-YPWODKD5.js.map +1 -0
  238. package/dist/chunk-YSLTTQLC.js +25 -0
  239. package/dist/chunk-YSLTTQLC.js.map +1 -0
  240. package/dist/chunk-YTN6BKWA.js +121 -0
  241. package/dist/chunk-YTN6BKWA.js.map +1 -0
  242. package/dist/chunk-Z7PQCAVK.js +200 -0
  243. package/dist/chunk-Z7PQCAVK.js.map +1 -0
  244. package/dist/chunk-ZUKFQL6E.js +47 -0
  245. package/dist/chunk-ZUKFQL6E.js.map +1 -0
  246. package/dist/chunk-ZUMULSEQ.js +1 -0
  247. package/dist/chunk-ZUMULSEQ.js.map +1 -0
  248. package/dist/runtime/analytics/index.js +8 -41
  249. package/dist/runtime/analytics/index.js.map +1 -1
  250. package/dist/runtime/analytics/types.js +8 -41
  251. package/dist/runtime/analytics/types.js.map +1 -1
  252. package/dist/runtime/base-classes/activity-entity-repository.js +6 -312
  253. package/dist/runtime/base-classes/activity-entity-repository.js.map +1 -1
  254. package/dist/runtime/base-classes/activity-entity-service.js +6 -212
  255. package/dist/runtime/base-classes/activity-entity-service.js.map +1 -1
  256. package/dist/runtime/base-classes/base-read-use-cases.js +5 -27
  257. package/dist/runtime/base-classes/base-read-use-cases.js.map +1 -1
  258. package/dist/runtime/base-classes/base-repository.js +5 -277
  259. package/dist/runtime/base-classes/base-repository.js.map +1 -1
  260. package/dist/runtime/base-classes/base-service.js +5 -184
  261. package/dist/runtime/base-classes/base-service.js.map +1 -1
  262. package/dist/runtime/base-classes/index.js +59 -1076
  263. package/dist/runtime/base-classes/index.js.map +1 -1
  264. package/dist/runtime/base-classes/integrated-entity-repository.js +6 -486
  265. package/dist/runtime/base-classes/integrated-entity-repository.js.map +1 -1
  266. package/dist/runtime/base-classes/integrated-entity-service.js +6 -213
  267. package/dist/runtime/base-classes/integrated-entity-service.js.map +1 -1
  268. package/dist/runtime/base-classes/junction-integration-repository.js +8 -448
  269. package/dist/runtime/base-classes/junction-integration-repository.js.map +1 -1
  270. package/dist/runtime/base-classes/knowledge-entity-repository.js +6 -283
  271. package/dist/runtime/base-classes/knowledge-entity-repository.js.map +1 -1
  272. package/dist/runtime/base-classes/knowledge-entity-service.js +6 -190
  273. package/dist/runtime/base-classes/knowledge-entity-service.js.map +1 -1
  274. package/dist/runtime/base-classes/lifecycle-events.js +8 -70
  275. package/dist/runtime/base-classes/lifecycle-events.js.map +1 -1
  276. package/dist/runtime/base-classes/metadata-entity-repository.js +6 -330
  277. package/dist/runtime/base-classes/metadata-entity-repository.js.map +1 -1
  278. package/dist/runtime/base-classes/metadata-entity-service.js +6 -212
  279. package/dist/runtime/base-classes/metadata-entity-service.js.map +1 -1
  280. package/dist/runtime/base-classes/tenant-context.js +10 -36
  281. package/dist/runtime/base-classes/tenant-context.js.map +1 -1
  282. package/dist/runtime/base-classes/with-analytics.js +4 -7
  283. package/dist/runtime/base-classes/with-analytics.js.map +1 -1
  284. package/dist/runtime/constants/tokens.js +5 -3
  285. package/dist/runtime/constants/tokens.js.map +1 -1
  286. package/dist/runtime/eav-helpers.js +2 -0
  287. package/dist/runtime/eav-helpers.js.map +1 -1
  288. package/dist/runtime/pipes/zod-validation.pipe.js +3 -10
  289. package/dist/runtime/pipes/zod-validation.pipe.js.map +1 -1
  290. package/dist/runtime/shared/openapi/error-response.dto.js +5 -8
  291. package/dist/runtime/shared/openapi/error-response.dto.js.map +1 -1
  292. package/dist/runtime/shared/openapi/errors.js +5 -19
  293. package/dist/runtime/shared/openapi/errors.js.map +1 -1
  294. package/dist/runtime/shared/openapi/index.js +15 -106
  295. package/dist/runtime/shared/openapi/index.js.map +1 -1
  296. package/dist/runtime/shared/openapi/registry.js +6 -103
  297. package/dist/runtime/shared/openapi/registry.js.map +1 -1
  298. package/dist/runtime/shared/openapi/registry.tokens.js +4 -2
  299. package/dist/runtime/shared/openapi/registry.tokens.js.map +1 -1
  300. package/dist/runtime/subsystems/analytics/analytics.module.js +8 -117
  301. package/dist/runtime/subsystems/analytics/analytics.module.js.map +1 -1
  302. package/dist/runtime/subsystems/analytics/analytics.tokens.js +7 -8
  303. package/dist/runtime/subsystems/analytics/analytics.tokens.js.map +1 -1
  304. package/dist/runtime/subsystems/analytics/cube-backend.js +6 -71
  305. package/dist/runtime/subsystems/analytics/cube-backend.js.map +1 -1
  306. package/dist/runtime/subsystems/analytics/index.js +16 -117
  307. package/dist/runtime/subsystems/analytics/index.js.map +1 -1
  308. package/dist/runtime/subsystems/analytics/noop-backend.js +4 -21
  309. package/dist/runtime/subsystems/analytics/noop-backend.js.map +1 -1
  310. package/dist/runtime/subsystems/auth/auth-oauth-state.schema.js +4 -8
  311. package/dist/runtime/subsystems/auth/auth-oauth-state.schema.js.map +1 -1
  312. package/dist/runtime/subsystems/auth/auth.module.js +12 -359
  313. package/dist/runtime/subsystems/auth/auth.module.js.map +1 -1
  314. package/dist/runtime/subsystems/auth/auth.tokens.js +12 -13
  315. package/dist/runtime/subsystems/auth/auth.tokens.js.map +1 -1
  316. package/dist/runtime/subsystems/auth/backends/encryption-key/env.js +4 -49
  317. package/dist/runtime/subsystems/auth/backends/encryption-key/env.js.map +1 -1
  318. package/dist/runtime/subsystems/auth/backends/state-store.drizzle-backend.js +6 -64
  319. package/dist/runtime/subsystems/auth/backends/state-store.drizzle-backend.js.map +1 -1
  320. package/dist/runtime/subsystems/auth/backends/state-store.memory-backend.js +5 -47
  321. package/dist/runtime/subsystems/auth/backends/state-store.memory-backend.js.map +1 -1
  322. package/dist/runtime/subsystems/auth/controllers/auth.controller.js +5 -139
  323. package/dist/runtime/subsystems/auth/controllers/auth.controller.js.map +1 -1
  324. package/dist/runtime/subsystems/auth/index.js +53 -542
  325. package/dist/runtime/subsystems/auth/index.js.map +1 -1
  326. package/dist/runtime/subsystems/auth/middleware/requester-context.js +9 -65
  327. package/dist/runtime/subsystems/auth/middleware/requester-context.js.map +1 -1
  328. package/dist/runtime/subsystems/auth/protocols/oauth-state-store.js +4 -9
  329. package/dist/runtime/subsystems/auth/protocols/oauth-state-store.js.map +1 -1
  330. package/dist/runtime/subsystems/auth/runtime/connection-broken.error.js +4 -15
  331. package/dist/runtime/subsystems/auth/runtime/connection-broken.error.js.map +1 -1
  332. package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.js +5 -104
  333. package/dist/runtime/subsystems/auth/runtime/oauth2-refresh.strategy.js.map +1 -1
  334. package/dist/runtime/subsystems/auth/runtime/session-expired.error.js +5 -16
  335. package/dist/runtime/subsystems/auth/runtime/session-expired.error.js.map +1 -1
  336. package/dist/runtime/subsystems/auth/runtime/with-auth-retry.js +5 -29
  337. package/dist/runtime/subsystems/auth/runtime/with-auth-retry.js.map +1 -1
  338. package/dist/runtime/subsystems/bridge/assert-tenant-id.js +5 -18
  339. package/dist/runtime/subsystems/bridge/assert-tenant-id.js.map +1 -1
  340. package/dist/runtime/subsystems/bridge/bridge-delivery-handler.js +12 -184
  341. package/dist/runtime/subsystems/bridge/bridge-delivery-handler.js.map +1 -1
  342. package/dist/runtime/subsystems/bridge/bridge-delivery.drizzle-backend.js +10 -448
  343. package/dist/runtime/subsystems/bridge/bridge-delivery.drizzle-backend.js.map +1 -1
  344. package/dist/runtime/subsystems/bridge/bridge-delivery.memory-backend.js +5 -126
  345. package/dist/runtime/subsystems/bridge/bridge-delivery.memory-backend.js.map +1 -1
  346. package/dist/runtime/subsystems/bridge/bridge-delivery.schema.js +6 -308
  347. package/dist/runtime/subsystems/bridge/bridge-delivery.schema.js.map +1 -1
  348. package/dist/runtime/subsystems/bridge/bridge-errors.js +6 -35
  349. package/dist/runtime/subsystems/bridge/bridge-errors.js.map +1 -1
  350. package/dist/runtime/subsystems/bridge/bridge-outbox-drain-hook.js +14 -606
  351. package/dist/runtime/subsystems/bridge/bridge-outbox-drain-hook.js.map +1 -1
  352. package/dist/runtime/subsystems/bridge/bridge.module.js +35 -3476
  353. package/dist/runtime/subsystems/bridge/bridge.module.js.map +1 -1
  354. package/dist/runtime/subsystems/bridge/bridge.tokens.js +9 -7
  355. package/dist/runtime/subsystems/bridge/bridge.tokens.js.map +1 -1
  356. package/dist/runtime/subsystems/bridge/event-flow.service.js +11 -137
  357. package/dist/runtime/subsystems/bridge/event-flow.service.js.map +1 -1
  358. package/dist/runtime/subsystems/bridge/generated/registry.js +4 -2
  359. package/dist/runtime/subsystems/bridge/generated/registry.js.map +1 -1
  360. package/dist/runtime/subsystems/bridge/index.js +60 -3470
  361. package/dist/runtime/subsystems/bridge/index.js.map +1 -1
  362. package/dist/runtime/subsystems/bridge/reserved-pools.js +4 -6
  363. package/dist/runtime/subsystems/bridge/reserved-pools.js.map +1 -1
  364. package/dist/runtime/subsystems/cache/cache.drizzle-backend.js +10 -133
  365. package/dist/runtime/subsystems/cache/cache.drizzle-backend.js.map +1 -1
  366. package/dist/runtime/subsystems/cache/cache.memory-backend.js +6 -101
  367. package/dist/runtime/subsystems/cache/cache.memory-backend.js.map +1 -1
  368. package/dist/runtime/subsystems/cache/cache.module.js +10 -278
  369. package/dist/runtime/subsystems/cache/cache.module.js.map +1 -1
  370. package/dist/runtime/subsystems/cache/cache.schema.js +4 -14
  371. package/dist/runtime/subsystems/cache/cache.schema.js.map +1 -1
  372. package/dist/runtime/subsystems/cache/cache.tokens.js +6 -7
  373. package/dist/runtime/subsystems/cache/cache.tokens.js.map +1 -1
  374. package/dist/runtime/subsystems/cache/index.js +20 -278
  375. package/dist/runtime/subsystems/cache/index.js.map +1 -1
  376. package/dist/runtime/subsystems/events/domain-events.schema.js +3 -72
  377. package/dist/runtime/subsystems/events/domain-events.schema.js.map +1 -1
  378. package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js +9 -413
  379. package/dist/runtime/subsystems/events/event-bus.drizzle-backend.js.map +1 -1
  380. package/dist/runtime/subsystems/events/event-bus.memory-backend.js +7 -235
  381. package/dist/runtime/subsystems/events/event-bus.memory-backend.js.map +1 -1
  382. package/dist/runtime/subsystems/events/event-bus.redis-backend.js +8 -20
  383. package/dist/runtime/subsystems/events/event-bus.redis-backend.js.map +1 -1
  384. package/dist/runtime/subsystems/events/event-keyset-cursor.js +8 -30
  385. package/dist/runtime/subsystems/events/event-keyset-cursor.js.map +1 -1
  386. package/dist/runtime/subsystems/events/event-read.protocol.js +2 -0
  387. package/dist/runtime/subsystems/events/event-read.protocol.js.map +1 -1
  388. package/dist/runtime/subsystems/events/events-errors.js +4 -11
  389. package/dist/runtime/subsystems/events/events-errors.js.map +1 -1
  390. package/dist/runtime/subsystems/events/events.module.js +15 -949
  391. package/dist/runtime/subsystems/events/events.module.js.map +1 -1
  392. package/dist/runtime/subsystems/events/events.tokens.js +10 -11
  393. package/dist/runtime/subsystems/events/events.tokens.js.map +1 -1
  394. package/dist/runtime/subsystems/events/generated/bus.js +9 -240
  395. package/dist/runtime/subsystems/events/generated/bus.js.map +1 -1
  396. package/dist/runtime/subsystems/events/generated/index.js +23 -240
  397. package/dist/runtime/subsystems/events/generated/index.js.map +1 -1
  398. package/dist/runtime/subsystems/events/generated/registry.js +5 -82
  399. package/dist/runtime/subsystems/events/generated/registry.js.map +1 -1
  400. package/dist/runtime/subsystems/events/generated/schemas.js +12 -52
  401. package/dist/runtime/subsystems/events/generated/schemas.js.map +1 -1
  402. package/dist/runtime/subsystems/events/generated/types.js +1 -0
  403. package/dist/runtime/subsystems/events/index.js +32 -949
  404. package/dist/runtime/subsystems/events/index.js.map +1 -1
  405. package/dist/runtime/subsystems/index.js +171 -5912
  406. package/dist/runtime/subsystems/index.js.map +1 -1
  407. package/dist/runtime/subsystems/integration/build-change-source.js +6 -178
  408. package/dist/runtime/subsystems/integration/build-change-source.js.map +1 -1
  409. package/dist/runtime/subsystems/integration/deep-equal.differ.js +4 -109
  410. package/dist/runtime/subsystems/integration/deep-equal.differ.js.map +1 -1
  411. package/dist/runtime/subsystems/integration/detection-config.schema.js +11 -78
  412. package/dist/runtime/subsystems/integration/detection-config.schema.js.map +1 -1
  413. package/dist/runtime/subsystems/integration/entity-change-source-registry.memory.js +5 -30
  414. package/dist/runtime/subsystems/integration/entity-change-source-registry.memory.js.map +1 -1
  415. package/dist/runtime/subsystems/integration/entity-change-source-registry.protocol.js +4 -9
  416. package/dist/runtime/subsystems/integration/entity-change-source-registry.protocol.js.map +1 -1
  417. package/dist/runtime/subsystems/integration/execute-integration.use-case.js +6 -239
  418. package/dist/runtime/subsystems/integration/execute-integration.use-case.js.map +1 -1
  419. package/dist/runtime/subsystems/integration/incremental-read.js +5 -144
  420. package/dist/runtime/subsystems/integration/incremental-read.js.map +1 -1
  421. package/dist/runtime/subsystems/integration/index.js +83 -1352
  422. package/dist/runtime/subsystems/integration/index.js.map +1 -1
  423. package/dist/runtime/subsystems/integration/integration-audit.schema.js +10 -155
  424. package/dist/runtime/subsystems/integration/integration-audit.schema.js.map +1 -1
  425. package/dist/runtime/subsystems/integration/integration-cursor-store.drizzle-backend.js +7 -270
  426. package/dist/runtime/subsystems/integration/integration-cursor-store.drizzle-backend.js.map +1 -1
  427. package/dist/runtime/subsystems/integration/integration-cursor-store.memory-backend.js +4 -65
  428. package/dist/runtime/subsystems/integration/integration-cursor-store.memory-backend.js.map +1 -1
  429. package/dist/runtime/subsystems/integration/integration-errors.js +5 -15
  430. package/dist/runtime/subsystems/integration/integration-errors.js.map +1 -1
  431. package/dist/runtime/subsystems/integration/integration-field-diff.protocol.js +5 -7
  432. package/dist/runtime/subsystems/integration/integration-field-diff.protocol.js.map +1 -1
  433. package/dist/runtime/subsystems/integration/integration-run-recorder.drizzle-backend.js +8 -303
  434. package/dist/runtime/subsystems/integration/integration-run-recorder.drizzle-backend.js.map +1 -1
  435. package/dist/runtime/subsystems/integration/integration-run-recorder.memory-backend.js +5 -125
  436. package/dist/runtime/subsystems/integration/integration-run-recorder.memory-backend.js.map +1 -1
  437. package/dist/runtime/subsystems/integration/integration.module.js +13 -700
  438. package/dist/runtime/subsystems/integration/integration.module.js.map +1 -1
  439. package/dist/runtime/subsystems/integration/integration.tokens.js +11 -9
  440. package/dist/runtime/subsystems/integration/integration.tokens.js.map +1 -1
  441. package/dist/runtime/subsystems/integration/loopback.middleware.js +4 -16
  442. package/dist/runtime/subsystems/integration/loopback.middleware.js.map +1 -1
  443. package/dist/runtime/subsystems/integration/poll-change-source.js +4 -89
  444. package/dist/runtime/subsystems/integration/poll-change-source.js.map +1 -1
  445. package/dist/runtime/subsystems/integration/webhook-change-source.js +4 -70
  446. package/dist/runtime/subsystems/integration/webhook-change-source.js.map +1 -1
  447. package/dist/runtime/subsystems/jobs/bullmq.config.js +9 -140
  448. package/dist/runtime/subsystems/jobs/bullmq.config.js.map +1 -1
  449. package/dist/runtime/subsystems/jobs/index.js +88 -2691
  450. package/dist/runtime/subsystems/jobs/index.js.map +1 -1
  451. package/dist/runtime/subsystems/jobs/job-handler.base.js +10 -49
  452. package/dist/runtime/subsystems/jobs/job-handler.base.js.map +1 -1
  453. package/dist/runtime/subsystems/jobs/job-orchestration.schema.js +13 -152
  454. package/dist/runtime/subsystems/jobs/job-orchestration.schema.js.map +1 -1
  455. package/dist/runtime/subsystems/jobs/job-orchestrator.bullmq-backend.js +36 -699
  456. package/dist/runtime/subsystems/jobs/job-orchestrator.bullmq-backend.js.map +1 -1
  457. package/dist/runtime/subsystems/jobs/job-orchestrator.drizzle-backend.js +10 -564
  458. package/dist/runtime/subsystems/jobs/job-orchestrator.drizzle-backend.js.map +1 -1
  459. package/dist/runtime/subsystems/jobs/job-orchestrator.memory-backend.js +10 -824
  460. package/dist/runtime/subsystems/jobs/job-orchestrator.memory-backend.js.map +1 -1
  461. package/dist/runtime/subsystems/jobs/job-run-keyset-cursor.js +9 -51
  462. package/dist/runtime/subsystems/jobs/job-run-keyset-cursor.js.map +1 -1
  463. package/dist/runtime/subsystems/jobs/job-run-service.drizzle-backend.js +9 -416
  464. package/dist/runtime/subsystems/jobs/job-run-service.drizzle-backend.js.map +1 -1
  465. package/dist/runtime/subsystems/jobs/job-run-service.memory-backend.js +9 -290
  466. package/dist/runtime/subsystems/jobs/job-run-service.memory-backend.js.map +1 -1
  467. package/dist/runtime/subsystems/jobs/job-step-service.drizzle-backend.js +5 -213
  468. package/dist/runtime/subsystems/jobs/job-step-service.drizzle-backend.js.map +1 -1
  469. package/dist/runtime/subsystems/jobs/job-step-service.memory-backend.js +5 -131
  470. package/dist/runtime/subsystems/jobs/job-step-service.memory-backend.js.map +1 -1
  471. package/dist/runtime/subsystems/jobs/job-worker.bullmq-backend.js +9 -175
  472. package/dist/runtime/subsystems/jobs/job-worker.bullmq-backend.js.map +1 -1
  473. package/dist/runtime/subsystems/jobs/job-worker.js +14 -613
  474. package/dist/runtime/subsystems/jobs/job-worker.js.map +1 -1
  475. package/dist/runtime/subsystems/jobs/job-worker.module.js +23 -2647
  476. package/dist/runtime/subsystems/jobs/job-worker.module.js.map +1 -1
  477. package/dist/runtime/subsystems/jobs/jobs-domain.module.js +19 -1897
  478. package/dist/runtime/subsystems/jobs/jobs-domain.module.js.map +1 -1
  479. package/dist/runtime/subsystems/jobs/jobs-domain.tokens.js +8 -9
  480. package/dist/runtime/subsystems/jobs/jobs-domain.tokens.js.map +1 -1
  481. package/dist/runtime/subsystems/jobs/jobs-errors.js +10 -78
  482. package/dist/runtime/subsystems/jobs/jobs-errors.js.map +1 -1
  483. package/dist/runtime/subsystems/jobs/memory-job-store.js +4 -15
  484. package/dist/runtime/subsystems/jobs/memory-job-store.js.map +1 -1
  485. package/dist/runtime/subsystems/jobs/pool-config.loader.js +9 -124
  486. package/dist/runtime/subsystems/jobs/pool-config.loader.js.map +1 -1
  487. package/dist/runtime/subsystems/observability/index.js +21 -310
  488. package/dist/runtime/subsystems/observability/index.js.map +1 -1
  489. package/dist/runtime/subsystems/observability/observability-errors.js +4 -9
  490. package/dist/runtime/subsystems/observability/observability-errors.js.map +1 -1
  491. package/dist/runtime/subsystems/observability/observability.module.js +11 -300
  492. package/dist/runtime/subsystems/observability/observability.module.js.map +1 -1
  493. package/dist/runtime/subsystems/observability/observability.service.js +9 -197
  494. package/dist/runtime/subsystems/observability/observability.service.js.map +1 -1
  495. package/dist/runtime/subsystems/observability/observability.tokens.js +5 -3
  496. package/dist/runtime/subsystems/observability/observability.tokens.js.map +1 -1
  497. package/dist/runtime/subsystems/observability/reporters/bridge-metrics.reporter.js +4 -84
  498. package/dist/runtime/subsystems/observability/reporters/bridge-metrics.reporter.js.map +1 -1
  499. package/dist/runtime/subsystems/observability/reporters/index.js +5 -84
  500. package/dist/runtime/subsystems/observability/reporters/index.js.map +1 -1
  501. package/dist/runtime/subsystems/storage/index.js +15 -200
  502. package/dist/runtime/subsystems/storage/index.js.map +1 -1
  503. package/dist/runtime/subsystems/storage/storage.local-backend.js +4 -103
  504. package/dist/runtime/subsystems/storage/storage.local-backend.js.map +1 -1
  505. package/dist/runtime/subsystems/storage/storage.memory-backend.js +5 -68
  506. package/dist/runtime/subsystems/storage/storage.memory-backend.js.map +1 -1
  507. package/dist/runtime/subsystems/storage/storage.module.js +8 -200
  508. package/dist/runtime/subsystems/storage/storage.module.js.map +1 -1
  509. package/dist/runtime/subsystems/storage/storage.tokens.js +5 -6
  510. package/dist/runtime/subsystems/storage/storage.tokens.js.map +1 -1
  511. package/dist/runtime/subsystems/storage/storage.utils.js +4 -14
  512. package/dist/runtime/subsystems/storage/storage.utils.js.map +1 -1
  513. package/dist/runtime/subsystems/token-key.js +5 -3
  514. package/dist/runtime/subsystems/token-key.js.map +1 -1
  515. package/dist/src/cli/index.js +637 -5454
  516. package/dist/src/cli/index.js.map +1 -1
  517. package/dist/src/index.js +68 -4170
  518. package/dist/src/index.js.map +1 -1
  519. package/package.json +1 -1
  520. package/runtime/subsystems/bridge/bridge-outbox-drain-hook.ts +44 -21
  521. package/runtime/subsystems/jobs/job-worker.ts +17 -11
@@ -0,0 +1,134 @@
1
+ import {
2
+ BRIDGE_DELIVERY_JOB_TYPE
3
+ } from "./chunk-YTN6BKWA.js";
4
+ import {
5
+ bridgeDelivery
6
+ } from "./chunk-2TVVBC53.js";
7
+ import {
8
+ BRIDGE_REGISTRY
9
+ } from "./chunk-4LH67P4U.js";
10
+ import {
11
+ jobRuns
12
+ } from "./chunk-OKXZ63IA.js";
13
+ import {
14
+ __decorateClass,
15
+ __decorateParam
16
+ } from "./chunk-2E224ZSN.js";
17
+
18
+ // runtime/subsystems/bridge/bridge-outbox-drain-hook.ts
19
+ import { Inject, Injectable, Logger, Optional } from "@nestjs/common";
20
+ import { randomUUID } from "crypto";
21
+ import { eq } from "drizzle-orm";
22
+ var POOL_BY_DIRECTION = {
23
+ inbound: "events_inbound",
24
+ change: "events_change",
25
+ outbound: "events_outbound"
26
+ };
27
+ var BridgeOutboxDrainHook = class {
28
+ constructor(registry = {}) {
29
+ this.registry = registry;
30
+ }
31
+ registry;
32
+ logger = new Logger(BridgeOutboxDrainHook.name);
33
+ warnedNullDirection = false;
34
+ warnedAuditTypes = /* @__PURE__ */ new Set();
35
+ async processEvent(event, tx) {
36
+ if (event.metadata?.["tier"] === "audit") {
37
+ this.warnAuditBlockedOnce(event);
38
+ return {
39
+ delivered: 0,
40
+ dedupSkips: 0,
41
+ triggerCount: 0,
42
+ auditBlocked: 1
43
+ };
44
+ }
45
+ const triggers = this.lookupTriggers(event.type);
46
+ if (triggers.length === 0) {
47
+ return {
48
+ delivered: 0,
49
+ dedupSkips: 0,
50
+ triggerCount: 0,
51
+ auditBlocked: 0
52
+ };
53
+ }
54
+ const direction = event.metadata?.["direction"] ?? null;
55
+ const tenantId = event.metadata?.["tenantId"] ?? null;
56
+ const wrapperPool = direction ? POOL_BY_DIRECTION[direction] : void 0;
57
+ if (!wrapperPool) {
58
+ if (!this.warnedNullDirection) {
59
+ this.warnedNullDirection = true;
60
+ this.logger.warn(
61
+ `Skipping bridge fanout for events with null/unknown direction. event.id=${event.id} event.type=${event.type} direction=${String(direction)}. The wrapper pool is derived from direction (events_<direction>); publishers must use TypedEventBus.publish() so direction is stamped on the outbox row.`
62
+ );
63
+ }
64
+ return {
65
+ delivered: 0,
66
+ dedupSkips: 0,
67
+ triggerCount: triggers.length,
68
+ auditBlocked: 0
69
+ };
70
+ }
71
+ let delivered = 0;
72
+ let dedupSkips = 0;
73
+ const client = tx;
74
+ for (const trigger of triggers) {
75
+ const deliveryId = randomUUID();
76
+ const wrapperRunId = randomUUID();
77
+ await tx.insert(jobRuns).values({
78
+ id: wrapperRunId,
79
+ jobType: BRIDGE_DELIVERY_JOB_TYPE,
80
+ jobVersion: 1,
81
+ rootRunId: wrapperRunId,
82
+ pool: wrapperPool,
83
+ status: "pending",
84
+ input: { deliveryId },
85
+ triggerSource: "event",
86
+ triggerRef: event.id,
87
+ tenantId
88
+ });
89
+ const inserted = await tx.insert(bridgeDelivery).values({
90
+ id: deliveryId,
91
+ eventId: event.id,
92
+ triggerId: trigger.triggerId,
93
+ wrapperRunId,
94
+ status: "pending",
95
+ tenantId
96
+ }).onConflictDoNothing({
97
+ target: [bridgeDelivery.eventId, bridgeDelivery.triggerId]
98
+ }).returning({ id: bridgeDelivery.id });
99
+ if (inserted.length === 0) {
100
+ await tx.delete(jobRuns).where(eq(jobRuns.id, wrapperRunId));
101
+ dedupSkips++;
102
+ continue;
103
+ }
104
+ delivered++;
105
+ }
106
+ return {
107
+ delivered,
108
+ dedupSkips,
109
+ triggerCount: triggers.length,
110
+ auditBlocked: 0
111
+ };
112
+ }
113
+ warnAuditBlockedOnce(event) {
114
+ if (this.warnedAuditTypes.has(event.type)) return;
115
+ this.warnedAuditTypes.add(event.type);
116
+ this.logger.warn(
117
+ `Bridge guard blocked audit-tier event '${event.type}' (event.id=${event.id}). Registry says this event is not bridge-eligible; a bridge_trigger row exists out-of-band. Investigate registry/runtime drift.`
118
+ );
119
+ }
120
+ lookupTriggers(eventType) {
121
+ const candidates = this.registry[eventType];
122
+ return candidates ?? [];
123
+ }
124
+ };
125
+ BridgeOutboxDrainHook = __decorateClass([
126
+ Injectable(),
127
+ __decorateParam(0, Optional()),
128
+ __decorateParam(0, Inject(BRIDGE_REGISTRY))
129
+ ], BridgeOutboxDrainHook);
130
+
131
+ export {
132
+ BridgeOutboxDrainHook
133
+ };
134
+ //# sourceMappingURL=chunk-L7BNNRGI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../runtime/subsystems/bridge/bridge-outbox-drain-hook.ts"],"sourcesContent":["/**\n * BridgeOutboxDrainHook — drains-time bridge fanout writer (BRIDGE-4,\n * ADR-023 Phase 2).\n *\n * Implements `IBridgeOutboxDrainHook`. Called by `DrizzleEventBus`'s\n * modified `processBatch` once per drained event, INSIDE the per-event\n * transaction. For every trigger registered against the event's type in\n * the codegen-emitted `bridgeRegistry`, writes:\n *\n * 1. `bridge_delivery` ledger row — `INSERT … ON CONFLICT (event_id,\n * trigger_id) DO NOTHING RETURNING id`. Empty result ⇒ Case B\n * facade-eager pre-write OR drain-replay collision; skip wrapper\n * insert for that trigger; sibling triggers still fire.\n * 2. `job_run` wrapper row — `type='@framework/bridge_delivery'`,\n * `pool='events_<direction>'`, `input={ deliveryId }`,\n * `trigger_source='event'`, `trigger_ref=event.id`. The wrapper is\n * what the framework `BridgeDeliveryHandler` (BRIDGE-5) eventually\n * claims via the worker that polls the corresponding reserved pool.\n *\n * Null `event.metadata.direction` is tolerated: the hook logs a one-line\n * warning per event and returns zeros without writing rows. The drain's\n * `processed_at` stamp + subscriber dispatch still fire normally.\n * Direction is null only for events published via the legacy\n * `IEventBus.publish(...)` path (`TypedEventBus.publish` always sets it);\n * such events are out of scope for bridge fanout.\n *\n * The wrapper insert generates its own `id` via Drizzle's `defaultRandom`\n * — we don't `RETURNING id` because nobody needs it at drain time;\n * `BridgeDeliveryHandler` later looks up the wrapper via the\n * `bridge_delivery.wrapper_run_id` link if needed. This keeps the drain\n * one-round-trip-per-trigger.\n */\nimport { Inject, Injectable, Logger, Optional } from '@nestjs/common';\nimport { randomUUID } from 'node:crypto';\nimport { eq } from 'drizzle-orm';\n\nimport type { DomainEvent, DrizzleTransaction } from '../events/event-bus.protocol';\nimport { bridgeDelivery } from './bridge-delivery.schema';\nimport { jobRuns } from '../jobs/job-orchestration.schema';\n\nimport { BRIDGE_REGISTRY } from './bridge.tokens';\nimport type {\n BridgeOutboxDrainResult,\n BridgeRegistry,\n BridgeTriggerEntry,\n IBridgeOutboxDrainHook,\n} from './bridge.protocol';\nimport { BRIDGE_DELIVERY_JOB_TYPE } from './bridge-delivery-handler';\nimport type { EventTypeName } from '../events/event-registry';\n\n/** Reserved pools the wrapper rows route into; ADR-022 / ADR-024. */\nconst POOL_BY_DIRECTION: Record<string, string> = {\n inbound: 'events_inbound',\n change: 'events_change',\n outbound: 'events_outbound',\n};\n\n@Injectable()\nexport class BridgeOutboxDrainHook implements IBridgeOutboxDrainHook {\n private readonly logger = new Logger(BridgeOutboxDrainHook.name);\n private warnedNullDirection = false;\n private readonly warnedAuditTypes = new Set<string>();\n\n constructor(\n @Optional()\n @Inject(BRIDGE_REGISTRY)\n private readonly registry: BridgeRegistry = {},\n ) {}\n\n async processEvent(\n event: DomainEvent,\n tx: DrizzleTransaction,\n ): Promise<BridgeOutboxDrainResult> {\n // Audit-tier guard (defense-in-depth — AUDIT-4). Audit events are not\n // bridge-eligible: the codegen-side validator (AUDIT-2) blocks the\n // registry from listing them as triggers. Reaching this branch means\n // registry/runtime drift — an out-of-band `bridge_trigger` insert, or\n // version skew during deploy. Refuse fanout, surface drift via WARN.\n if (event.metadata?.['tier'] === 'audit') {\n this.warnAuditBlockedOnce(event);\n return {\n delivered: 0,\n dedupSkips: 0,\n triggerCount: 0,\n auditBlocked: 1,\n };\n }\n\n const triggers = this.lookupTriggers(event.type);\n if (triggers.length === 0) {\n return {\n delivered: 0,\n dedupSkips: 0,\n triggerCount: 0,\n auditBlocked: 0,\n };\n }\n\n const direction =\n (event.metadata?.['direction'] as string | undefined) ?? null;\n const tenantId =\n (event.metadata?.['tenantId'] as string | null | undefined) ?? null;\n const wrapperPool = direction ? POOL_BY_DIRECTION[direction] : undefined;\n\n if (!wrapperPool) {\n // Null direction (or an unrecognised one — defensive). Bridge\n // fanout requires a routed wrapper pool; without one we can't\n // spawn. Log once per process so misconfiguration surfaces.\n if (!this.warnedNullDirection) {\n this.warnedNullDirection = true;\n this.logger.warn(\n `Skipping bridge fanout for events with null/unknown direction. ` +\n `event.id=${event.id} event.type=${event.type} ` +\n `direction=${String(direction)}. The wrapper pool is derived ` +\n `from direction (events_<direction>); publishers must use ` +\n `TypedEventBus.publish() so direction is stamped on the ` +\n `outbox row.`,\n );\n }\n return {\n delivered: 0,\n dedupSkips: 0,\n triggerCount: triggers.length,\n auditBlocked: 0,\n };\n }\n\n let delivered = 0;\n let dedupSkips = 0;\n const client = tx as unknown as {\n insert: (table: unknown) => {\n values: (v: unknown) => {\n onConflictDoNothing: (opts: unknown) => {\n returning: (cols: unknown) => Promise<{ id: string }[]>;\n };\n } & {\n // wrapper insert path — no ON CONFLICT\n // (typed loosely via the same helper return shape)\n };\n };\n };\n\n for (const trigger of triggers) {\n const deliveryId = randomUUID();\n const wrapperRunId = randomUUID();\n\n // FK ORDER (BRIDGE / 0.15.2): `bridge_delivery.wrapper_run_id` REFERENCES\n // `job_run(id)` is a plain (non-deferrable) FK, so the referenced\n // wrapper `job_run` MUST exist before the delivery row that points at it\n // is inserted — otherwise Postgres rejects the delivery insert\n // immediately. (The codegen unit tests mock `tx`, so they never\n // exercised this ordering against a real FK; package-mode bridge\n // deliveries are the first to do so.) We therefore insert the wrapper\n // run FIRST, then the delivery. Idempotency is unchanged: the delivery\n // keeps its `ON CONFLICT (event_id, trigger_id) DO NOTHING RETURNING`,\n // and when the delivery conflicts (outbox replay or facade-eager Case B)\n // we DELETE the just-inserted orphan wrapper run in the same tx, so a\n // skipped delivery leaves no stray `job_run` for a worker to claim.\n\n // 1. Wrapper job_run insert. We carry the deliveryId into the wrapper\n // input so BridgeDeliveryHandler.run(ctx) can locate the row via\n // repo.findDeliveryById(ctx.input.deliveryId).\n await (tx as unknown as { insert: typeof client.insert })\n .insert(jobRuns)\n .values({\n id: wrapperRunId,\n jobType: BRIDGE_DELIVERY_JOB_TYPE,\n jobVersion: 1,\n rootRunId: wrapperRunId,\n pool: wrapperPool,\n status: 'pending',\n input: { deliveryId },\n triggerSource: 'event',\n triggerRef: event.id,\n tenantId,\n });\n\n // 2. bridge_delivery insert with ON CONFLICT DO NOTHING + RETURNING.\n const inserted = await (tx as unknown as {\n insert: typeof client.insert;\n })\n .insert(bridgeDelivery)\n .values({\n id: deliveryId,\n eventId: event.id,\n triggerId: trigger.triggerId,\n wrapperRunId,\n status: 'pending',\n tenantId,\n })\n .onConflictDoNothing({\n target: [bridgeDelivery.eventId, bridgeDelivery.triggerId],\n })\n .returning({ id: bridgeDelivery.id });\n\n if (inserted.length === 0) {\n // Case B (facade pre-wrote `delivered`) or drain replay — the delivery\n // already exists, so this trigger is a no-op. Remove the orphan wrapper\n // run we speculatively inserted above so no worker claims it. Sibling\n // triggers still fire.\n await (tx as unknown as {\n delete: (table: unknown) => {\n where: (cond: unknown) => Promise<unknown>;\n };\n })\n .delete(jobRuns)\n .where(eq(jobRuns.id, wrapperRunId));\n dedupSkips++;\n continue;\n }\n\n delivered++;\n }\n\n return {\n delivered,\n dedupSkips,\n triggerCount: triggers.length,\n auditBlocked: 0,\n };\n }\n\n private warnAuditBlockedOnce(event: DomainEvent): void {\n if (this.warnedAuditTypes.has(event.type)) return;\n this.warnedAuditTypes.add(event.type);\n this.logger.warn(\n `Bridge guard blocked audit-tier event '${event.type}' (event.id=${event.id}). ` +\n `Registry says this event is not bridge-eligible; a bridge_trigger row exists ` +\n `out-of-band. Investigate registry/runtime drift.`,\n );\n }\n\n private lookupTriggers(\n eventType: string,\n ): BridgeTriggerEntry[] {\n const candidates = this.registry[eventType as EventTypeName];\n return (candidates ?? []) as BridgeTriggerEntry[];\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,150 @@
1
+ // runtime/subsystems/integration/incremental-read.ts
2
+ async function mapConcurrent(ids, fn, limit) {
3
+ const out = /* @__PURE__ */ new Map();
4
+ if (ids.length === 0) return out;
5
+ const width = Math.max(1, Math.min(limit, ids.length));
6
+ let next = 0;
7
+ const worker = async () => {
8
+ while (next < ids.length) {
9
+ const idx = next++;
10
+ const id = ids[idx];
11
+ out.set(id, await fn(id));
12
+ }
13
+ };
14
+ await Promise.all(Array.from({ length: width }, worker));
15
+ return out;
16
+ }
17
+ var IncrementalReadBase = class {
18
+ /**
19
+ * Whether the vendor takes the request predicate server-side. Declared, not
20
+ * enforced here — surfaced into the emission manifest (R3) so the falsifier
21
+ * suite (R4) can record which adapters filter post-hydrate. `false` is the
22
+ * honest floor (e.g. Gmail without `q=`), handled via `matchesRecord`.
23
+ */
24
+ filterPushdown = false;
25
+ /** Max concurrent in-flight calls for a `mapConcurrent`-built `hydrate`. */
26
+ hydrateConcurrency = 10;
27
+ /** `Change<T>.source` provenance stamped by `listChanges`. */
28
+ changeSource = "poll";
29
+ /**
30
+ * Whether this source's cursor strategy is divisible (RFC-0003 §3). When
31
+ * `true` (default — sortable watermarks like `systemModstamp`/`timestamp`/
32
+ * `replayId`), `listChanges` emits each record's per-ref cursor, so the
33
+ * orchestrator may checkpoint mid-walk and a crash resumes from the last
34
+ * delivered ref.
35
+ *
36
+ * When `false` (atomic opaque tokens — Gmail `historyId`, Calendar
37
+ * `syncToken`), `listChanges` WITHHOLDS per-ref cursors and emits the
38
+ * end-of-walk token only on the final record, so the orchestrator's
39
+ * persist-last-yielded lifecycle can never persist an unresumable mid-walk
40
+ * token. The cost is blast-radius: an interrupted atomic run resumes
41
+ * all-or-nothing from the prior persisted token. For atomic *backfills* that
42
+ * radius is the whole enumerate walk — bound it with `ReadRequest.pageSize`
43
+ * (smaller pages ⇒ shorter walks per run). Per-page atomic checkpointing is a
44
+ * future refinement; R2 gates at end-of-walk.
45
+ *
46
+ * Codegen (R3) sets this from the strategy kind via `isDivisibleCursor`.
47
+ */
48
+ cursorDivisible = true;
49
+ // ---- Optional filter hooks — exactly one is live per `filterPushdown` ----
50
+ /** Pre-hydrate predicate over the cheap ref (preferred — avoids hydration). */
51
+ matchesRef(_ref, _filter) {
52
+ return true;
53
+ }
54
+ /** Post-hydrate predicate over the canonical record (the no-pushdown floor). */
55
+ matchesRecord(_record, _filter) {
56
+ return true;
57
+ }
58
+ /**
59
+ * Resolve the filter for a subscription when adapting to `listChanges`
60
+ * (which has no filter argument). Defaults to none; codegen wiring (R3)
61
+ * overrides this to thread `DetectionConfig.filters`.
62
+ */
63
+ filterFor(_subscription) {
64
+ return void 0;
65
+ }
66
+ // ---- PROVIDED by the base ----
67
+ /**
68
+ * Stream canonical records for a request. Filter is applied BEFORE hydrate
69
+ * (structural: a kept ref is hydrated, a rejected one never is), so an
70
+ * adapter cannot hydrate-then-discard. A hydrate miss (deleted mid-run) is
71
+ * skipped, never fabricated.
72
+ */
73
+ async *read(req, ctx) {
74
+ for await (const refPage of this.enumerate(req.mode, req.filter, req.pageSize, ctx)) {
75
+ const kept = refPage.filter((ref) => this.matchesRef(ref, req.filter));
76
+ if (kept.length === 0) continue;
77
+ const raws = await this.hydrate(
78
+ kept.map((ref) => ref.externalId),
79
+ ctx
80
+ );
81
+ for (const ref of kept) {
82
+ const raw = raws.get(ref.externalId);
83
+ if (raw === void 0 || raw === null) continue;
84
+ const record = this.toCanonical(raw);
85
+ if (record !== null && this.matchesRecord(record, req.filter)) {
86
+ yield { externalId: ref.externalId, record, raw, cursor: ref.cursor };
87
+ }
88
+ }
89
+ }
90
+ }
91
+ /**
92
+ * `RandomRead<T>` — single-record read, provided for free as
93
+ * `toCanonical ∘ hydrate([id])`. Reuses the adapter's batched fetch + miss
94
+ * tolerance; returns `null` for a missing or undecodable record.
95
+ */
96
+ async get(id, ctx) {
97
+ const raws = await this.hydrate([id], ctx);
98
+ const raw = raws.get(id);
99
+ if (raw === void 0 || raw === null) return null;
100
+ return this.toCanonical(raw);
101
+ }
102
+ /**
103
+ * `IChangeSource<T>` adaptation. Maps the orchestrator's by-value cursor to a
104
+ * `ReadMode` (`null` → `full` backfill, else `delta`), streams `read()`, and
105
+ * stamps each `SourcedRecord` into a `Change<T>`. All records surface as
106
+ * `'updated'`; the orchestrator's diff stage classifies create-vs-update and
107
+ * deletes arrive as tombstone refs (`toCanonical` may flag them).
108
+ *
109
+ * Cursor emission honors `cursorDivisible` (RFC-0003 §3). Divisible: each
110
+ * record carries its own per-ref cursor. Atomic: per-ref cursors are withheld
111
+ * (`undefined`, which the orchestrator skips persisting) and the end-of-walk
112
+ * token rides only on the final record — so a mid-walk crash never persists
113
+ * an unresumable token. If an atomic run yields no surviving records, no
114
+ * cursor is persisted and the next run re-reads the same (empty) delta — a
115
+ * bounded inefficiency, never data loss.
116
+ */
117
+ async *listChanges(subscription, cursor) {
118
+ const mode = cursor === null || cursor === void 0 ? { kind: "full" } : { kind: "delta", cursor };
119
+ const filter = this.filterFor(subscription);
120
+ const stream = this.read({ mode, filter }, { subscription });
121
+ if (this.cursorDivisible) {
122
+ for await (const sourced of stream) {
123
+ yield this.toChange(sourced, sourced.cursor);
124
+ }
125
+ return;
126
+ }
127
+ let prev = null;
128
+ for await (const sourced of stream) {
129
+ if (prev !== null) yield this.toChange(prev, void 0);
130
+ prev = sourced;
131
+ }
132
+ if (prev !== null) yield this.toChange(prev, prev.cursor);
133
+ }
134
+ /** Stamp a `SourcedRecord` into a `Change<T>` with an explicit emitted cursor. */
135
+ toChange(sourced, cursor) {
136
+ return {
137
+ externalId: sourced.externalId,
138
+ operation: "updated",
139
+ record: sourced.record,
140
+ cursor,
141
+ source: this.changeSource
142
+ };
143
+ }
144
+ };
145
+
146
+ export {
147
+ mapConcurrent,
148
+ IncrementalReadBase
149
+ };
150
+ //# sourceMappingURL=chunk-LG57S2SC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../runtime/subsystems/integration/incremental-read.ts"],"sourcesContent":["/**\n * Integration subsystem — `IncrementalRead<T, F>` + `RandomRead<T>` capability\n * and the providing `IncrementalReadBase<T, F, M>` (RFC-0003 R1).\n *\n * The universal read primitive. Where `IChangeSource.listChanges` is the\n * *transport* contract (stream `Change<T>`, orchestrator owns cursor lifecycle),\n * this base owns *how the body that produces those changes is written* — the\n * level the bare `changeSources = {}` author-seam left unstructured.\n *\n * The read decomposes into two composable verbs the adapter supplies:\n *\n * - `enumerate(mode, filter) → AsyncIterable<Ref<M>[]>` — the cheap delta /\n * backfill walk; streams pages of lightweight refs (id + per-ref cursor +\n * filterable metadata). LAZY: pull-driven so hydrate backpressures it.\n * - `hydrate(ids) → Map<id, raw>` — the expensive fetch-by-id, batched; where\n * bounded concurrency / a vendor `/batch` endpoint lives. Keyed and\n * miss-tolerant (a mid-run 404 cannot shift alignment).\n * - `toCanonical(raw) → T | null` — provider payload → canonical record.\n *\n * The base PROVIDES the orchestration: drain enumerate, **filter before\n * hydrate** (structural — an adapter physically cannot hydrate-then-discard),\n * keyed pairing, per-ref cursor emission, and the `IChangeSource.listChanges`\n * adaptation. It also provides `RandomRead.get()` for free as\n * `toCanonical ∘ hydrate([id])` — so every incremental adapter is a\n * single-record reader (the \"list cheaply, fill on click\" query-surface need)\n * without extra code.\n *\n * The shape generalizes dealbrain's proven HubSpot `listSince` (streams, pushes\n * the filter server-side, carries a per-record cursor) to vendors whose list\n * returns id-stubs (Gmail) or nested resources (Meet). Calendar-style\n * full-object lists override `hydrate` as a passthrough.\n *\n * See RFC-0003 (Track D round-3), ADR-033 (`detection:` config), and\n * `poll-change-source.ts` (the sibling primitive this composes beside).\n */\n\nimport type {\n Change,\n ChangeSource,\n IChangeSource,\n IntegrationSubscriptionView,\n} from './integration-change-source.protocol';\n\n// ============================================================================\n// Capability shapes\n// ============================================================================\n\n/**\n * How a read walks the upstream. Modes are values, not verbs (swe-brain\n * ADR-0003: mode ≠ capability) — one `read()` verb dispatches on these.\n *\n * - `delta` — incremental walk from a persisted cursor.\n * - `full` — cursorless backfill (optionally bounded by `since`).\n * - `reconcile` — gap-repair: re-fetch a known id set the cursor skipped\n * (the repair pass for the silent-tail-skip + #414-style\n * multi-provider divergence).\n */\nexport type ReadMode =\n | { readonly kind: 'delta'; readonly cursor: unknown }\n | { readonly kind: 'full'; readonly since?: Date }\n | { readonly kind: 'reconcile'; readonly knownIds: readonly string[] };\n\n/**\n * A cheap ref from the enumerate pass: identity + per-ref cursor + metadata to\n * filter or display on. `cursor` is the position AS OF this ref — see\n * `IncrementalReadBase.cursorDivisible` (R2) for when it may be checkpointed\n * mid-walk versus withheld until a safe boundary.\n */\nexport interface Ref<M = Record<string, unknown>> {\n readonly externalId: string;\n readonly cursor: unknown;\n readonly meta: M;\n}\n\n/** A read request: the mode, an optional adapter-typed filter, and page size. */\nexport interface ReadRequest<F = unknown> {\n readonly mode: ReadMode;\n readonly filter?: F;\n readonly pageSize?: number;\n}\n\n/**\n * Per-run context threaded from `listChanges` into the vendor read body (R5).\n *\n * Carries the `subscription` framing the run so `enumerate`/`hydrate` can resolve\n * **per-connection credentials** (and raw-landing keys) from\n * `subscription.externalRef` — the gap a multi-account consumer surfaced: a\n * singleton change source cannot hold connection-scoped auth, and before R5 the\n * base forwarded the subscription only into `filterFor`, never into the fetch.\n *\n * Optional throughout (the core contract): a direct `read()` / `get()` call — the\n * query surface's \"fill one record on click\" — may omit it. An adapter that needs\n * per-connection auth reads `ctx?.subscription?.externalRef` and asserts its\n * presence; a provider-level-auth adapter ignores it.\n */\nexport interface ReadContext {\n /** The subscription framing this run; `externalRef` is the upstream scope /\n * connection id the adapter resolves credentials + raw-landing keys from. */\n readonly subscription?: IntegrationSubscriptionView;\n}\n\n/**\n * The `read()`-side envelope: canonical record + the raw vendor payload it came\n * from + the originating external id + the per-ref cursor.\n *\n * Distinct from the runtime's transport envelope `Change<T>`\n * (operation/externalId/cursor/source). The relationship is one-directional:\n * `listChanges()` adapts `read()` → `Change<T>` (dropping `raw`, stamping\n * `operation`). `read()` keeps `raw` and `externalId` so a query surface can\n * re-project without a second fetch.\n */\nexport interface SourcedRecord<T> {\n readonly externalId: string;\n readonly record: T;\n readonly raw: unknown;\n readonly cursor: unknown;\n}\n\n/**\n * The universal read capability — one public verb that streams. Filtering,\n * hydration, and cursor emission are the providing base's concern.\n */\nexport interface IncrementalRead<T, F = unknown> {\n read(req: ReadRequest<F>, ctx?: ReadContext): AsyncIterable<SourcedRecord<T>>;\n}\n\n/**\n * Single-record read by external id — the \"fill on click\" atom. Provided for\n * free by `IncrementalReadBase` (composes `hydrate` + `toCanonical`); declared\n * as its own capability so consumers can depend on it without the streaming\n * surface.\n */\nexport interface RandomRead<T> {\n get(id: string, ctx?: ReadContext): Promise<T | null>;\n}\n\n// ============================================================================\n// Bounded-parallel map helper\n// ============================================================================\n\n/**\n * Map `ids` through `fn` with at most `limit` concurrent in-flight calls,\n * collecting results keyed by id. The workhorse for writing a batched\n * `hydrate` over a single-id fetch without serial N+1 latency.\n */\nexport async function mapConcurrent<R>(\n ids: readonly string[],\n fn: (id: string) => Promise<R>,\n limit: number,\n): Promise<Map<string, R>> {\n const out = new Map<string, R>();\n if (ids.length === 0) return out;\n const width = Math.max(1, Math.min(limit, ids.length));\n let next = 0;\n const worker = async (): Promise<void> => {\n while (next < ids.length) {\n const idx = next++;\n const id = ids[idx]!;\n out.set(id, await fn(id));\n }\n };\n await Promise.all(Array.from({ length: width }, worker));\n return out;\n}\n\n// ============================================================================\n// IncrementalReadBase\n// ============================================================================\n\n/**\n * Providing base for the read capability. A subclass fills exactly three vendor\n * methods — `enumerate`, `hydrate`, `toCanonical` — and gets a streaming,\n * filter-before-hydrate, miss-tolerant `IncrementalRead<T, F>` +\n * `IChangeSource<T>` + `RandomRead<T>`.\n *\n * Type params: `T` canonical record, `F` adapter-typed filter, `M` per-ref\n * metadata (defaults to an untyped bag — surface packages supply a domain `M`).\n */\nexport abstract class IncrementalReadBase<T, F = unknown, M = Record<string, unknown>>\n implements IncrementalRead<T, F>, IChangeSource<T>, RandomRead<T>\n{\n /** Human label for run logs — e.g. `'google-mail-email'`. */\n abstract readonly label: string;\n\n /**\n * Whether the vendor takes the request predicate server-side. Declared, not\n * enforced here — surfaced into the emission manifest (R3) so the falsifier\n * suite (R4) can record which adapters filter post-hydrate. `false` is the\n * honest floor (e.g. Gmail without `q=`), handled via `matchesRecord`.\n */\n protected readonly filterPushdown: boolean = false;\n\n /** Max concurrent in-flight calls for a `mapConcurrent`-built `hydrate`. */\n protected readonly hydrateConcurrency: number = 10;\n\n /** `Change<T>.source` provenance stamped by `listChanges`. */\n protected readonly changeSource: ChangeSource = 'poll';\n\n /**\n * Whether this source's cursor strategy is divisible (RFC-0003 §3). When\n * `true` (default — sortable watermarks like `systemModstamp`/`timestamp`/\n * `replayId`), `listChanges` emits each record's per-ref cursor, so the\n * orchestrator may checkpoint mid-walk and a crash resumes from the last\n * delivered ref.\n *\n * When `false` (atomic opaque tokens — Gmail `historyId`, Calendar\n * `syncToken`), `listChanges` WITHHOLDS per-ref cursors and emits the\n * end-of-walk token only on the final record, so the orchestrator's\n * persist-last-yielded lifecycle can never persist an unresumable mid-walk\n * token. The cost is blast-radius: an interrupted atomic run resumes\n * all-or-nothing from the prior persisted token. For atomic *backfills* that\n * radius is the whole enumerate walk — bound it with `ReadRequest.pageSize`\n * (smaller pages ⇒ shorter walks per run). Per-page atomic checkpointing is a\n * future refinement; R2 gates at end-of-walk.\n *\n * Codegen (R3) sets this from the strategy kind via `isDivisibleCursor`.\n */\n protected readonly cursorDivisible: boolean = true;\n\n // ---- SUPPLIED by the adapter (the irreducible vendor seam) ----\n\n /**\n * The cheap walk. Streams pages of refs; LAZY so `hydrate` backpressures it\n * (one page hydrated before the next is pulled). Mode-dispatch lives here:\n * `delta` resumes from `mode.cursor`, `full` walks from the top, `reconcile`\n * re-fetches `mode.knownIds`.\n *\n * `pageSize` (from `ReadRequest`) is the adapter's requested vendor page size\n * — also the atomic-cursor backfill blast-radius bound (§ `cursorDivisible`).\n * Honor it as a hint; vendors that cap page size clamp it.\n *\n * `ctx?.subscription` (R5) carries the run's subscription, so a per-connection\n * adapter resolves credentials / upstream scope from `externalRef` here; absent\n * on a direct `read()` with no run subscription.\n */\n protected abstract enumerate(\n mode: ReadMode,\n filter?: F,\n pageSize?: number,\n ctx?: ReadContext,\n ): AsyncIterable<Ref<M>[]>;\n\n /**\n * Fetch raw payloads for `ids`, keyed by id. MUST be miss-tolerant: omit (or\n * map to `null`) any id that 404s mid-run rather than throwing or shifting\n * alignment. Write it over `mapConcurrent(ids, (id) => this.fetchOne(id),\n * this.hydrateConcurrency)`; override with a real `/batch` call or a\n * passthrough (full-object list) where the vendor allows.\n *\n * `ctx?.subscription` (R5) carries the run's subscription for per-connection\n * credential resolution (the fetch is where the vendor call happens) and is the\n * natural place to land raw payloads keyed by `subscription.id`.\n */\n protected abstract hydrate(ids: string[], ctx?: ReadContext): Promise<Map<string, unknown>>;\n\n /** Provider payload → canonical record. Return `null` to drop a record. */\n protected abstract toCanonical(raw: unknown): T | null;\n\n // ---- Optional filter hooks — exactly one is live per `filterPushdown` ----\n\n /** Pre-hydrate predicate over the cheap ref (preferred — avoids hydration). */\n protected matchesRef(_ref: Ref<M>, _filter?: F): boolean {\n return true;\n }\n\n /** Post-hydrate predicate over the canonical record (the no-pushdown floor). */\n protected matchesRecord(_record: T, _filter?: F): boolean {\n return true;\n }\n\n /**\n * Resolve the filter for a subscription when adapting to `listChanges`\n * (which has no filter argument). Defaults to none; codegen wiring (R3)\n * overrides this to thread `DetectionConfig.filters`.\n */\n protected filterFor(_subscription: IntegrationSubscriptionView): F | undefined {\n return undefined;\n }\n\n // ---- PROVIDED by the base ----\n\n /**\n * Stream canonical records for a request. Filter is applied BEFORE hydrate\n * (structural: a kept ref is hydrated, a rejected one never is), so an\n * adapter cannot hydrate-then-discard. A hydrate miss (deleted mid-run) is\n * skipped, never fabricated.\n */\n async *read(req: ReadRequest<F>, ctx?: ReadContext): AsyncIterable<SourcedRecord<T>> {\n for await (const refPage of this.enumerate(req.mode, req.filter, req.pageSize, ctx)) {\n const kept = refPage.filter((ref) => this.matchesRef(ref, req.filter));\n if (kept.length === 0) continue;\n const raws = await this.hydrate(\n kept.map((ref) => ref.externalId),\n ctx,\n );\n for (const ref of kept) {\n const raw = raws.get(ref.externalId);\n if (raw === undefined || raw === null) continue; // deleted mid-run → skip\n const record = this.toCanonical(raw);\n if (record !== null && this.matchesRecord(record, req.filter)) {\n yield { externalId: ref.externalId, record, raw, cursor: ref.cursor };\n }\n }\n }\n }\n\n /**\n * `RandomRead<T>` — single-record read, provided for free as\n * `toCanonical ∘ hydrate([id])`. Reuses the adapter's batched fetch + miss\n * tolerance; returns `null` for a missing or undecodable record.\n */\n async get(id: string, ctx?: ReadContext): Promise<T | null> {\n const raws = await this.hydrate([id], ctx);\n const raw = raws.get(id);\n if (raw === undefined || raw === null) return null;\n return this.toCanonical(raw);\n }\n\n /**\n * `IChangeSource<T>` adaptation. Maps the orchestrator's by-value cursor to a\n * `ReadMode` (`null` → `full` backfill, else `delta`), streams `read()`, and\n * stamps each `SourcedRecord` into a `Change<T>`. All records surface as\n * `'updated'`; the orchestrator's diff stage classifies create-vs-update and\n * deletes arrive as tombstone refs (`toCanonical` may flag them).\n *\n * Cursor emission honors `cursorDivisible` (RFC-0003 §3). Divisible: each\n * record carries its own per-ref cursor. Atomic: per-ref cursors are withheld\n * (`undefined`, which the orchestrator skips persisting) and the end-of-walk\n * token rides only on the final record — so a mid-walk crash never persists\n * an unresumable token. If an atomic run yields no surviving records, no\n * cursor is persisted and the next run re-reads the same (empty) delta — a\n * bounded inefficiency, never data loss.\n */\n async *listChanges(\n subscription: IntegrationSubscriptionView,\n cursor: unknown | null,\n ): AsyncIterable<Change<T>> {\n const mode: ReadMode =\n cursor === null || cursor === undefined\n ? { kind: 'full' }\n : { kind: 'delta', cursor };\n const filter = this.filterFor(subscription);\n // R5: thread the run's subscription into the read body so `enumerate`/`hydrate`\n // can resolve per-connection credentials (and raw-landing keys) from it.\n const stream = this.read({ mode, filter }, { subscription });\n\n if (this.cursorDivisible) {\n for await (const sourced of stream) {\n yield this.toChange(sourced, sourced.cursor);\n }\n return;\n }\n\n // Atomic: one-record lookahead. Emit every record but the last with a\n // withheld (`undefined`) cursor; the last record carries the end-of-walk\n // token. Contract: an atomic adapter stamps the (single, shared) end-of-walk\n // token onto its refs' `cursor` — so whichever record survives last carries\n // it. The base emits a real cursor exactly once, on that final record, so the\n // orchestrator can never persist a mid-walk value. If zero records survive,\n // nothing is persisted (next run re-reads the delta — bounded, never lossy).\n let prev: SourcedRecord<T> | null = null;\n for await (const sourced of stream) {\n if (prev !== null) yield this.toChange(prev, undefined);\n prev = sourced;\n }\n if (prev !== null) yield this.toChange(prev, prev.cursor);\n }\n\n /** Stamp a `SourcedRecord` into a `Change<T>` with an explicit emitted cursor. */\n private toChange(sourced: SourcedRecord<T>, cursor: unknown): Change<T> {\n return {\n externalId: sourced.externalId,\n operation: 'updated',\n record: sourced.record,\n cursor,\n source: this.changeSource,\n };\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,97 @@
1
+ import {
2
+ ConnectionBrokenError
3
+ } from "./chunk-2N4UG4VD.js";
4
+
5
+ // runtime/subsystems/auth/runtime/oauth2-refresh.strategy.ts
6
+ var REFRESH_SAFETY_MS = 5 * 60 * 1e3;
7
+ var OAuth2RefreshStrategy = class {
8
+ connectionReader;
9
+ tokenWriter;
10
+ fetchImpl;
11
+ now;
12
+ constructor(opts) {
13
+ this.connectionReader = opts.connectionReader;
14
+ this.tokenWriter = opts.tokenWriter;
15
+ this.fetchImpl = opts.fetch ?? fetch;
16
+ this.now = opts.now ?? Date.now;
17
+ }
18
+ async resolve(connectionId, opts = {}) {
19
+ const connection = await this.connectionReader.findByIdDecrypted(connectionId);
20
+ if (!connection) {
21
+ throw new Error(`Connection ${connectionId} not found`);
22
+ }
23
+ if (connection.provider !== this.provider) {
24
+ throw new Error(
25
+ `${this.constructor.name} called for non-${this.provider} connection ${connectionId} (provider=${connection.provider})`
26
+ );
27
+ }
28
+ const needsRefresh = opts.forceRefresh || this.isExpiring(connection.expiresAt) || !connection.accessToken;
29
+ if (!needsRefresh) {
30
+ return this.buildCredentials(connection.accessToken, connection);
31
+ }
32
+ if (!connection.refreshToken) {
33
+ throw new ConnectionBrokenError(
34
+ connectionId,
35
+ "no_refresh_token",
36
+ "Connection has no refresh token; user must reconnect"
37
+ );
38
+ }
39
+ const { parsed, raw } = await this.executeRefresh(
40
+ connectionId,
41
+ connection.refreshToken
42
+ );
43
+ const newExpiresAt = new Date(
44
+ this.now() + (parsed.expiresInSec ?? this.defaultExpiresInSec) * 1e3
45
+ );
46
+ await this.tokenWriter.persistRefresh({
47
+ connectionId,
48
+ accessToken: parsed.accessToken,
49
+ refreshToken: parsed.refreshToken ?? void 0,
50
+ expiresAt: newExpiresAt
51
+ });
52
+ return this.buildCredentials(parsed.accessToken, connection, raw);
53
+ }
54
+ async executeRefresh(connectionId, refreshToken) {
55
+ const body = new URLSearchParams({
56
+ grant_type: "refresh_token",
57
+ refresh_token: refreshToken,
58
+ ...this.refreshBodyExtras()
59
+ });
60
+ const response = await this.fetchImpl(this.tokenEndpoint(), {
61
+ method: "POST",
62
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
63
+ body: body.toString()
64
+ });
65
+ if (!response.ok) {
66
+ const err = await safeJson(response);
67
+ if (response.status === 400 && (err.error === "invalid_grant" || err.error === "invalid_token")) {
68
+ throw new ConnectionBrokenError(
69
+ connectionId,
70
+ err.error ?? "invalid_grant",
71
+ err.error_description ?? err.message ?? "refresh token rejected"
72
+ );
73
+ }
74
+ throw new Error(
75
+ `${this.provider} token refresh failed: ${response.status} ${err.error ?? ""} ${err.error_description ?? err.message ?? ""}`.trim()
76
+ );
77
+ }
78
+ const raw = await response.json();
79
+ return { parsed: this.parseRefreshResponse(raw), raw };
80
+ }
81
+ isExpiring(expiresAt) {
82
+ if (!expiresAt) return true;
83
+ return expiresAt.getTime() - this.now() < REFRESH_SAFETY_MS;
84
+ }
85
+ };
86
+ async function safeJson(response) {
87
+ try {
88
+ return await response.clone().json();
89
+ } catch {
90
+ return {};
91
+ }
92
+ }
93
+
94
+ export {
95
+ OAuth2RefreshStrategy
96
+ };
97
+ //# sourceMappingURL=chunk-M6QLSLPO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../runtime/subsystems/auth/runtime/oauth2-refresh.strategy.ts"],"sourcesContent":["/**\n * Abstract base class for OAuth2 refresh-token strategies.\n *\n * Template-method pattern: `resolve()` is concrete; four small hooks inject\n * provider specifics. Validated across two providers (Salesforce, HubSpot)\n * in the extraction-source app before being extracted here — see\n * `docs/gate-1-auth-extraction-findings.md` for the \"build first, extract\n * later\" evidence.\n *\n * Subclass contract:\n * - `provider` — slug matched against `connections.provider`\n * - `defaultExpiresInSec` — fallback when refresh response omits `expires_in`\n * - `tokenEndpoint()` — URL to POST the refresh grant\n * - `refreshBodyExtras()` — provider-specific body params\n * - `parseRefreshResponse()` — raw JSON → ParsedRefreshResponse\n * - `buildCredentials()` — stored or freshly-refreshed access token +\n * connection + optional raw refresh response\n * → provider credentials\n *\n * Base handles: expiry check w/ 5-min safety window, `forceRefresh` escape\n * hatch, POST form-urlencoded body, OAuth2 error mapping to\n * `ConnectionBrokenError`, refresh-token rotation persistence, fetch +\n * clock injection for tests.\n */\nimport type {\n AuthCredentials,\n AuthResolveOptions,\n IAuthStrategy,\n} from '../protocols/auth-strategy';\nimport type {\n DecryptedConnection,\n IConnectionReader,\n IConnectionTokenWriter,\n} from '../protocols/connection-store';\nimport { ConnectionBrokenError } from './connection-broken.error';\n\nexport type FetchLike = (\n input: string | URL | Request,\n init?: RequestInit,\n) => Promise<Response>;\n\n/** Safety window before expiry that triggers a refresh. */\nconst REFRESH_SAFETY_MS = 5 * 60 * 1000;\n\nexport interface OAuth2RefreshStrategyOptions {\n connectionReader: IConnectionReader;\n tokenWriter: IConnectionTokenWriter;\n /** Injectable fetch for tests. Defaults to the global `fetch`. */\n fetch?: FetchLike;\n /** Injectable clock for tests. Defaults to `Date.now`. */\n now?: () => number;\n}\n\nexport interface ParsedRefreshResponse {\n accessToken: string;\n /**\n * New refresh token if the provider rotated it (HubSpot: always, Salesforce:\n * sometimes). Omit when the provider reused the old refresh token.\n */\n refreshToken?: string;\n /** Seconds from now. If omitted, subclass `defaultExpiresInSec` applies. */\n expiresInSec?: number;\n}\n\nexport abstract class OAuth2RefreshStrategy implements IAuthStrategy {\n protected abstract readonly provider: string;\n protected abstract readonly defaultExpiresInSec: number;\n\n protected readonly connectionReader: IConnectionReader;\n protected readonly tokenWriter: IConnectionTokenWriter;\n protected readonly fetchImpl: FetchLike;\n protected readonly now: () => number;\n\n constructor(opts: OAuth2RefreshStrategyOptions) {\n this.connectionReader = opts.connectionReader;\n this.tokenWriter = opts.tokenWriter;\n this.fetchImpl = opts.fetch ?? fetch;\n this.now = opts.now ?? Date.now;\n }\n\n async resolve(\n connectionId: string,\n opts: AuthResolveOptions = {},\n ): Promise<AuthCredentials> {\n const connection =\n await this.connectionReader.findByIdDecrypted(connectionId);\n if (!connection) {\n throw new Error(`Connection ${connectionId} not found`);\n }\n if (connection.provider !== this.provider) {\n throw new Error(\n `${this.constructor.name} called for non-${this.provider} connection ${connectionId} (provider=${connection.provider})`,\n );\n }\n\n const needsRefresh =\n opts.forceRefresh ||\n this.isExpiring(connection.expiresAt) ||\n !connection.accessToken;\n\n if (!needsRefresh) {\n return this.buildCredentials(connection.accessToken, connection);\n }\n\n if (!connection.refreshToken) {\n throw new ConnectionBrokenError(\n connectionId,\n 'no_refresh_token',\n 'Connection has no refresh token; user must reconnect',\n );\n }\n\n const { parsed, raw } = await this.executeRefresh(\n connectionId,\n connection.refreshToken,\n );\n const newExpiresAt = new Date(\n this.now() + (parsed.expiresInSec ?? this.defaultExpiresInSec) * 1000,\n );\n await this.tokenWriter.persistRefresh({\n connectionId,\n accessToken: parsed.accessToken,\n refreshToken: parsed.refreshToken ?? undefined,\n expiresAt: newExpiresAt,\n });\n\n return this.buildCredentials(parsed.accessToken, connection, raw);\n }\n\n protected abstract tokenEndpoint(): string;\n protected abstract refreshBodyExtras(): Record<string, string>;\n protected abstract parseRefreshResponse(raw: unknown): ParsedRefreshResponse;\n protected abstract buildCredentials(\n accessToken: string,\n connection: DecryptedConnection,\n refreshRaw?: unknown,\n ): AuthCredentials;\n\n private async executeRefresh(\n connectionId: string,\n refreshToken: string,\n ): Promise<{ parsed: ParsedRefreshResponse; raw: unknown }> {\n const body = new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n ...this.refreshBodyExtras(),\n });\n const response = await this.fetchImpl(this.tokenEndpoint(), {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n });\n if (!response.ok) {\n const err = (await safeJson(response)) as Partial<{\n error: string;\n error_description: string;\n message: string;\n }>;\n if (\n response.status === 400 &&\n (err.error === 'invalid_grant' || err.error === 'invalid_token')\n ) {\n throw new ConnectionBrokenError(\n connectionId,\n err.error ?? 'invalid_grant',\n err.error_description ?? err.message ?? 'refresh token rejected',\n );\n }\n throw new Error(\n `${this.provider} token refresh failed: ${response.status} ${err.error ?? ''} ${err.error_description ?? err.message ?? ''}`.trim(),\n );\n }\n const raw = await response.json();\n return { parsed: this.parseRefreshResponse(raw), raw };\n }\n\n private isExpiring(expiresAt: Date | null): boolean {\n if (!expiresAt) return true;\n return expiresAt.getTime() - this.now() < REFRESH_SAFETY_MS;\n }\n}\n\nasync function safeJson(response: Response): Promise<unknown> {\n try {\n return await response.clone().json();\n } catch {\n return {};\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,21 @@
1
+ // runtime/subsystems/integration/integration-errors.ts
2
+ var MissingTenantIdError = class extends Error {
3
+ name = "MissingTenantIdError";
4
+ constructor(operation) {
5
+ super(
6
+ `Missing tenantId for integration operation '${operation}'. IntegrationModule is configured with multiTenant: true \u2014 every call must include a non-null tenantId. Either pass the tenantId or disable multi-tenancy on the module.`
7
+ );
8
+ }
9
+ };
10
+ function assertTenantId(tenantId, options) {
11
+ if (!options.multiTenant) return;
12
+ if (tenantId === void 0 || tenantId === null) {
13
+ throw new MissingTenantIdError(options.operation);
14
+ }
15
+ }
16
+
17
+ export {
18
+ MissingTenantIdError,
19
+ assertTenantId
20
+ };
21
+ //# sourceMappingURL=chunk-MZ6GV4YF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../runtime/subsystems/integration/integration-errors.ts"],"sourcesContent":["/**\n * Typed errors + shared boundary helpers for the integration subsystem.\n *\n * Classes (not bare Error) so consumers can `instanceof` them in catch\n * blocks and exception filters can map them to HTTP codes.\n *\n * Mirrors the shape of `events-errors.ts` and `jobs-errors.ts`.\n */\n\n/**\n * Thrown by the Drizzle cursor-store / run-recorder backends AND by the\n * orchestrator entry point when `INTEGRATION_MULTI_TENANT` is enabled but the\n * caller did not supply a non-null `tenantId`. Strict enforcement at the\n * boundary — explicit `null` still throws.\n *\n * Disable multi-tenancy on the module (`multiTenant: false`, the default)\n * to opt out of the requirement entirely.\n *\n * `operation` identifies the call site (e.g. `'cursor.put'`,\n * `'startRun'`, `'execute'`) so the stack-trace message points at the\n * specific boundary that rejected the input.\n */\nexport class MissingTenantIdError extends Error {\n override readonly name = 'MissingTenantIdError';\n constructor(operation: string) {\n super(\n `Missing tenantId for integration operation '${operation}'. IntegrationModule is ` +\n `configured with multiTenant: true — every call must include a ` +\n `non-null tenantId. Either pass the tenantId or disable multi-` +\n `tenancy on the module.`,\n );\n }\n}\n\n/**\n * Shared boundary guard — used at the orchestrator entry AND inside the\n * Drizzle backends. Keeping the check in one function guarantees every\n * `MissingTenantIdError` carries the same message shape regardless of the\n * site that raised it, which makes it easier for consumers to pattern-\n * match on the error in logs/metrics.\n *\n * When `multiTenant` is false, the function is a no-op — `tenantId` may\n * be anything (including `undefined`). When true, `undefined` or `null`\n * throws.\n */\nexport function assertTenantId(\n tenantId: string | null | undefined,\n options: { multiTenant: boolean; operation: string },\n): asserts tenantId is string {\n if (!options.multiTenant) return;\n if (tenantId === undefined || tenantId === null) {\n throw new MissingTenantIdError(options.operation);\n }\n}\n"],"mappings":";AAsBO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAC5B,OAAO;AAAA,EACzB,YAAY,WAAmB;AAC7B;AAAA,MACE,+CAA+C,SAAS;AAAA,IAI1D;AAAA,EACF;AACF;AAaO,SAAS,eACd,UACA,SAC4B;AAC5B,MAAI,CAAC,QAAQ,YAAa;AAC1B,MAAI,aAAa,UAAa,aAAa,MAAM;AAC/C,UAAM,IAAI,qBAAqB,QAAQ,SAAS;AAAA,EAClD;AACF;","names":[]}
@@ -0,0 +1,55 @@
1
+ import {
2
+ OAuthStateError
3
+ } from "./chunk-BPARRK6F.js";
4
+ import {
5
+ authOAuthState
6
+ } from "./chunk-NPFPZ2HO.js";
7
+
8
+ // runtime/subsystems/auth/backends/state-store.drizzle-backend.ts
9
+ import { randomBytes } from "crypto";
10
+ import { eq } from "drizzle-orm";
11
+ var DrizzleOAuthStateStore = class {
12
+ constructor(db, opts = {}) {
13
+ this.db = db;
14
+ this.ttlMs = opts.ttlMs ?? 10 * 60 * 1e3;
15
+ this.now = opts.now ?? (() => Date.now());
16
+ this.generateToken = opts.generateToken ?? (() => randomBytes(32).toString("base64url"));
17
+ }
18
+ db;
19
+ ttlMs;
20
+ now;
21
+ generateToken;
22
+ async generate(record) {
23
+ const state = this.generateToken();
24
+ const expiresAt = new Date(this.now() + this.ttlMs);
25
+ await this.db.insert(authOAuthState).values({
26
+ state,
27
+ userId: record.userId,
28
+ redirect: record.redirect ?? null,
29
+ expiresAt
30
+ });
31
+ return state;
32
+ }
33
+ async consume(state) {
34
+ const rows = await this.db.delete(authOAuthState).where(eq(authOAuthState.state, state)).returning();
35
+ const row = rows[0];
36
+ if (!row) {
37
+ throw new OAuthStateError(
38
+ `OAuth state token unknown or already consumed`,
39
+ "missing"
40
+ );
41
+ }
42
+ if (row.expiresAt.getTime() <= this.now()) {
43
+ throw new OAuthStateError(`OAuth state token expired`, "expired");
44
+ }
45
+ return {
46
+ userId: row.userId,
47
+ redirect: row.redirect ?? void 0
48
+ };
49
+ }
50
+ };
51
+
52
+ export {
53
+ DrizzleOAuthStateStore
54
+ };
55
+ //# sourceMappingURL=chunk-N5OTOWTP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../runtime/subsystems/auth/backends/state-store.drizzle-backend.ts"],"sourcesContent":["/**\n * Drizzle-backed `IOAuthStateStore`.\n *\n * Uses the `auth_oauth_state` table (see `auth-oauth-state.schema.ts`).\n * Single-use semantics enforced via `DELETE ... RETURNING`: the consume\n * path atomically deletes and returns the row, so a concurrent /callback\n * with the same state cannot replay.\n *\n * Behaviour:\n * - `generate(record)` mints a 256-bit base64url token, INSERTs the row\n * with `expires_at = now() + ttlMs`.\n * - `consume(state)` runs `DELETE ... WHERE state = $1 RETURNING ...`\n * once. Throws `OAuthStateError('missing')` if no row was deleted\n * (unknown or already consumed) and `OAuthStateError('expired')` if\n * the deleted row was past its `expires_at`.\n */\nimport { randomBytes } from 'node:crypto';\nimport { eq } from 'drizzle-orm';\nimport type { DrizzleClient } from '../../../types/drizzle';\nimport { authOAuthState } from '../auth-oauth-state.schema';\nimport {\n type IOAuthStateStore,\n type OAuthStateRecord,\n OAuthStateError,\n} from '../protocols/oauth-state-store';\n\nexport interface DrizzleOAuthStateStoreOptions {\n /** TTL in ms. Default 10 minutes. */\n ttlMs?: number;\n /** Injectable clock for tests. Default `Date.now`. */\n now?: () => number;\n /** Injectable token generator for tests. Default 32-byte base64url. */\n generateToken?: () => string;\n}\n\nexport class DrizzleOAuthStateStore implements IOAuthStateStore {\n private readonly ttlMs: number;\n private readonly now: () => number;\n private readonly generateToken: () => string;\n\n constructor(\n private readonly db: DrizzleClient,\n opts: DrizzleOAuthStateStoreOptions = {},\n ) {\n this.ttlMs = opts.ttlMs ?? 10 * 60 * 1000;\n this.now = opts.now ?? (() => Date.now());\n this.generateToken =\n opts.generateToken ?? (() => randomBytes(32).toString('base64url'));\n }\n\n async generate(record: OAuthStateRecord): Promise<string> {\n const state = this.generateToken();\n const expiresAt = new Date(this.now() + this.ttlMs);\n await this.db.insert(authOAuthState).values({\n state,\n userId: record.userId,\n redirect: record.redirect ?? null,\n expiresAt,\n });\n return state;\n }\n\n async consume(state: string): Promise<OAuthStateRecord> {\n const rows = await this.db\n .delete(authOAuthState)\n .where(eq(authOAuthState.state, state))\n .returning();\n const row = rows[0];\n if (!row) {\n throw new OAuthStateError(\n `OAuth state token unknown or already consumed`,\n 'missing',\n );\n }\n if (row.expiresAt.getTime() <= this.now()) {\n throw new OAuthStateError(`OAuth state token expired`, 'expired');\n }\n return {\n userId: row.userId,\n redirect: row.redirect ?? undefined,\n };\n }\n}\n"],"mappings":";;;;;;;;AAgBA,SAAS,mBAAmB;AAC5B,SAAS,UAAU;AAkBZ,IAAM,yBAAN,MAAyD;AAAA,EAK9D,YACmB,IACjB,OAAsC,CAAC,GACvC;AAFiB;AAGjB,SAAK,QAAQ,KAAK,SAAS,KAAK,KAAK;AACrC,SAAK,MAAM,KAAK,QAAQ,MAAM,KAAK,IAAI;AACvC,SAAK,gBACH,KAAK,kBAAkB,MAAM,YAAY,EAAE,EAAE,SAAS,WAAW;AAAA,EACrE;AAAA,EAPmB;AAAA,EALF;AAAA,EACA;AAAA,EACA;AAAA,EAYjB,MAAM,SAAS,QAA2C;AACxD,UAAM,QAAQ,KAAK,cAAc;AACjC,UAAM,YAAY,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK;AAClD,UAAM,KAAK,GAAG,OAAO,cAAc,EAAE,OAAO;AAAA,MAC1C;AAAA,MACA,QAAQ,OAAO;AAAA,MACf,UAAU,OAAO,YAAY;AAAA,MAC7B;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAAQ,OAA0C;AACtD,UAAM,OAAO,MAAM,KAAK,GACrB,OAAO,cAAc,EACrB,MAAM,GAAG,eAAe,OAAO,KAAK,CAAC,EACrC,UAAU;AACb,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,CAAC,KAAK;AACR,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,QAAI,IAAI,UAAU,QAAQ,KAAK,KAAK,IAAI,GAAG;AACzC,YAAM,IAAI,gBAAgB,6BAA6B,SAAS;AAAA,IAClE;AACA,WAAO;AAAA,MACL,QAAQ,IAAI;AAAA,MACZ,UAAU,IAAI,YAAY;AAAA,IAC5B;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,14 @@
1
+ import {
2
+ BaseRepository
3
+ } from "./chunk-J6KZS54B.js";
4
+
5
+ // runtime/base-classes/knowledge-entity-repository.ts
6
+ var KnowledgeEntityRepository = class extends BaseRepository {
7
+ // pgvector-dependent methods will be added when the extension is available:
8
+ // semanticSearch, findPendingByOpportunityId, updateStatus, updateStatusBatch
9
+ };
10
+
11
+ export {
12
+ KnowledgeEntityRepository
13
+ };
14
+ //# sourceMappingURL=chunk-NN7XZEGF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../runtime/base-classes/knowledge-entity-repository.ts"],"sourcesContent":["/**\n * KnowledgeEntityRepository<TEntity>\n *\n * Stub for the knowledge family (requires pgvector — parked for now).\n * Concrete repos extend this when pgvector is available.\n */\nimport { BaseRepository } from './base-repository';\n\nexport abstract class KnowledgeEntityRepository<TEntity> extends BaseRepository<TEntity> {\n // pgvector-dependent methods will be added when the extension is available:\n // semanticSearch, findPendingByOpportunityId, updateStatus, updateStatusBatch\n}\n"],"mappings":";;;;;AAQO,IAAe,4BAAf,cAA0D,eAAwB;AAAA;AAAA;AAGzF;","names":[]}
@@ -0,0 +1,13 @@
1
+ // runtime/subsystems/auth/auth-oauth-state.schema.ts
2
+ import { pgTable, text, timestamp } from "drizzle-orm/pg-core";
3
+ var authOAuthState = pgTable("auth_oauth_state", {
4
+ state: text("state").primaryKey(),
5
+ userId: text("user_id").notNull(),
6
+ redirect: text("redirect"),
7
+ expiresAt: timestamp("expires_at", { withTimezone: true }).notNull()
8
+ });
9
+
10
+ export {
11
+ authOAuthState
12
+ };
13
+ //# sourceMappingURL=chunk-NPFPZ2HO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../runtime/subsystems/auth/auth-oauth-state.schema.ts"],"sourcesContent":["/**\n * Drizzle schema for the `auth_oauth_state` table — backs the\n * `DrizzleOAuthStateStore` (`state-store.drizzle-backend.ts`).\n *\n * One row per outstanding /connect → /callback dance. Single-use; rows are\n * deleted on consume. A periodic sweep (or a `WHERE expires_at < now()`\n * filter on read) clears abandoned rows.\n *\n * Columns:\n * - `state` — opaque random token, primary key.\n * - `user_id` — text (matches the consumer-defined user-id shape;\n * the auth subsystem doesn't constrain this to UUID\n * because some apps key users by external id).\n * - `redirect` — optional post-callback redirect path.\n * - `expires_at` — TTL boundary; entries past this are treated as absent.\n *\n * Convention: schema files live at the root of the subsystem dir\n * (mirrors `cache.schema.ts`, `integration-audit.schema.ts`, `domain-events.schema.ts`).\n */\nimport { pgTable, text, timestamp } from 'drizzle-orm/pg-core';\nimport type { InferSelectModel } from 'drizzle-orm';\n\nexport const authOAuthState = pgTable('auth_oauth_state', {\n state: text('state').primaryKey(),\n userId: text('user_id').notNull(),\n redirect: text('redirect'),\n expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),\n});\n\nexport type AuthOAuthState = InferSelectModel<typeof authOAuthState>;\n"],"mappings":";AAmBA,SAAS,SAAS,MAAM,iBAAiB;AAGlC,IAAM,iBAAiB,QAAQ,oBAAoB;AAAA,EACxD,OAAO,KAAK,OAAO,EAAE,WAAW;AAAA,EAChC,QAAQ,KAAK,SAAS,EAAE,QAAQ;AAAA,EAChC,UAAU,KAAK,UAAU;AAAA,EACzB,WAAW,UAAU,cAAc,EAAE,cAAc,KAAK,CAAC,EAAE,QAAQ;AACrE,CAAC;","names":[]}
@@ -0,0 +1,42 @@
1
+ // runtime/subsystems/bridge/bridge-errors.ts
2
+ var MissingTenantIdError = class extends Error {
3
+ constructor(callSite) {
4
+ super(
5
+ `MissingTenantIdError: BridgeModule was configured with multiTenant=true but ${callSite} was called without tenantId (undefined). Pass an explicit tenantId, or pass null for cross-tenant work.`
6
+ );
7
+ this.callSite = callSite;
8
+ }
9
+ callSite;
10
+ name = "MissingTenantIdError";
11
+ };
12
+ var BridgeReservedPoolsNotPolledError = class extends Error {
13
+ constructor(missingPools) {
14
+ super(
15
+ `BridgeModule loaded but JobWorkerModule is not polling reserved pool '${missingPools[0]}'. Add ...BRIDGE_RESERVED_POOLS to your JobWorkerModule.forRoot({ pools }) configuration. Missing pools: ${missingPools.join(", ")}. (Bridge-fanout wrappers will sit pending forever without these pollers.)`
16
+ );
17
+ this.missingPools = missingPools;
18
+ }
19
+ missingPools;
20
+ name = "BridgeReservedPoolsNotPolledError";
21
+ };
22
+ var UniqueConstraintError = class extends Error {
23
+ constructor(constraint, eventId, triggerId) {
24
+ super(
25
+ `UniqueConstraintError: duplicate insert into bridge_delivery for (event_id='${eventId}', trigger_id='${triggerId}') \u2014 violates constraint '${constraint}'.`
26
+ );
27
+ this.constraint = constraint;
28
+ this.eventId = eventId;
29
+ this.triggerId = triggerId;
30
+ }
31
+ constraint;
32
+ eventId;
33
+ triggerId;
34
+ name = "UniqueConstraintError";
35
+ };
36
+
37
+ export {
38
+ MissingTenantIdError,
39
+ BridgeReservedPoolsNotPolledError,
40
+ UniqueConstraintError
41
+ };
42
+ //# sourceMappingURL=chunk-NXXDZ6ZF.js.map