@alneas/eaos-server 0.0.0-stage → 0.2.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 (360) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/LICENSE +21 -0
  3. package/README.ja.md +49 -0
  4. package/README.md +46 -2
  5. package/dist/agentic/agent-jobs.d.ts +333 -0
  6. package/dist/agentic/agent-jobs.js +15 -0
  7. package/dist/agentic/agent-jobs.js.map +1 -0
  8. package/dist/agentic/agent-node.d.ts +40 -0
  9. package/dist/agentic/agent-node.js +7 -0
  10. package/dist/agentic/agent-node.js.map +1 -0
  11. package/dist/agentic/agent-runner.d.ts +33 -0
  12. package/dist/agentic/agent-runner.js +7 -0
  13. package/dist/agentic/agent-runner.js.map +1 -0
  14. package/dist/agentic/ai-broker.d.ts +169 -0
  15. package/dist/agentic/ai-broker.js +8 -0
  16. package/dist/agentic/ai-broker.js.map +1 -0
  17. package/dist/agentic/atomic-checkpointer.d.ts +137 -0
  18. package/dist/agentic/atomic-checkpointer.js +9 -0
  19. package/dist/agentic/atomic-checkpointer.js.map +1 -0
  20. package/dist/agentic/autonomous-worker.d.ts +122 -0
  21. package/dist/agentic/autonomous-worker.js +10 -0
  22. package/dist/agentic/autonomous-worker.js.map +1 -0
  23. package/dist/agentic/event-bridge.d.ts +350 -0
  24. package/dist/agentic/event-bridge.js +9 -0
  25. package/dist/agentic/event-bridge.js.map +1 -0
  26. package/dist/agentic/executor.d.ts +91 -0
  27. package/dist/agentic/executor.js +12 -0
  28. package/dist/agentic/executor.js.map +1 -0
  29. package/dist/agentic/graph-projection.d.ts +119 -0
  30. package/dist/agentic/graph-projection.js +7 -0
  31. package/dist/agentic/graph-projection.js.map +1 -0
  32. package/dist/agentic/graph.d.ts +524 -0
  33. package/dist/agentic/graph.js +7 -0
  34. package/dist/agentic/graph.js.map +1 -0
  35. package/dist/agentic/index.d.ts +28 -0
  36. package/dist/agentic/index.js +87 -0
  37. package/dist/agentic/index.js.map +1 -0
  38. package/dist/agentic/local-runner.d.ts +106 -0
  39. package/dist/agentic/local-runner.js +7 -0
  40. package/dist/agentic/local-runner.js.map +1 -0
  41. package/dist/agentic/remote-executor.d.ts +67 -0
  42. package/dist/agentic/remote-executor.js +8 -0
  43. package/dist/agentic/remote-executor.js.map +1 -0
  44. package/dist/agentic/types.d.ts +157 -0
  45. package/dist/agentic/types.js +7 -0
  46. package/dist/agentic/types.js.map +1 -0
  47. package/dist/agentic/workflow-catalog.d.ts +152 -0
  48. package/dist/agentic/workflow-catalog.js +7 -0
  49. package/dist/agentic/workflow-catalog.js.map +1 -0
  50. package/dist/agentic/workflow-compiler.d.ts +44 -0
  51. package/dist/agentic/workflow-compiler.js +8 -0
  52. package/dist/agentic/workflow-compiler.js.map +1 -0
  53. package/dist/agentic/workflow-coordinator.d.ts +170 -0
  54. package/dist/agentic/workflow-coordinator.js +8 -0
  55. package/dist/agentic/workflow-coordinator.js.map +1 -0
  56. package/dist/agentic/workflow-manager.d.ts +91 -0
  57. package/dist/agentic/workflow-manager.js +7 -0
  58. package/dist/agentic/workflow-manager.js.map +1 -0
  59. package/dist/agentic/workflow-registry.d.ts +334 -0
  60. package/dist/agentic/workflow-registry.js +7 -0
  61. package/dist/agentic/workflow-registry.js.map +1 -0
  62. package/dist/artifacts-CteHmCMI.d.ts +614 -0
  63. package/dist/auth-hooks/api-key.d.ts +75 -0
  64. package/dist/auth-hooks/api-key.js +7 -0
  65. package/dist/auth-hooks/api-key.js.map +1 -0
  66. package/dist/auth-hooks/index.d.ts +80 -0
  67. package/dist/auth-hooks/index.js +28 -0
  68. package/dist/auth-hooks/index.js.map +1 -0
  69. package/dist/browser-auth/account-memberships.d.ts +213 -0
  70. package/dist/browser-auth/account-memberships.js +13 -0
  71. package/dist/browser-auth/account-memberships.js.map +1 -0
  72. package/dist/browser-auth/index.d.ts +8 -0
  73. package/dist/browser-auth/index.js +59 -0
  74. package/dist/browser-auth/index.js.map +1 -0
  75. package/dist/browser-auth/kratos-session.d.ts +37 -0
  76. package/dist/browser-auth/kratos-session.js +7 -0
  77. package/dist/browser-auth/kratos-session.js.map +1 -0
  78. package/dist/browser-auth/platform-session.d.ts +120 -0
  79. package/dist/browser-auth/platform-session.js +7 -0
  80. package/dist/browser-auth/platform-session.js.map +1 -0
  81. package/dist/browser-auth/public-memberships.d.ts +22 -0
  82. package/dist/browser-auth/public-memberships.js +7 -0
  83. package/dist/browser-auth/public-memberships.js.map +1 -0
  84. package/dist/cache/index.d.ts +181 -0
  85. package/dist/cache/index.js +197 -0
  86. package/dist/cache/index.js.map +1 -0
  87. package/dist/chunk-32746UQZ.js +131 -0
  88. package/dist/chunk-32746UQZ.js.map +1 -0
  89. package/dist/chunk-3NLSWP2Y.js +223 -0
  90. package/dist/chunk-3NLSWP2Y.js.map +1 -0
  91. package/dist/chunk-3P4XTTQH.js +346 -0
  92. package/dist/chunk-3P4XTTQH.js.map +1 -0
  93. package/dist/chunk-3VITSHN3.js +15 -0
  94. package/dist/chunk-3VITSHN3.js.map +1 -0
  95. package/dist/chunk-46UWPEW2.js +226 -0
  96. package/dist/chunk-46UWPEW2.js.map +1 -0
  97. package/dist/chunk-4BARRLJR.js +180 -0
  98. package/dist/chunk-4BARRLJR.js.map +1 -0
  99. package/dist/chunk-4VORUFKR.js +45 -0
  100. package/dist/chunk-4VORUFKR.js.map +1 -0
  101. package/dist/chunk-55D4ERWO.js +1 -0
  102. package/dist/chunk-55D4ERWO.js.map +1 -0
  103. package/dist/chunk-5TBBZIND.js +18 -0
  104. package/dist/chunk-5TBBZIND.js.map +1 -0
  105. package/dist/chunk-5WOZWPZA.js +211 -0
  106. package/dist/chunk-5WOZWPZA.js.map +1 -0
  107. package/dist/chunk-6CBVZ6CT.js +168 -0
  108. package/dist/chunk-6CBVZ6CT.js.map +1 -0
  109. package/dist/chunk-6XZXYNJR.js +74 -0
  110. package/dist/chunk-6XZXYNJR.js.map +1 -0
  111. package/dist/chunk-753HWDSC.js +222 -0
  112. package/dist/chunk-753HWDSC.js.map +1 -0
  113. package/dist/chunk-7AHSS7SO.js +81 -0
  114. package/dist/chunk-7AHSS7SO.js.map +1 -0
  115. package/dist/chunk-7FTJN4SA.js +1 -0
  116. package/dist/chunk-7FTJN4SA.js.map +1 -0
  117. package/dist/chunk-AVDMLTPF.js +24 -0
  118. package/dist/chunk-AVDMLTPF.js.map +1 -0
  119. package/dist/chunk-BKAHUEIT.js +95 -0
  120. package/dist/chunk-BKAHUEIT.js.map +1 -0
  121. package/dist/chunk-CJ7OFEF7.js +134 -0
  122. package/dist/chunk-CJ7OFEF7.js.map +1 -0
  123. package/dist/chunk-EJKWDZIU.js +111 -0
  124. package/dist/chunk-EJKWDZIU.js.map +1 -0
  125. package/dist/chunk-F2J6IQ6I.js +247 -0
  126. package/dist/chunk-F2J6IQ6I.js.map +1 -0
  127. package/dist/chunk-F3O7CELI.js +23 -0
  128. package/dist/chunk-F3O7CELI.js.map +1 -0
  129. package/dist/chunk-F4IITPGX.js +221 -0
  130. package/dist/chunk-F4IITPGX.js.map +1 -0
  131. package/dist/chunk-FD6VC2NA.js +66 -0
  132. package/dist/chunk-FD6VC2NA.js.map +1 -0
  133. package/dist/chunk-FRRRWAHO.js +14 -0
  134. package/dist/chunk-FRRRWAHO.js.map +1 -0
  135. package/dist/chunk-HCKAGLLB.js +17 -0
  136. package/dist/chunk-HCKAGLLB.js.map +1 -0
  137. package/dist/chunk-HVC7FG6B.js +191 -0
  138. package/dist/chunk-HVC7FG6B.js.map +1 -0
  139. package/dist/chunk-HXFVOR7Z.js +496 -0
  140. package/dist/chunk-HXFVOR7Z.js.map +1 -0
  141. package/dist/chunk-IJWYS2PF.js +122 -0
  142. package/dist/chunk-IJWYS2PF.js.map +1 -0
  143. package/dist/chunk-INCHXAFK.js +1395 -0
  144. package/dist/chunk-INCHXAFK.js.map +1 -0
  145. package/dist/chunk-JT6BRGQM.js +1 -0
  146. package/dist/chunk-JT6BRGQM.js.map +1 -0
  147. package/dist/chunk-L6PMAEMB.js +115 -0
  148. package/dist/chunk-L6PMAEMB.js.map +1 -0
  149. package/dist/chunk-LOUGW6MU.js +126 -0
  150. package/dist/chunk-LOUGW6MU.js.map +1 -0
  151. package/dist/chunk-LYPZPE53.js +129 -0
  152. package/dist/chunk-LYPZPE53.js.map +1 -0
  153. package/dist/chunk-NNCCN7JP.js +186 -0
  154. package/dist/chunk-NNCCN7JP.js.map +1 -0
  155. package/dist/chunk-PBC3MZUL.js +212 -0
  156. package/dist/chunk-PBC3MZUL.js.map +1 -0
  157. package/dist/chunk-R4ADP2DC.js +20 -0
  158. package/dist/chunk-R4ADP2DC.js.map +1 -0
  159. package/dist/chunk-RHN4Y6VS.js +44 -0
  160. package/dist/chunk-RHN4Y6VS.js.map +1 -0
  161. package/dist/chunk-SDJNYPYK.js +770 -0
  162. package/dist/chunk-SDJNYPYK.js.map +1 -0
  163. package/dist/chunk-UGNTCOVR.js +28 -0
  164. package/dist/chunk-UGNTCOVR.js.map +1 -0
  165. package/dist/chunk-VC2PCK2S.js +31 -0
  166. package/dist/chunk-VC2PCK2S.js.map +1 -0
  167. package/dist/chunk-VF5YDZJC.js +305 -0
  168. package/dist/chunk-VF5YDZJC.js.map +1 -0
  169. package/dist/chunk-VISRDVTK.js +675 -0
  170. package/dist/chunk-VISRDVTK.js.map +1 -0
  171. package/dist/chunk-W6O3LVBY.js +102 -0
  172. package/dist/chunk-W6O3LVBY.js.map +1 -0
  173. package/dist/chunk-WFEAKJLR.js +47 -0
  174. package/dist/chunk-WFEAKJLR.js.map +1 -0
  175. package/dist/chunk-XIEY2OF4.js +67 -0
  176. package/dist/chunk-XIEY2OF4.js.map +1 -0
  177. package/dist/chunk-XITLHDG3.js +37 -0
  178. package/dist/chunk-XITLHDG3.js.map +1 -0
  179. package/dist/chunk-XMWPYZWZ.js +61 -0
  180. package/dist/chunk-XMWPYZWZ.js.map +1 -0
  181. package/dist/chunk-XUP6CNOM.js +34 -0
  182. package/dist/chunk-XUP6CNOM.js.map +1 -0
  183. package/dist/chunk-YABTQZDJ.js +25 -0
  184. package/dist/chunk-YABTQZDJ.js.map +1 -0
  185. package/dist/chunk-YMHVRBUU.js +199 -0
  186. package/dist/chunk-YMHVRBUU.js.map +1 -0
  187. package/dist/chunk-YMJ7BRKU.js +510 -0
  188. package/dist/chunk-YMJ7BRKU.js.map +1 -0
  189. package/dist/chunk-ZC3XWU7B.js +28 -0
  190. package/dist/chunk-ZC3XWU7B.js.map +1 -0
  191. package/dist/chunk-ZHMTD5KV.js +90 -0
  192. package/dist/chunk-ZHMTD5KV.js.map +1 -0
  193. package/dist/chunk-ZWZDLOE7.js +160 -0
  194. package/dist/chunk-ZWZDLOE7.js.map +1 -0
  195. package/dist/db-package/db/local-first-sqlite-adapter.d.ts +432 -0
  196. package/dist/db-package/db/local-first-sqlite-adapter.js +7 -0
  197. package/dist/db-package/db/local-first-sqlite-adapter.js.map +1 -0
  198. package/dist/db-package/index.d.ts +7 -0
  199. package/dist/db-package/index.js +16 -0
  200. package/dist/db-package/index.js.map +1 -0
  201. package/dist/db-package/migration/aggregator.d.ts +86 -0
  202. package/dist/db-package/migration/aggregator.js +7 -0
  203. package/dist/db-package/migration/aggregator.js.map +1 -0
  204. package/dist/db-package/migration/index.d.ts +3 -0
  205. package/dist/db-package/migration/index.js +8 -0
  206. package/dist/db-package/migration/index.js.map +1 -0
  207. package/dist/engine.d.ts +205 -0
  208. package/dist/engine.js +20 -0
  209. package/dist/engine.js.map +1 -0
  210. package/dist/entitlements/index.d.ts +313 -0
  211. package/dist/entitlements/index.js +23 -0
  212. package/dist/entitlements/index.js.map +1 -0
  213. package/dist/execution/chat.d.ts +7 -0
  214. package/dist/execution/chat.js +7 -0
  215. package/dist/execution/chat.js.map +1 -0
  216. package/dist/execution/index.d.ts +342 -0
  217. package/dist/execution/index.js +66 -0
  218. package/dist/execution/index.js.map +1 -0
  219. package/dist/execution/tool-agent.d.ts +7 -0
  220. package/dist/execution/tool-agent.js +8 -0
  221. package/dist/execution/tool-agent.js.map +1 -0
  222. package/dist/extensions/index.d.ts +172 -0
  223. package/dist/extensions/index.js +95 -0
  224. package/dist/extensions/index.js.map +1 -0
  225. package/dist/health/index.d.ts +35 -0
  226. package/dist/health/index.js +7 -0
  227. package/dist/health/index.js.map +1 -0
  228. package/dist/index.d.ts +43 -0
  229. package/dist/index.js +161 -0
  230. package/dist/index.js.map +1 -0
  231. package/dist/lifecycle/index.d.ts +133 -0
  232. package/dist/lifecycle/index.js +13 -0
  233. package/dist/lifecycle/index.js.map +1 -0
  234. package/dist/lifecycle-engine/backend-migration.d.ts +2 -0
  235. package/dist/lifecycle-engine/backend-migration.js +11 -0
  236. package/dist/lifecycle-engine/backend-migration.js.map +1 -0
  237. package/dist/lifecycle-engine/baseline.d.ts +2 -0
  238. package/dist/lifecycle-engine/baseline.js +9 -0
  239. package/dist/lifecycle-engine/baseline.js.map +1 -0
  240. package/dist/lifecycle-engine/index.d.ts +1497 -0
  241. package/dist/lifecycle-engine/index.js +41 -0
  242. package/dist/lifecycle-engine/index.js.map +1 -0
  243. package/dist/lifecycle-engine/platform/artifacts.d.ts +4 -0
  244. package/dist/lifecycle-engine/platform/artifacts.js +7 -0
  245. package/dist/lifecycle-engine/platform/artifacts.js.map +1 -0
  246. package/dist/lifecycle-engine/platform/control-plane.d.ts +12 -0
  247. package/dist/lifecycle-engine/platform/control-plane.js +2 -0
  248. package/dist/lifecycle-engine/platform/control-plane.js.map +1 -0
  249. package/dist/lifecycle-engine/platform/database-router.d.ts +118 -0
  250. package/dist/lifecycle-engine/platform/database-router.js +7 -0
  251. package/dist/lifecycle-engine/platform/database-router.js.map +1 -0
  252. package/dist/lifecycle-engine/platform/deployment-placements.d.ts +464 -0
  253. package/dist/lifecycle-engine/platform/deployment-placements.js +16 -0
  254. package/dist/lifecycle-engine/platform/deployment-placements.js.map +1 -0
  255. package/dist/lifecycle-engine/platform/deployment.d.ts +4 -0
  256. package/dist/lifecycle-engine/platform/deployment.js +17 -0
  257. package/dist/lifecycle-engine/platform/deployment.js.map +1 -0
  258. package/dist/lifecycle-engine/platform/index.d.ts +737 -0
  259. package/dist/lifecycle-engine/platform/index.js +60 -0
  260. package/dist/lifecycle-engine/platform/index.js.map +1 -0
  261. package/dist/lifecycle-engine/platform/runtime.d.ts +80 -0
  262. package/dist/lifecycle-engine/platform/runtime.js +11 -0
  263. package/dist/lifecycle-engine/platform/runtime.js.map +1 -0
  264. package/dist/lifecycle-engine/platform/site-publication.d.ts +102 -0
  265. package/dist/lifecycle-engine/platform/site-publication.js +7 -0
  266. package/dist/lifecycle-engine/platform/site-publication.js.map +1 -0
  267. package/dist/lifecycle-engine/platform/user-directory.d.ts +139 -0
  268. package/dist/lifecycle-engine/platform/user-directory.js +13 -0
  269. package/dist/lifecycle-engine/platform/user-directory.js.map +1 -0
  270. package/dist/mcp.d.ts +92 -0
  271. package/dist/mcp.js +10 -0
  272. package/dist/mcp.js.map +1 -0
  273. package/dist/middleware/auth.d.ts +118 -0
  274. package/dist/middleware/auth.js +7 -0
  275. package/dist/middleware/auth.js.map +1 -0
  276. package/dist/middleware/error-handler.d.ts +35 -0
  277. package/dist/middleware/error-handler.js +7 -0
  278. package/dist/middleware/error-handler.js.map +1 -0
  279. package/dist/middleware/module-guard.d.ts +33 -0
  280. package/dist/middleware/module-guard.js +7 -0
  281. package/dist/middleware/module-guard.js.map +1 -0
  282. package/dist/platform-admin/index.d.ts +37 -0
  283. package/dist/platform-admin/index.js +11 -0
  284. package/dist/platform-admin/index.js.map +1 -0
  285. package/dist/platform-admin/store.d.ts +346 -0
  286. package/dist/platform-admin/store.js +7 -0
  287. package/dist/platform-admin/store.js.map +1 -0
  288. package/dist/plugin-data/annotations.d.ts +6 -0
  289. package/dist/plugin-data/annotations.js +12 -0
  290. package/dist/plugin-data/annotations.js.map +1 -0
  291. package/dist/plugin-data/atomic-context.d.ts +41 -0
  292. package/dist/plugin-data/atomic-context.js +9 -0
  293. package/dist/plugin-data/atomic-context.js.map +1 -0
  294. package/dist/plugin-data/atomic.d.ts +6 -0
  295. package/dist/plugin-data/atomic.js +26 -0
  296. package/dist/plugin-data/atomic.js.map +1 -0
  297. package/dist/plugin-data/audit.d.ts +6 -0
  298. package/dist/plugin-data/audit.js +12 -0
  299. package/dist/plugin-data/audit.js.map +1 -0
  300. package/dist/plugin-data/commands.d.ts +6 -0
  301. package/dist/plugin-data/commands.js +8 -0
  302. package/dist/plugin-data/commands.js.map +1 -0
  303. package/dist/plugin-data/composite.d.ts +6 -0
  304. package/dist/plugin-data/composite.js +8 -0
  305. package/dist/plugin-data/composite.js.map +1 -0
  306. package/dist/plugin-data/delivery.d.ts +6 -0
  307. package/dist/plugin-data/delivery.js +16 -0
  308. package/dist/plugin-data/delivery.js.map +1 -0
  309. package/dist/plugin-data/index.d.ts +2798 -0
  310. package/dist/plugin-data/index.js +102 -0
  311. package/dist/plugin-data/index.js.map +1 -0
  312. package/dist/plugin-data/json-documents.d.ts +6 -0
  313. package/dist/plugin-data/json-documents.js +16 -0
  314. package/dist/plugin-data/json-documents.js.map +1 -0
  315. package/dist/plugin-data/outbox.d.ts +6 -0
  316. package/dist/plugin-data/outbox.js +16 -0
  317. package/dist/plugin-data/outbox.js.map +1 -0
  318. package/dist/plugin-data/scoped-records.d.ts +6 -0
  319. package/dist/plugin-data/scoped-records.js +10 -0
  320. package/dist/plugin-data/scoped-records.js.map +1 -0
  321. package/dist/plugin-sdk.d.ts +41 -0
  322. package/dist/plugin-sdk.js +10 -0
  323. package/dist/plugin-sdk.js.map +1 -0
  324. package/dist/sql-lifecycle/index.d.ts +138 -0
  325. package/dist/sql-lifecycle/index.js +167 -0
  326. package/dist/sql-lifecycle/index.js.map +1 -0
  327. package/dist/storage/index.d.ts +2 -0
  328. package/dist/storage/index.js +13 -0
  329. package/dist/storage/index.js.map +1 -0
  330. package/dist/storage/s3-compatible.d.ts +139 -0
  331. package/dist/storage/s3-compatible.js +11 -0
  332. package/dist/storage/s3-compatible.js.map +1 -0
  333. package/dist/tenant.d.ts +108 -0
  334. package/dist/tenant.js +9 -0
  335. package/dist/tenant.js.map +1 -0
  336. package/dist/workspace-context.d.ts +119 -0
  337. package/dist/workspace-context.js +9 -0
  338. package/dist/workspace-context.js.map +1 -0
  339. package/docs/api.md +30560 -0
  340. package/docs/db/README.md +49 -0
  341. package/docs/db/docs/api.md +1613 -0
  342. package/docs/db/docs/guide.md +47 -0
  343. package/docs/entitlements.md +60 -0
  344. package/docs/guide.md +92 -0
  345. package/docs/index.md +57 -0
  346. package/docs/ja/db/README.md +46 -0
  347. package/docs/ja/db/docs/guide.md +53 -0
  348. package/docs/ja/guide.md +46 -0
  349. package/docs/ja/lifecycle/README.md +46 -0
  350. package/docs/ja/lifecycle/docs/guide.md +45 -0
  351. package/docs/ja/storage/README.md +46 -0
  352. package/docs/ja/storage/docs/guide.md +43 -0
  353. package/docs/lifecycle/README.md +49 -0
  354. package/docs/lifecycle/docs/api.md +3770 -0
  355. package/docs/lifecycle/docs/baseline.md +50 -0
  356. package/docs/lifecycle/docs/guide.md +47 -0
  357. package/docs/storage/README.md +49 -0
  358. package/docs/storage/docs/api.md +470 -0
  359. package/docs/storage/docs/guide.md +47 -0
  360. package/package.json +354 -4
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lifecycle-engine/platform/deployment.ts"],"sourcesContent":["import type { DeploymentInventory } from './artifacts'\n\n/**\n * Supported deployment capability categories used to validate component declarations.\n * \n * @see summarizeDeployment for canonical integration usage.\n */\nexport const deploymentComponentKinds = ['frontend', 'api', 'mcp', 'service', 'function', 'worker', 'job', 'webhook', 'workflow', 'database', 'infrastructure', 'storage', 'cache', 'queue', 'search', 'integration', 'native', 'model', 'data-import'] as const\n/**\n * Supported declarative work phases; inspection never executes these actions.\n * \n * @see summarizeDeployment for canonical integration usage.\n */\nexport const deploymentActions = ['build', 'test', 'preview', 'provision', 'configure', 'migrate', 'deploy', 'verify', 'import', 'enable'] as const\n/**\n * One declared deployable capability with explicit placement and nonsecret host requirements.\n * \n * @see summarizeDeployment for canonical integration usage.\n */\nexport interface DeploymentComponent {\n /**\n * Unique component ID within the plugin.\n */\n id: string\n /**\n * False marks an optional capability; omitted means required.\n * \n * Optional provider/native capabilities remain visible without requiring every deployment to adopt them.\n */\n required?: boolean\n /**\n * Supported frontend/server/storage/compute capability category.\n */\n kind: typeof deploymentComponentKinds[number]\n /**\n * Declared host/container/function/database/cloud/native/external placement.\n */\n placement: 'host' | 'container' | 'function' | 'database' | 'cloud' | 'native' | 'external'\n /**\n * Optional runtime descriptor.\n */\n runtime?: string\n /**\n * Exact checksummed inventory asset references.\n * \n * References to files in the checksummed inventory, not arbitrary source paths.\n */\n assets?: string[]\n /**\n * Author-side asset selectors resolved by packing; unresolved patterns prevent completion.\n * \n * Author-side selectors resolved to exact assets by the packer; emitted inventories omit these.\n */\n assetPatterns?: string[]\n /**\n * Optional entry asset path.\n */\n entry?: string\n /**\n * Canonical schema contract IDs and semver ranges, never copied DDL.\n * \n * Canonical contract IDs/ranges; no copied DDL.\n */\n dataContracts?: Record<string, string>\n /**\n * Optional required tool ranges and host binding/adapter names.\n */\n requirements?: { \n /**\n * Tool-name to required-version/range map declared by the plugin.\n */\n tools?: Record<string, string>; \n /**\n * Required nonsecret host binding names; never credential values.\n */\n bindings?: string[]; \n /**\n * Required host adapter capability names.\n */\n adapters?: string[] }\n}\n/**\n * Declarative host-approved work and dependency ordering for deployment evidence.\n * \n * @see summarizeDeployment for canonical integration usage.\n */\nexport interface DeploymentTask {\n /**\n * Unique task ID within the plugin.\n */\n id: string\n /**\n * Existing components whose work this task covers.\n */\n componentIds: string[]\n /**\n * Supported build/test/provision/deploy/etc. phase.\n */\n action: typeof deploymentActions[number]\n /**\n * Artifact work is reusable; environment and tenant work require corresponding target evidence.\n */\n scope: 'artifact' | 'environment' | 'tenant'\n /**\n * Whether successful task evidence is required for completion.\n */\n required: boolean\n /**\n * Existing task IDs that must succeed before this task is considered unblocked.\n */\n dependsOn: string[]\n /**\n * Host-approved executor reference; inspection never launches it.\n * \n * Host-approved executor reference. Inspection never executes it or argv.\n */\n executor: string\n /**\n * Optional declarative arguments; never automatically executed by inspection.\n */\n argv?: string[]\n /**\n * Optional human operator instructions.\n */\n instructions?: string\n}\n/**\n * Classified deployment component/task graph for one lifecycle feature.\n * \n * @see summarizeDeployment for canonical integration usage.\n */\nexport interface DeploymentPlugin {\n /**\n * Plugin ID covered by the inventory lifecycle bundle.\n */\n id: string;\n /**\n * Unique deployable capability definitions.\n */\n components: DeploymentComponent[];\n /**\n * Unique work definitions forming an acyclic dependency graph.\n */\n tasks: DeploymentTask[] }\n/**\n * Nonsecret exact environment, physical placement and optional tenant context for scoped evidence.\n * \n * @see summarizeDeployment for canonical integration usage.\n */\nexport interface DeploymentTarget {\n /**\n * Nonblank deployment environment label.\n */\n environment: string;\n /**\n * Optional exact lifecycle backend ID; required for database work evidence.\n */\n backendId?: string;\n /**\n * Optional physical database identity; required with backendId for database evidence.\n */\n databaseId?: string;\n /**\n * Optional concrete tenant; required for tenant tasks and absent for environment tasks.\n */\n tenantId?: string }\n/**\n * Reported execution evidence bound to a task, inventory and optional destination revision.\n * \n * @see summarizeDeployment for canonical integration usage.\n */\nexport interface DeploymentResult {\n /**\n * Declared inventory plugin ID.\n */\n pluginId: string\n /**\n * Declared plugin task ID.\n */\n taskId: string\n /**\n * Exact environment/tenant target; absent for artifact work.\n */\n target?: DeploymentTarget\n /**\n * Reported running/succeeded/failed result; no independent execution proof is implied.\n */\n status: 'running' | 'succeeded' | 'failed'\n /**\n * Exact UTC ISO timestamp including millisecond precision; increases per task/target/placement.\n */\n recordedAt: string\n /**\n * Nonblank host/operator identity reporting the result.\n */\n actor: string\n /**\n * Nonempty distinct nonsecret evidence references, such as reviewed logs or CI receipts.\n * \n * Non-secret evidence references, such as a reviewed log, CI run or lifecycle plan receipt.\n */\n evidence: string[]\n /**\n * Optional explicit destination identity paired with placementSha256; forbidden for artifact results.\n * \n * Environment/tenant evidence bound to a reviewed component placement. Artifact results remain reusable.\n */\n destinationId?: string\n /**\n * Hash of reviewed placement/binding revisions paired with destinationId.\n */\n placementSha256?: string\n}\n/**\n * Operator/host-owned reported evidence journal pinned to one inventory digest.\n * \n * \n * Host/operator-owned journal. This is reported evidence, never runtime admission authority.\n * @see summarizeDeployment for canonical integration usage.\n */\nexport interface DeploymentReceipt {\n /**\n * Receipt discriminator; currently 1.\n */\n apiVersion: 1\n /**\n * Exact inventory owner to which these results belong.\n */\n owner: string\n /**\n * Lowercase 64-character SHA-256 of the trusted inventory bytes.\n */\n inventorySha256: string\n /**\n * Reported task outcomes in increasing per-task/target/placement timestamp order.\n */\n results: DeploymentResult[]\n}\n/**\n * Derived task readiness: pending, dependency-blocked, stale evidence, running, succeeded or failed.\n * \n * @see summarizeDeployment for canonical integration usage.\n */\nexport type DeploymentTaskStatus = 'pending' | 'blocked' | 'stale' | 'running' | 'succeeded' | 'failed'\n\nfunction object(value: unknown): value is Record<string, any> { return !!value && typeof value === 'object' && !Array.isArray(value) }\nfunction nonempty(value: unknown): value is string { return typeof value === 'string' && !!value.trim() && value === value.trim() }\nfunction id(value: unknown): value is string { return nonempty(value) && /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(value) }\nfunction strings(value: unknown, allowEmpty = true): value is string[] { return Array.isArray(value) && (allowEmpty || !!value.length) && value.every(nonempty) && new Set(value).size === value.length }\nfunction fields(value: object, allowed: string[]) { if (Object.keys(value).some(key => !allowed.includes(key))) throw new Error('Unknown deployment declaration field') }\nfunction mapping(value: unknown) { return object(value) && Object.entries(value).every(([key, v]) => nonempty(key) && nonempty(v)) }\nfunction targetKey(target?: DeploymentTarget) { return JSON.stringify([target?.environment ?? null, target?.backendId ?? null, target?.databaseId ?? null, target?.tenantId ?? null]) }\n\n/**\n * Validates declared plugin component references and task dependencies before artifact inspection.\n * \n * Validate references and the dependency DAG before artifact registration or status inspection.\n * @param inventory - Deployment inventory with checksummed asset metadata and optional per-plugin work declarations.\n * @returns The original plugin array, or undefined for legacy inventories without plugin declarations.\n * @throws Error for invalid/duplicate declarations, unsupported component/action/scope, unknown references, cycles or missing required work.\n * \n * @remarks\n * Requires explicit lifecycle-bundle coverage, known assets/components, acyclic dependencies and work for adopted components. This validates declarations without executing tasks or proving artifact file checksums.\n * \n * @example\n * ```typescript\n * import { validateDeploymentPlugins, type DeploymentInventory } from '@alneas/eaos-server/platform';\n * export function inspectDeclaration(inventory: DeploymentInventory) { return validateDeploymentPlugins(inventory); }\n * ```\n */\nexport function validateDeploymentPlugins(inventory: DeploymentInventory): DeploymentPlugin[] | undefined {\n if (inventory.plugins === undefined) return undefined\n if (!Array.isArray(inventory.plugins) || !inventory.plugins.length || !strings(inventory.lifecycleBundle, false)\n || inventory.plugins.length !== inventory.lifecycleBundle.length) throw new Error('Deployment plugins must cover the lifecycle bundle')\n const pluginIds = new Set<string>(), assets = new Set(inventory.assets.map(asset => asset.path))\n for (const plugin of inventory.plugins) {\n if (!object(plugin) || !id(plugin.id) || pluginIds.has(plugin.id) || !inventory.lifecycleBundle.includes(plugin.id)\n || !Array.isArray(plugin.components) || !Array.isArray(plugin.tasks)) throw new Error('Invalid or duplicate deployment plugin')\n fields(plugin, ['id', 'components', 'tasks'])\n pluginIds.add(plugin.id)\n const components = new Set<string>(), tasks = new Map<string, DeploymentTask>()\n for (const component of plugin.components) {\n if (!object(component) || !id(component.id) || components.has(component.id) || !deploymentComponentKinds.includes(component.kind)\n || (component.required !== undefined && typeof component.required !== 'boolean')\n || !['host', 'container', 'function', 'database', 'cloud', 'native', 'external'].includes(component.placement)\n || (component.runtime !== undefined && !nonempty(component.runtime))\n || (component.assets !== undefined && (!strings(component.assets) || component.assets.some(path => !assets.has(path))))\n || (component.assetPatterns !== undefined && (!strings(component.assetPatterns, false) || component.assetPatterns.some(pattern => pattern.startsWith('/') || pattern.includes('\\\\') || pattern.split('/').some(part => !part || part === '.' || part === '..'))))\n || (component.entry !== undefined && (!nonempty(component.entry) || !assets.has(component.entry)))\n || (component.dataContracts !== undefined && !mapping(component.dataContracts))) throw new Error('Invalid deployment component or unverified asset reference')\n fields(component, ['id', 'kind', 'required', 'placement', 'runtime', 'assets', 'assetPatterns', 'entry', 'dataContracts', 'requirements'])\n if (component.requirements !== undefined) {\n const req = component.requirements\n if (!object(req) || (req.tools !== undefined && !mapping(req.tools)) || (req.bindings !== undefined && (!strings(req.bindings) || req.bindings.some(key => !/^[A-Z][A-Z0-9_]*$/.test(key))))\n || (req.adapters !== undefined && !strings(req.adapters))) throw new Error('Invalid deployment requirements; declare references, not secret values')\n fields(req, ['tools', 'bindings', 'adapters'])\n }\n components.add(component.id)\n }\n for (const task of plugin.tasks) {\n if (!object(task) || !id(task.id) || tasks.has(task.id) || !strings(task.componentIds, false) || task.componentIds.some(ref => !components.has(ref))\n || !deploymentActions.includes(task.action) || !['artifact', 'environment', 'tenant'].includes(task.scope) || typeof task.required !== 'boolean'\n || !strings(task.dependsOn) || !nonempty(task.executor) || (task.argv !== undefined && (!Array.isArray(task.argv) || !task.argv.length || task.argv.some(arg => typeof arg !== 'string')))\n || (task.instructions !== undefined && !nonempty(task.instructions))) throw new Error('Invalid deployment task or component reference')\n fields(task, ['id', 'componentIds', 'action', 'scope', 'required', 'dependsOn', 'executor', 'argv', 'instructions'])\n if (task.scope === 'artifact' && !['build', 'test', 'verify'].includes(task.action)) throw new Error('Environment-changing work cannot have artifact scope')\n tasks.set(task.id, task)\n }\n const visiting = new Set<string>(), visited = new Set<string>(), scopeRank = { artifact: 0, environment: 1, tenant: 2 }\n const visit = (task: DeploymentTask) => {\n if (visiting.has(task.id)) throw new Error('Cyclic deployment task dependency')\n if (visited.has(task.id)) return\n visiting.add(task.id)\n for (const ref of task.dependsOn) {\n const dependency = tasks.get(ref)\n if (!dependency) throw new Error('Unknown deployment task dependency')\n if (scopeRank[dependency.scope] > scopeRank[task.scope]) throw new Error('Deployment dependency has a narrower target scope')\n visit(dependency)\n }\n visiting.delete(task.id); visited.add(task.id)\n }\n for (const task of tasks.values()) visit(task)\n if (plugin.components.some(component => !plugin.tasks.some(task => (component.required === false || task.required) && task.componentIds.includes(component.id)))) throw new Error('Every required deployment component requires at least one required task; optional components still require declared work')\n if (!components.size && tasks.size) throw new Error('Tasks require deployment components')\n }\n return inventory.plugins\n}\n\n/**\n * Validates the exact nonsecret environment/backend/database/tenant target shape.\n * @param value - Untrusted target object with a nonblank environment and optional nonblank identity references.\n * @returns Completes without a value and narrows the input to DeploymentTarget.\n * @throws Error for missing/blank identity fields or unknown target properties.\n * \n * @remarks\n * Does not resolve backend existence, tenant membership or deployment authority.\n * \n * @example\n * ```typescript\n * import { validateDeploymentTarget } from '@alneas/eaos-server/platform/deployment';\n * const target: unknown = { environment: 'review' };\n * validateDeploymentTarget(target);\n * ```\n */\nexport function validateDeploymentTarget(value: unknown): asserts value is DeploymentTarget {\n if (!object(value) || !nonempty(value.environment) || ['backendId', 'databaseId', 'tenantId'].some(key => value[key] !== undefined && !nonempty(value[key]))) throw new Error('Invalid deployment target')\n fields(value, ['environment', 'backendId', 'databaseId', 'tenantId'])\n}\n/**\n * Validates version-1 reported task evidence and strictly increasing timestamps per task/target/placement.\n * @param value - Untrusted receipt with owner, pinned inventory SHA-256 and task result records.\n * @returns Completes without a value and narrows the input to DeploymentReceipt.\n * @throws Error for malformed/extra fields, invalid hashes/timestamps, missing evidence or nonincreasing repeated-result timestamps.\n * \n * @remarks\n * Each result needs a UTC millisecond ISO timestamp, actor and nonempty distinct evidence references. destinationId and placementSha256 must occur together. This validates shape/order only; it does not independently verify evidence or grant runtime admission.\n * \n * @example\n * ```typescript\n * import { validateDeploymentReceipt } from '@alneas/eaos-server/platform/deployment';\n * const receipt: unknown = { apiVersion: 1, owner: 'reports', inventorySha256: 'a'.repeat(64), results: [] };\n * validateDeploymentReceipt(receipt);\n * ```\n */\nexport function validateDeploymentReceipt(value: unknown): asserts value is DeploymentReceipt {\n if (!object(value) || value.apiVersion !== 1 || !nonempty(value.owner) || typeof value.inventorySha256 !== 'string' || !/^[a-f0-9]{64}$/.test(value.inventorySha256) || !Array.isArray(value.results)) throw new Error('Invalid deployment receipt')\n fields(value, ['apiVersion', 'owner', 'inventorySha256', 'results'])\n const times = new Map<string, number>()\n for (const result of value.results) {\n if (!object(result) || !id(result.pluginId) || !id(result.taskId) || !['running', 'succeeded', 'failed'].includes(result.status)\n || !nonempty(result.actor) || !strings(result.evidence, false) || !nonempty(result.recordedAt)\n || !/^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d\\.\\d{3}Z$/.test(result.recordedAt) || !Number.isFinite(Date.parse(result.recordedAt))\n || new Date(result.recordedAt).toISOString() !== result.recordedAt) throw new Error('Invalid deployment result; actor, timestamp and evidence are required')\n fields(result, ['pluginId', 'taskId', 'target', 'status', 'recordedAt', 'actor', 'evidence', 'destinationId', 'placementSha256'])\n if ((result.destinationId === undefined) !== (result.placementSha256 === undefined) || (result.destinationId !== undefined && (!id(result.destinationId) || !/^[a-f0-9]{64}$/.test(result.placementSha256!)))) throw Error('Placement evidence requires destinationId and placementSha256')\n if (result.target !== undefined) validateDeploymentTarget(result.target)\n const key = JSON.stringify([result.pluginId, result.taskId, targetKey(result.target), result.destinationId ?? null, result.placementSha256 ?? null])\n const time = Date.parse(result.recordedAt)\n if (time <= (times.get(key) ?? -Infinity)) throw new Error('Deployment result timestamps must increase for each task/target')\n times.set(key, time)\n }\n}\nfunction taskTarget(task: DeploymentTask, target?: DeploymentTarget): DeploymentTarget | undefined {\n if (task.scope === 'artifact') return undefined\n if (!target || (task.scope === 'tenant' && !target.tenantId)) return undefined\n const { tenantId: _tenantId, ...environment } = target\n return task.scope === 'tenant' ? target : environment\n}\n\n/**\n * Aggregates host/operator task evidence into dependency-aware plugin and component completion states.\n * \n * Aggregate operator/host evidence only. A build receipt cannot complete DB/infra/deployment tasks.\n * @param inventory - Validated artifact declaration; missing plugins remains legacy-unclassified.\n * @param inventorySha256 - Trusted lowercase 64-character inventory digest.\n * @param receipts - Reported receipts; defaults to none.\n * @param target - Optional current environment/backend/database/tenant context for scoped work.\n * @returns A read-only summary with coverage, artifact resolution, task states and ignored owner/stale-inventory/placement receipts.\n * @throws Error for invalid declarations/receipts/hash/target, undeclared tasks, scope mismatch or conflicting equal-time evidence.\n * \n * @remarks\n * No task executes. Artifact work is reusable; environment/tenant evidence must match scope and database work needs explicit backend/database identities. Newer dependency evidence makes older success stale. Completion is host-reported evidence, never admission authority.\n * \n * @example\n * ```typescript\n * import { summarizeDeployment, type DeploymentInventory, type DeploymentReceipt, type DeploymentTarget } from '@alneas/eaos-server/platform';\n * export function inspect(inventory: DeploymentInventory, digest: string, receipts: DeploymentReceipt[], target?: DeploymentTarget) { return summarizeDeployment(inventory, digest, receipts, target); }\n * ```\n */\nexport function summarizeDeployment(inventory: DeploymentInventory, inventorySha256: string, receipts: DeploymentReceipt[] = [], target?: DeploymentTarget) {\n if (!/^[a-f0-9]{64}$/.test(inventorySha256)) throw new Error('Invalid inventory SHA-256')\n const plugins = validateDeploymentPlugins(inventory)\n if (target !== undefined) validateDeploymentTarget(target)\n const results = new Map<string, DeploymentResult>(), ignoredReceipts: Array<{ owner: string; reason: string }> = []\n for (const receipt of receipts) {\n validateDeploymentReceipt(receipt)\n if (receipt.owner !== inventory.owner || receipt.inventorySha256 !== inventorySha256) {\n ignoredReceipts.push({ owner: receipt.owner, reason: receipt.owner !== inventory.owner ? 'different-owner' : 'stale-inventory' }); continue\n }\n for (const result of receipt.results) {\n const task = plugins?.find(plugin => plugin.id === result.pluginId)?.tasks.find(task => task.id === result.taskId)\n if (!task) throw new Error('Receipt references an undeclared deployment task')\n if (result.destinationId !== undefined) {\n if (task.scope === 'artifact') throw Error('Artifact evidence must not be bound to a destination')\n ignoredReceipts.push({ owner: receipt.owner, reason: 'placement-context-required' }); continue\n }\n if ((task.scope === 'artifact' && result.target !== undefined) || (task.scope !== 'artifact' && !result.target)\n || (task.scope === 'environment' && result.target?.tenantId !== undefined) || (task.scope === 'tenant' && !result.target?.tenantId)) throw new Error('Receipt target does not match task scope')\n const plugin = plugins!.find(plugin => plugin.id === result.pluginId)!\n if (task.scope !== 'artifact' && plugin.components.some(component => component.kind === 'database' && task.componentIds.includes(component.id))\n && (!result.target?.backendId || !result.target.databaseId)) throw new Error('Database work requires explicit backendId and databaseId evidence')\n const expected = taskTarget(task, target)\n if ((task.scope !== 'artifact' && !expected) || targetKey(result.target) !== targetKey(expected)) continue\n const key = JSON.stringify([result.pluginId, result.taskId]), old = results.get(key)\n if (old && old.recordedAt === result.recordedAt && JSON.stringify(old) !== JSON.stringify(result)) throw new Error('Conflicting deployment results at the same timestamp')\n if (!old || old.recordedAt < result.recordedAt) results.set(key, result)\n }\n }\n const summaries = (plugins ?? []).map(plugin => {\n const artifactResolved = !plugin.components.some(component => component.assetPatterns?.length)\n const states = new Map<string, { status: DeploymentTaskStatus; result?: DeploymentResult }>()\n const status = (task: DeploymentTask): { status: DeploymentTaskStatus; result?: DeploymentResult } => {\n const known = states.get(task.id)\n if (known) return known\n const result = results.get(JSON.stringify([plugin.id, task.id]))\n const dependencies = task.dependsOn.map(ref => status(plugin.tasks.find(task => task.id === ref)!))\n const blocked = dependencies.some(dependency => dependency.status !== 'succeeded')\n const stale = result?.status === 'succeeded' && dependencies.some(dependency => dependency.result && dependency.result.recordedAt > result.recordedAt)\n const state = { status: (blocked ? 'blocked' : stale ? 'stale' : result?.status ?? 'pending') as DeploymentTaskStatus, result }\n states.set(task.id, state); return state\n }\n const tasks = plugin.tasks.map(task => ({ ...task, ...status(task) }))\n return { id: plugin.id, artifactResolved, complete: artifactResolved && tasks.filter(task => task.required).every(task => task.status === 'succeeded'),\n components: plugin.components.map(component => ({ ...component, complete: artifactResolved && tasks.filter(task => (component.required === false || task.required) && task.componentIds.includes(component.id)).every(task => task.status === 'succeeded') })), tasks }\n })\n return { owner: inventory.owner, inventorySha256, target, coverage: plugins ? 'declared' as const : 'legacy-unclassified' as const,\n artifactResolved: !!plugins && summaries.every(plugin => plugin.artifactResolved), complete: !!plugins && summaries.every(plugin => plugin.complete), plugins: summaries, ignoredReceipts,\n evidencePolicy: 'Operator/host-reported evidence; not independent verification or runtime authorization' }\n}\n"],"mappings":";AAOO,IAAM,2BAA2B,CAAC,YAAY,OAAO,OAAO,WAAW,YAAY,UAAU,OAAO,WAAW,YAAY,YAAY,kBAAkB,WAAW,SAAS,SAAS,UAAU,eAAe,UAAU,SAAS,aAAa;AAM/O,IAAM,oBAAoB,CAAC,SAAS,QAAQ,WAAW,aAAa,aAAa,WAAW,UAAU,UAAU,UAAU,QAAQ;AAwOzI,SAAS,OAAO,OAA8C;AAAE,SAAO,CAAC,CAAC,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAAE;AACrI,SAAS,SAAS,OAAiC;AAAE,SAAO,OAAO,UAAU,YAAY,CAAC,CAAC,MAAM,KAAK,KAAK,UAAU,MAAM,KAAK;AAAE;AAClI,SAAS,GAAG,OAAiC;AAAE,SAAO,SAAS,KAAK,KAAK,+BAA+B,KAAK,KAAK;AAAE;AACpH,SAAS,QAAQ,OAAgB,aAAa,MAAyB;AAAE,SAAO,MAAM,QAAQ,KAAK,MAAM,cAAc,CAAC,CAAC,MAAM,WAAW,MAAM,MAAM,QAAQ,KAAK,IAAI,IAAI,KAAK,EAAE,SAAS,MAAM;AAAO;AACxM,SAAS,OAAO,OAAe,SAAmB;AAAE,MAAI,OAAO,KAAK,KAAK,EAAE,KAAK,SAAO,CAAC,QAAQ,SAAS,GAAG,CAAC,EAAG,OAAM,IAAI,MAAM,sCAAsC;AAAE;AACxK,SAAS,QAAQ,OAAgB;AAAE,SAAO,OAAO,KAAK,KAAK,OAAO,QAAQ,KAAK,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,SAAS,GAAG,KAAK,SAAS,CAAC,CAAC;AAAE;AACnI,SAAS,UAAU,QAA2B;AAAE,SAAO,KAAK,UAAU,CAAC,QAAQ,eAAe,MAAM,QAAQ,aAAa,MAAM,QAAQ,cAAc,MAAM,QAAQ,YAAY,IAAI,CAAC;AAAE;AAmB/K,SAAS,0BAA0B,WAAgE;AACxG,MAAI,UAAU,YAAY,OAAW,QAAO;AAC5C,MAAI,CAAC,MAAM,QAAQ,UAAU,OAAO,KAAK,CAAC,UAAU,QAAQ,UAAU,CAAC,QAAQ,UAAU,iBAAiB,KAAK,KAC1G,UAAU,QAAQ,WAAW,UAAU,gBAAgB,OAAQ,OAAM,IAAI,MAAM,oDAAoD;AACxI,QAAM,YAAY,oBAAI,IAAY,GAAG,SAAS,IAAI,IAAI,UAAU,OAAO,IAAI,WAAS,MAAM,IAAI,CAAC;AAC/F,aAAW,UAAU,UAAU,SAAS;AACtC,QAAI,CAAC,OAAO,MAAM,KAAK,CAAC,GAAG,OAAO,EAAE,KAAK,UAAU,IAAI,OAAO,EAAE,KAAK,CAAC,UAAU,gBAAgB,SAAS,OAAO,EAAE,KAC7G,CAAC,MAAM,QAAQ,OAAO,UAAU,KAAK,CAAC,MAAM,QAAQ,OAAO,KAAK,EAAG,OAAM,IAAI,MAAM,wCAAwC;AAChI,WAAO,QAAQ,CAAC,MAAM,cAAc,OAAO,CAAC;AAC5C,cAAU,IAAI,OAAO,EAAE;AACvB,UAAM,aAAa,oBAAI,IAAY,GAAG,QAAQ,oBAAI,IAA4B;AAC9E,eAAW,aAAa,OAAO,YAAY;AACzC,UAAI,CAAC,OAAO,SAAS,KAAK,CAAC,GAAG,UAAU,EAAE,KAAK,WAAW,IAAI,UAAU,EAAE,KAAK,CAAC,yBAAyB,SAAS,UAAU,IAAI,KAC1H,UAAU,aAAa,UAAa,OAAO,UAAU,aAAa,aACnE,CAAC,CAAC,QAAQ,aAAa,YAAY,YAAY,SAAS,UAAU,UAAU,EAAE,SAAS,UAAU,SAAS,KACzG,UAAU,YAAY,UAAa,CAAC,SAAS,UAAU,OAAO,KAC9D,UAAU,WAAW,WAAc,CAAC,QAAQ,UAAU,MAAM,KAAK,UAAU,OAAO,KAAK,UAAQ,CAAC,OAAO,IAAI,IAAI,CAAC,MAChH,UAAU,kBAAkB,WAAc,CAAC,QAAQ,UAAU,eAAe,KAAK,KAAK,UAAU,cAAc,KAAK,aAAW,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,IAAI,KAAK,QAAQ,MAAM,GAAG,EAAE,KAAK,UAAQ,CAAC,QAAQ,SAAS,OAAO,SAAS,IAAI,CAAC,MAC1P,UAAU,UAAU,WAAc,CAAC,SAAS,UAAU,KAAK,KAAK,CAAC,OAAO,IAAI,UAAU,KAAK,MAC3F,UAAU,kBAAkB,UAAa,CAAC,QAAQ,UAAU,aAAa,EAAI,OAAM,IAAI,MAAM,4DAA4D;AAC/J,aAAO,WAAW,CAAC,MAAM,QAAQ,YAAY,aAAa,WAAW,UAAU,iBAAiB,SAAS,iBAAiB,cAAc,CAAC;AACzI,UAAI,UAAU,iBAAiB,QAAW;AACxC,cAAM,MAAM,UAAU;AACtB,YAAI,CAAC,OAAO,GAAG,KAAM,IAAI,UAAU,UAAa,CAAC,QAAQ,IAAI,KAAK,KAAO,IAAI,aAAa,WAAc,CAAC,QAAQ,IAAI,QAAQ,KAAK,IAAI,SAAS,KAAK,SAAO,CAAC,oBAAoB,KAAK,GAAG,CAAC,MACnL,IAAI,aAAa,UAAa,CAAC,QAAQ,IAAI,QAAQ,EAAI,OAAM,IAAI,MAAM,wEAAwE;AACrJ,eAAO,KAAK,CAAC,SAAS,YAAY,UAAU,CAAC;AAAA,MAC/C;AACA,iBAAW,IAAI,UAAU,EAAE;AAAA,IAC7B;AACA,eAAW,QAAQ,OAAO,OAAO;AAC/B,UAAI,CAAC,OAAO,IAAI,KAAK,CAAC,GAAG,KAAK,EAAE,KAAK,MAAM,IAAI,KAAK,EAAE,KAAK,CAAC,QAAQ,KAAK,cAAc,KAAK,KAAK,KAAK,aAAa,KAAK,SAAO,CAAC,WAAW,IAAI,GAAG,CAAC,KAC9I,CAAC,kBAAkB,SAAS,KAAK,MAAM,KAAK,CAAC,CAAC,YAAY,eAAe,QAAQ,EAAE,SAAS,KAAK,KAAK,KAAK,OAAO,KAAK,aAAa,aACpI,CAAC,QAAQ,KAAK,SAAS,KAAK,CAAC,SAAS,KAAK,QAAQ,KAAM,KAAK,SAAS,WAAc,CAAC,MAAM,QAAQ,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK,UAAU,KAAK,KAAK,KAAK,SAAO,OAAO,QAAQ,QAAQ,MACnL,KAAK,iBAAiB,UAAa,CAAC,SAAS,KAAK,YAAY,EAAI,OAAM,IAAI,MAAM,gDAAgD;AACxI,aAAO,MAAM,CAAC,MAAM,gBAAgB,UAAU,SAAS,YAAY,aAAa,YAAY,QAAQ,cAAc,CAAC;AACnH,UAAI,KAAK,UAAU,cAAc,CAAC,CAAC,SAAS,QAAQ,QAAQ,EAAE,SAAS,KAAK,MAAM,EAAG,OAAM,IAAI,MAAM,sDAAsD;AAC3J,YAAM,IAAI,KAAK,IAAI,IAAI;AAAA,IACzB;AACA,UAAM,WAAW,oBAAI,IAAY,GAAG,UAAU,oBAAI,IAAY,GAAG,YAAY,EAAE,UAAU,GAAG,aAAa,GAAG,QAAQ,EAAE;AACtH,UAAM,QAAQ,CAAC,SAAyB;AACtC,UAAI,SAAS,IAAI,KAAK,EAAE,EAAG,OAAM,IAAI,MAAM,mCAAmC;AAC9E,UAAI,QAAQ,IAAI,KAAK,EAAE,EAAG;AAC1B,eAAS,IAAI,KAAK,EAAE;AACpB,iBAAW,OAAO,KAAK,WAAW;AAChC,cAAM,aAAa,MAAM,IAAI,GAAG;AAChC,YAAI,CAAC,WAAY,OAAM,IAAI,MAAM,oCAAoC;AACrE,YAAI,UAAU,WAAW,KAAK,IAAI,UAAU,KAAK,KAAK,EAAG,OAAM,IAAI,MAAM,mDAAmD;AAC5H,cAAM,UAAU;AAAA,MAClB;AACA,eAAS,OAAO,KAAK,EAAE;AAAG,cAAQ,IAAI,KAAK,EAAE;AAAA,IAC/C;AACA,eAAW,QAAQ,MAAM,OAAO,EAAG,OAAM,IAAI;AAC7C,QAAI,OAAO,WAAW,KAAK,eAAa,CAAC,OAAO,MAAM,KAAK,WAAS,UAAU,aAAa,SAAS,KAAK,aAAa,KAAK,aAAa,SAAS,UAAU,EAAE,CAAC,CAAC,EAAG,OAAM,IAAI,MAAM,0HAA0H;AAC5S,QAAI,CAAC,WAAW,QAAQ,MAAM,KAAM,OAAM,IAAI,MAAM,qCAAqC;AAAA,EAC3F;AACA,SAAO,UAAU;AACnB;AAkBO,SAAS,yBAAyB,OAAmD;AAC1F,MAAI,CAAC,OAAO,KAAK,KAAK,CAAC,SAAS,MAAM,WAAW,KAAK,CAAC,aAAa,cAAc,UAAU,EAAE,KAAK,SAAO,MAAM,GAAG,MAAM,UAAa,CAAC,SAAS,MAAM,GAAG,CAAC,CAAC,EAAG,OAAM,IAAI,MAAM,2BAA2B;AACzM,SAAO,OAAO,CAAC,eAAe,aAAa,cAAc,UAAU,CAAC;AACtE;AAiBO,SAAS,0BAA0B,OAAoD;AAC5F,MAAI,CAAC,OAAO,KAAK,KAAK,MAAM,eAAe,KAAK,CAAC,SAAS,MAAM,KAAK,KAAK,OAAO,MAAM,oBAAoB,YAAY,CAAC,iBAAiB,KAAK,MAAM,eAAe,KAAK,CAAC,MAAM,QAAQ,MAAM,OAAO,EAAG,OAAM,IAAI,MAAM,4BAA4B;AACnP,SAAO,OAAO,CAAC,cAAc,SAAS,mBAAmB,SAAS,CAAC;AACnE,QAAM,QAAQ,oBAAI,IAAoB;AACtC,aAAW,UAAU,MAAM,SAAS;AAClC,QAAI,CAAC,OAAO,MAAM,KAAK,CAAC,GAAG,OAAO,QAAQ,KAAK,CAAC,GAAG,OAAO,MAAM,KAAK,CAAC,CAAC,WAAW,aAAa,QAAQ,EAAE,SAAS,OAAO,MAAM,KAC1H,CAAC,SAAS,OAAO,KAAK,KAAK,CAAC,QAAQ,OAAO,UAAU,KAAK,KAAK,CAAC,SAAS,OAAO,UAAU,KAC1F,CAAC,2CAA2C,KAAK,OAAO,UAAU,KAAK,CAAC,OAAO,SAAS,KAAK,MAAM,OAAO,UAAU,CAAC,KACrH,IAAI,KAAK,OAAO,UAAU,EAAE,YAAY,MAAM,OAAO,WAAY,OAAM,IAAI,MAAM,uEAAuE;AAC7J,WAAO,QAAQ,CAAC,YAAY,UAAU,UAAU,UAAU,cAAc,SAAS,YAAY,iBAAiB,iBAAiB,CAAC;AAChI,QAAK,OAAO,kBAAkB,YAAgB,OAAO,oBAAoB,WAAe,OAAO,kBAAkB,WAAc,CAAC,GAAG,OAAO,aAAa,KAAK,CAAC,iBAAiB,KAAK,OAAO,eAAgB,GAAK,OAAM,MAAM,+DAA+D;AAC1R,QAAI,OAAO,WAAW,OAAW,0BAAyB,OAAO,MAAM;AACvE,UAAM,MAAM,KAAK,UAAU,CAAC,OAAO,UAAU,OAAO,QAAQ,UAAU,OAAO,MAAM,GAAG,OAAO,iBAAiB,MAAM,OAAO,mBAAmB,IAAI,CAAC;AACnJ,UAAM,OAAO,KAAK,MAAM,OAAO,UAAU;AACzC,QAAI,SAAS,MAAM,IAAI,GAAG,KAAK,WAAY,OAAM,IAAI,MAAM,iEAAiE;AAC5H,UAAM,IAAI,KAAK,IAAI;AAAA,EACrB;AACF;AACA,SAAS,WAAW,MAAsB,QAAyD;AACjG,MAAI,KAAK,UAAU,WAAY,QAAO;AACtC,MAAI,CAAC,UAAW,KAAK,UAAU,YAAY,CAAC,OAAO,SAAW,QAAO;AACrE,QAAM,EAAE,UAAU,WAAW,GAAG,YAAY,IAAI;AAChD,SAAO,KAAK,UAAU,WAAW,SAAS;AAC5C;AAsBO,SAAS,oBAAoB,WAAgC,iBAAyB,WAAgC,CAAC,GAAG,QAA2B;AAC1J,MAAI,CAAC,iBAAiB,KAAK,eAAe,EAAG,OAAM,IAAI,MAAM,2BAA2B;AACxF,QAAM,UAAU,0BAA0B,SAAS;AACnD,MAAI,WAAW,OAAW,0BAAyB,MAAM;AACzD,QAAM,UAAU,oBAAI,IAA8B,GAAG,kBAA4D,CAAC;AAClH,aAAW,WAAW,UAAU;AAC9B,8BAA0B,OAAO;AACjC,QAAI,QAAQ,UAAU,UAAU,SAAS,QAAQ,oBAAoB,iBAAiB;AACpF,sBAAgB,KAAK,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,UAAU,UAAU,QAAQ,oBAAoB,kBAAkB,CAAC;AAAG;AAAA,IACrI;AACA,eAAW,UAAU,QAAQ,SAAS;AACpC,YAAM,OAAO,SAAS,KAAK,CAAAA,YAAUA,QAAO,OAAO,OAAO,QAAQ,GAAG,MAAM,KAAK,CAAAC,UAAQA,MAAK,OAAO,OAAO,MAAM;AACjH,UAAI,CAAC,KAAM,OAAM,IAAI,MAAM,kDAAkD;AAC7E,UAAI,OAAO,kBAAkB,QAAW;AACtC,YAAI,KAAK,UAAU,WAAY,OAAM,MAAM,sDAAsD;AACjG,wBAAgB,KAAK,EAAE,OAAO,QAAQ,OAAO,QAAQ,6BAA6B,CAAC;AAAG;AAAA,MACxF;AACA,UAAK,KAAK,UAAU,cAAc,OAAO,WAAW,UAAe,KAAK,UAAU,cAAc,CAAC,OAAO,UAClG,KAAK,UAAU,iBAAiB,OAAO,QAAQ,aAAa,UAAe,KAAK,UAAU,YAAY,CAAC,OAAO,QAAQ,SAAW,OAAM,IAAI,MAAM,0CAA0C;AACjM,YAAM,SAAS,QAAS,KAAK,CAAAD,YAAUA,QAAO,OAAO,OAAO,QAAQ;AACpE,UAAI,KAAK,UAAU,cAAc,OAAO,WAAW,KAAK,eAAa,UAAU,SAAS,cAAc,KAAK,aAAa,SAAS,UAAU,EAAE,CAAC,MACxI,CAAC,OAAO,QAAQ,aAAa,CAAC,OAAO,OAAO,YAAa,OAAM,IAAI,MAAM,mEAAmE;AAClJ,YAAM,WAAW,WAAW,MAAM,MAAM;AACxC,UAAK,KAAK,UAAU,cAAc,CAAC,YAAa,UAAU,OAAO,MAAM,MAAM,UAAU,QAAQ,EAAG;AAClG,YAAM,MAAM,KAAK,UAAU,CAAC,OAAO,UAAU,OAAO,MAAM,CAAC,GAAG,MAAM,QAAQ,IAAI,GAAG;AACnF,UAAI,OAAO,IAAI,eAAe,OAAO,cAAc,KAAK,UAAU,GAAG,MAAM,KAAK,UAAU,MAAM,EAAG,OAAM,IAAI,MAAM,sDAAsD;AACzK,UAAI,CAAC,OAAO,IAAI,aAAa,OAAO,WAAY,SAAQ,IAAI,KAAK,MAAM;AAAA,IACzE;AAAA,EACF;AACA,QAAM,aAAa,WAAW,CAAC,GAAG,IAAI,YAAU;AAC9C,UAAM,mBAAmB,CAAC,OAAO,WAAW,KAAK,eAAa,UAAU,eAAe,MAAM;AAC7F,UAAM,SAAS,oBAAI,IAAyE;AAC5F,UAAM,SAAS,CAAC,SAAsF;AACpG,YAAM,QAAQ,OAAO,IAAI,KAAK,EAAE;AAChC,UAAI,MAAO,QAAO;AAClB,YAAM,SAAS,QAAQ,IAAI,KAAK,UAAU,CAAC,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC;AAC/D,YAAM,eAAe,KAAK,UAAU,IAAI,SAAO,OAAO,OAAO,MAAM,KAAK,CAAAC,UAAQA,MAAK,OAAO,GAAG,CAAE,CAAC;AAClG,YAAM,UAAU,aAAa,KAAK,gBAAc,WAAW,WAAW,WAAW;AACjF,YAAM,QAAQ,QAAQ,WAAW,eAAe,aAAa,KAAK,gBAAc,WAAW,UAAU,WAAW,OAAO,aAAa,OAAO,UAAU;AACrJ,YAAM,QAAQ,EAAE,QAAS,UAAU,YAAY,QAAQ,UAAU,QAAQ,UAAU,WAAoC,OAAO;AAC9H,aAAO,IAAI,KAAK,IAAI,KAAK;AAAG,aAAO;AAAA,IACrC;AACA,UAAM,QAAQ,OAAO,MAAM,IAAI,WAAS,EAAE,GAAG,MAAM,GAAG,OAAO,IAAI,EAAE,EAAE;AACrE,WAAO;AAAA,MAAE,IAAI,OAAO;AAAA,MAAI;AAAA,MAAkB,UAAU,oBAAoB,MAAM,OAAO,UAAQ,KAAK,QAAQ,EAAE,MAAM,UAAQ,KAAK,WAAW,WAAW;AAAA,MACnJ,YAAY,OAAO,WAAW,IAAI,gBAAc,EAAE,GAAG,WAAW,UAAU,oBAAoB,MAAM,OAAO,WAAS,UAAU,aAAa,SAAS,KAAK,aAAa,KAAK,aAAa,SAAS,UAAU,EAAE,CAAC,EAAE,MAAM,UAAQ,KAAK,WAAW,WAAW,EAAE,EAAE;AAAA,MAAG;AAAA,IAAM;AAAA,EAC1Q,CAAC;AACD,SAAO;AAAA,IAAE,OAAO,UAAU;AAAA,IAAO;AAAA,IAAiB;AAAA,IAAQ,UAAU,UAAU,aAAsB;AAAA,IAClG,kBAAkB,CAAC,CAAC,WAAW,UAAU,MAAM,YAAU,OAAO,gBAAgB;AAAA,IAAG,UAAU,CAAC,CAAC,WAAW,UAAU,MAAM,YAAU,OAAO,QAAQ;AAAA,IAAG,SAAS;AAAA,IAAW;AAAA,IAC1K,gBAAgB;AAAA,EAAyF;AAC7G;","names":["plugin","task"]}
@@ -0,0 +1,74 @@
1
+ // src/agentic/agent-runner.ts
2
+ import {
3
+ parseWorkflowAgentProposal
4
+ } from "@alneas/eaos-core";
5
+ function createWorkflowAgentRunner(options) {
6
+ if (typeof options?.executor !== "function") throw new Error("Workflow agent executor is required");
7
+ return {
8
+ async run(request) {
9
+ const startedAt = Date.now();
10
+ const task = {
11
+ id: request.taskId,
12
+ tenantId: request.tenantId,
13
+ userId: request.userId,
14
+ title: request.purpose,
15
+ workerType: "custom",
16
+ ...request.jobKind === void 0 ? {} : { jobKind: request.jobKind },
17
+ instructions: JSON.stringify({
18
+ schemaVersion: "1.0",
19
+ purpose: request.purpose,
20
+ input: request.input,
21
+ toolScope: request.toolScope,
22
+ output: "Return only a JSON WorkflowAgentProposal with schemaVersion 1.0."
23
+ }),
24
+ executionContext: {
25
+ workflowId: request.workflowId,
26
+ correlationId: request.correlationId,
27
+ idempotencyKey: request.idempotencyKey,
28
+ toolMode: request.toolScope.mode,
29
+ allowedToolNames: request.toolScope.allowedToolNames
30
+ },
31
+ timeoutMs: request.timeoutMs
32
+ };
33
+ let rawOutput;
34
+ try {
35
+ rawOutput = await options.executor(task);
36
+ } catch (error) {
37
+ const failureCode = isAgentFailureCode(error) ? error.failureCode : "RUNTIME_FAILED";
38
+ const retryable = isAgentRetryable(error) ?? (failureCode === "AGENT_UNAVAILABLE" || failureCode === "TIMEOUT" || failureCode === "RUNTIME_FAILED");
39
+ return {
40
+ status: failureCode === "AGENT_UNAVAILABLE" ? "UNAVAILABLE" : "FAILED",
41
+ error: error instanceof Error ? error.message : "Workflow agent execution failed",
42
+ failureCode,
43
+ retryable,
44
+ ...options.runtimeId ? { runtimeId: options.runtimeId } : {},
45
+ durationMs: Date.now() - startedAt
46
+ };
47
+ }
48
+ try {
49
+ const proposal = parseWorkflowAgentProposal(rawOutput);
50
+ return { status: "COMPLETED", proposal, ...options.runtimeId ? { runtimeId: options.runtimeId } : {}, durationMs: Date.now() - startedAt };
51
+ } catch (error) {
52
+ return {
53
+ status: "FAILED",
54
+ error: error instanceof Error ? error.message : "Invalid workflow agent proposal",
55
+ failureCode: "INVALID_PROPOSAL",
56
+ retryable: false,
57
+ ...options.runtimeId ? { runtimeId: options.runtimeId } : {},
58
+ durationMs: Date.now() - startedAt
59
+ };
60
+ }
61
+ }
62
+ };
63
+ }
64
+ function isAgentFailureCode(error) {
65
+ return typeof error === "object" && error !== null && "failureCode" in error && typeof error.failureCode === "string";
66
+ }
67
+ function isAgentRetryable(error) {
68
+ return typeof error === "object" && error !== null && "retryable" in error && typeof error.retryable === "boolean" ? error.retryable : void 0;
69
+ }
70
+
71
+ export {
72
+ createWorkflowAgentRunner
73
+ };
74
+ //# sourceMappingURL=chunk-6XZXYNJR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/agentic/agent-runner.ts"],"sourcesContent":["import {\n parseWorkflowAgentProposal,\n type WorkflowAgentRequest,\n type WorkflowAgentRunResult,\n type WorkflowAgentRunner,\n} from '@alneas/eaos-core'\nimport type { ServerAgentExecutor, ServerAgentTaskRequest } from './types'\n\n/**\n * Host executor configuration for {@link createWorkflowAgentRunner}.\n */\nexport interface ServerWorkflowAgentRunnerOptions {\n /** Host-owned executor. It may be backed by Goose, Hermes or another runtime. */\n executor: ServerAgentExecutor\n /** Optional host runtime label copied into every normalized run result. */\n runtimeId?: string\n}\n\n/**\n * Bridges the host/server executor contract to the vendor-neutral workflow\n * runner contract. The executor output is parsed as a proposal; it is never\n * treated as an instruction to perform a side effect.\n * @param options - Host-owned executor and optional runtime label.\n * @returns A runner whose generic run method accepts a WorkflowAgentRequest and resolves a parsed proposal or a failure result. Executor errors become FAILED/UNAVAILABLE data; parse errors become nonretryable INVALID_PROPOSAL data.\n * @throws Synchronously when executor is missing. run may reject before execution when request serialization fails.\n * @remarks The runner forwards workflow/correlation/idempotency/tool context but does not independently authorize, retry, deduplicate, execute tools, or enforce timeouts. Those boundaries belong to the host executor. Runtime text must parse as a version 1.0 proposal; domain-specific output still needs plugin validation.\n * @example\n * ```typescript\n * import { createWorkflowAgentRunner } from \"@alneas/eaos-server/agentic/agent-runner\";\n * import type { ServerAgentExecutor } from \"@alneas/eaos-server/agentic/types\";\n * export function workflowRunner(executor: ServerAgentExecutor) {\n * return createWorkflowAgentRunner({ executor, runtimeId: \"host-runtime\" });\n * }\n * ```\n */\nexport function createWorkflowAgentRunner(options: ServerWorkflowAgentRunnerOptions): WorkflowAgentRunner {\n if (typeof options?.executor !== 'function') throw new Error('Workflow agent executor is required')\n\n return {\n async run<TOutput>(request: WorkflowAgentRequest): Promise<WorkflowAgentRunResult<TOutput>> {\n const startedAt = Date.now()\n const task: ServerAgentTaskRequest = {\n id: request.taskId,\n tenantId: request.tenantId,\n userId: request.userId,\n title: request.purpose,\n workerType: 'custom',\n ...(request.jobKind === undefined ? {} : { jobKind: request.jobKind }),\n instructions: JSON.stringify({\n schemaVersion: '1.0',\n purpose: request.purpose,\n input: request.input,\n toolScope: request.toolScope,\n output: 'Return only a JSON WorkflowAgentProposal with schemaVersion 1.0.',\n }),\n executionContext: {\n workflowId: request.workflowId,\n correlationId: request.correlationId,\n idempotencyKey: request.idempotencyKey,\n toolMode: request.toolScope.mode,\n allowedToolNames: request.toolScope.allowedToolNames,\n },\n timeoutMs: request.timeoutMs,\n }\n\n let rawOutput: string\n try {\n rawOutput = await options.executor(task)\n } catch (error) {\n const failureCode = isAgentFailureCode(error) ? error.failureCode : 'RUNTIME_FAILED'\n const retryable = isAgentRetryable(error) ?? (failureCode === 'AGENT_UNAVAILABLE' || failureCode === 'TIMEOUT' || failureCode === 'RUNTIME_FAILED')\n return {\n status: failureCode === 'AGENT_UNAVAILABLE' ? 'UNAVAILABLE' : 'FAILED',\n error: error instanceof Error ? error.message : 'Workflow agent execution failed',\n failureCode,\n retryable,\n ...(options.runtimeId ? { runtimeId: options.runtimeId } : {}),\n durationMs: Date.now() - startedAt,\n }\n }\n\n try {\n const proposal = parseWorkflowAgentProposal<TOutput>(rawOutput)\n return { status: 'COMPLETED', proposal, ...(options.runtimeId ? { runtimeId: options.runtimeId } : {}), durationMs: Date.now() - startedAt }\n } catch (error) {\n return {\n status: 'FAILED',\n error: error instanceof Error ? error.message : 'Invalid workflow agent proposal',\n failureCode: 'INVALID_PROPOSAL',\n retryable: false,\n ...(options.runtimeId ? { runtimeId: options.runtimeId } : {}),\n durationMs: Date.now() - startedAt,\n }\n }\n },\n }\n}\n\nfunction isAgentFailureCode(error: unknown): error is { failureCode: NonNullable<WorkflowAgentRunResult['failureCode']> } {\n return typeof error === 'object' && error !== null && 'failureCode' in error && typeof error.failureCode === 'string'\n}\n\nfunction isAgentRetryable(error: unknown): boolean | undefined {\n return typeof error === 'object' && error !== null && 'retryable' in error && typeof error.retryable === 'boolean'\n ? error.retryable\n : undefined\n}\n"],"mappings":";AAAA;AAAA,EACE;AAAA,OAIK;AA8BA,SAAS,0BAA0B,SAAgE;AACxG,MAAI,OAAO,SAAS,aAAa,WAAY,OAAM,IAAI,MAAM,qCAAqC;AAElG,SAAO;AAAA,IACL,MAAM,IAAa,SAAyE;AAC1F,YAAM,YAAY,KAAK,IAAI;AAC3B,YAAM,OAA+B;AAAA,QACnC,IAAI,QAAQ;AAAA,QACZ,UAAU,QAAQ;AAAA,QAClB,QAAQ,QAAQ;AAAA,QAChB,OAAO,QAAQ;AAAA,QACf,YAAY;AAAA,QACZ,GAAI,QAAQ,YAAY,SAAY,CAAC,IAAI,EAAE,SAAS,QAAQ,QAAQ;AAAA,QACpE,cAAc,KAAK,UAAU;AAAA,UAC3B,eAAe;AAAA,UACf,SAAS,QAAQ;AAAA,UACjB,OAAO,QAAQ;AAAA,UACf,WAAW,QAAQ;AAAA,UACnB,QAAQ;AAAA,QACV,CAAC;AAAA,QACD,kBAAkB;AAAA,UAChB,YAAY,QAAQ;AAAA,UACpB,eAAe,QAAQ;AAAA,UACvB,gBAAgB,QAAQ;AAAA,UACxB,UAAU,QAAQ,UAAU;AAAA,UAC5B,kBAAkB,QAAQ,UAAU;AAAA,QACtC;AAAA,QACA,WAAW,QAAQ;AAAA,MACrB;AAEA,UAAI;AACJ,UAAI;AACF,oBAAY,MAAM,QAAQ,SAAS,IAAI;AAAA,MACzC,SAAS,OAAO;AACd,cAAM,cAAc,mBAAmB,KAAK,IAAI,MAAM,cAAc;AACpE,cAAM,YAAY,iBAAiB,KAAK,MAAM,gBAAgB,uBAAuB,gBAAgB,aAAa,gBAAgB;AAClI,eAAO;AAAA,UACL,QAAQ,gBAAgB,sBAAsB,gBAAgB;AAAA,UAC9D,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,UAChD;AAAA,UACA;AAAA,UACA,GAAI,QAAQ,YAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;AAAA,UAC5D,YAAY,KAAK,IAAI,IAAI;AAAA,QAC3B;AAAA,MACF;AAEA,UAAI;AACF,cAAM,WAAW,2BAAoC,SAAS;AAC9D,eAAO,EAAE,QAAQ,aAAa,UAAU,GAAI,QAAQ,YAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC,GAAI,YAAY,KAAK,IAAI,IAAI,UAAU;AAAA,MAC7I,SAAS,OAAO;AACd,eAAO;AAAA,UACL,QAAQ;AAAA,UACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,UAChD,aAAa;AAAA,UACb,WAAW;AAAA,UACX,GAAI,QAAQ,YAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;AAAA,UAC5D,YAAY,KAAK,IAAI,IAAI;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,mBAAmB,OAA8F;AACxH,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,iBAAiB,SAAS,OAAO,MAAM,gBAAgB;AAC/G;AAEA,SAAS,iBAAiB,OAAqC;AAC7D,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,eAAe,SAAS,OAAO,MAAM,cAAc,YACrG,MAAM,YACN;AACN;","names":[]}
@@ -0,0 +1,222 @@
1
+ // src/platform-admin/index.ts
2
+ import { Hono } from "hono";
3
+ import { assertBackendMigrationCutover, planBackendMigration } from "@alneas/eaos-server/lifecycle-engine";
4
+ function object(value) {
5
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Request body must be an object");
6
+ return value;
7
+ }
8
+ function string(value, name, max = 256) {
9
+ if (typeof value !== "string" || !value.trim() || value.length > max) throw new Error(`Invalid ${name}`);
10
+ return value;
11
+ }
12
+ function stringArray(value, name, max = 128) {
13
+ if (!Array.isArray(value) || value.length === 0 || value.length > max || value.some((item) => typeof item !== "string" || !item.trim())) throw new Error(`Invalid ${name}`);
14
+ return [...value];
15
+ }
16
+ async function body(c) {
17
+ return object(await c.req.json().catch(() => null));
18
+ }
19
+ function publicBackend(backend) {
20
+ return {
21
+ id: backend.id,
22
+ databaseId: backend.databaseId,
23
+ dialect: backend.dialect,
24
+ mode: backend.mode,
25
+ ...backend.tenantId === void 0 ? {} : { tenantId: backend.tenantId },
26
+ ...backend.label === void 0 ? {} : { label: backend.label },
27
+ ...backend.provider === void 0 ? {} : { provider: backend.provider },
28
+ ...backend.capabilities === void 0 ? {} : { capabilities: backend.capabilities }
29
+ };
30
+ }
31
+ function createPlatformAdminRouter(options) {
32
+ if (!options?.store || !options.resolvePrincipal || !options.authorize || !options.audit) throw new Error("Platform admin router dependencies are required");
33
+ const app = new Hono();
34
+ const now = options.now ?? (() => /* @__PURE__ */ new Date());
35
+ const access = async (request, action, tenantId) => {
36
+ const principal = await options.resolvePrincipal(request);
37
+ if (!principal) return new Response(JSON.stringify({ error: "Authentication required" }), { status: 401, headers: { "content-type": "application/json" } });
38
+ const allowed = principal.isPlatformAdmin === true && await options.authorize(principal, action, tenantId);
39
+ if (!allowed) {
40
+ await options.audit({ action, actorId: principal.userId, ...tenantId ? { tenantId } : {}, outcome: "denied", occurredAt: now().toISOString() });
41
+ return new Response(JSON.stringify({ error: "Platform administrator access required" }), { status: 403, headers: { "content-type": "application/json" } });
42
+ }
43
+ return { principal };
44
+ };
45
+ const failure = (error, status = 400) => new Response(JSON.stringify({ error: error instanceof Error ? error.message : "Request failed" }), { status, headers: { "content-type": "application/json" } });
46
+ app.get("/tenants", async (c) => {
47
+ const authorized = await access(c.req.raw, "tenant:list");
48
+ if (authorized instanceof Response) return authorized;
49
+ return c.json({ tenants: await options.store.listTenants() });
50
+ });
51
+ app.post("/tenants", async (c) => {
52
+ const authorized = await access(c.req.raw, "tenant:create");
53
+ if (authorized instanceof Response) return authorized;
54
+ try {
55
+ const input = await body(c);
56
+ const tenant = await options.store.createTenant({ id: string(input.id, "tenant id"), name: string(input.name, "tenant name"), domains: stringArray(input.domains, "domains"), backendId: string(input.backendId, "initial backend id") });
57
+ await options.audit({ action: "tenant:create", actorId: authorized.principal.userId, tenantId: tenant.id, outcome: "allowed", occurredAt: now().toISOString() });
58
+ return c.json({ tenant }, 201);
59
+ } catch (error) {
60
+ return failure(error);
61
+ }
62
+ });
63
+ app.patch("/tenants/:tenantId", async (c) => {
64
+ const tenantId = string(c.req.param("tenantId"), "tenant id");
65
+ const authorized = await access(c.req.raw, "tenant:update", tenantId);
66
+ if (authorized instanceof Response) return authorized;
67
+ try {
68
+ const input = await body(c);
69
+ const patch = {
70
+ ...input.name === void 0 ? {} : { name: string(input.name, "tenant name") },
71
+ ...input.active === void 0 ? {} : { active: input.active === true },
72
+ ...input.domains === void 0 ? {} : { domains: stringArray(input.domains, "domains") }
73
+ };
74
+ if (!Object.keys(patch).length) throw new Error("Tenant patch is empty");
75
+ const tenant = await options.store.updateTenant(tenantId, patch);
76
+ await options.audit({ action: "tenant:update", actorId: authorized.principal.userId, tenantId, outcome: "allowed", occurredAt: now().toISOString() });
77
+ return c.json({ tenant });
78
+ } catch (error) {
79
+ return failure(error);
80
+ }
81
+ });
82
+ app.get("/backends", async (c) => {
83
+ const authorized = await access(c.req.raw, "backend:list");
84
+ if (authorized instanceof Response) return authorized;
85
+ return c.json({ backends: (await options.store.listBackends()).map(publicBackend) });
86
+ });
87
+ app.get("/tenants/:tenantId/placement", async (c) => {
88
+ const tenantId = string(c.req.param("tenantId"), "tenant id");
89
+ const authorized = await access(c.req.raw, "placement:read", tenantId);
90
+ if (authorized instanceof Response) return authorized;
91
+ const placement = await options.store.getTenantPlacement(tenantId);
92
+ if (!placement) return failure(new Error("Tenant placement not found"), 404);
93
+ return c.json({ placement: { ...placement, backend: publicBackend(placement.backend) } });
94
+ });
95
+ app.post("/tenants/:tenantId/placement/plan", async (c) => {
96
+ const tenantId = string(c.req.param("tenantId"), "tenant id");
97
+ const authorized = await access(c.req.raw, "placement:plan", tenantId);
98
+ if (authorized instanceof Response) return authorized;
99
+ try {
100
+ const input = await body(c);
101
+ const targetBackendId = string(input.targetBackendId, "target backend id");
102
+ const pluginIds = stringArray(input.pluginIds, "pluginIds");
103
+ const reason = string(input.reason, "migration reason", 1024);
104
+ const current = await options.store.getTenantPlacement(tenantId);
105
+ if (!current) return failure(new Error("Tenant placement not found"), 404);
106
+ const target = await options.store.getBackend(targetBackendId);
107
+ if (!target) return failure(new Error("Target backend not found"), 404);
108
+ const plan = planBackendMigration({
109
+ migrationId: `platform-${crypto.randomUUID()}`,
110
+ source: current.backend,
111
+ target,
112
+ scope: { kind: "tenants", tenantIds: [tenantId] },
113
+ pluginIds,
114
+ requestedAt: now().toISOString(),
115
+ reason
116
+ });
117
+ await options.store.saveMigrationPlan(plan);
118
+ await options.audit({ action: "placement:plan", actorId: authorized.principal.userId, tenantId, sourceBackendId: plan.request.source.id, targetBackendId: plan.request.target.id, migrationId: plan.id, outcome: "allowed", occurredAt: now().toISOString() });
119
+ return c.json({ plan }, 201);
120
+ } catch (error) {
121
+ return failure(error);
122
+ }
123
+ });
124
+ app.post("/tenants/:tenantId/placement/execute", async (c) => {
125
+ const tenantId = string(c.req.param("tenantId"), "tenant id");
126
+ const authorized = await access(c.req.raw, "placement:cutover", tenantId);
127
+ if (authorized instanceof Response) return authorized;
128
+ if (!options.placementExecutor) return failure(new Error("Placement execution is not configured"), 501);
129
+ let migrationId = "";
130
+ let executionId = "";
131
+ try {
132
+ const input = await body(c);
133
+ migrationId = string(input.migrationId, "migration id");
134
+ executionId = string(input.executionId, "execution id");
135
+ const plan = await options.store.getMigrationPlan(migrationId);
136
+ if (!plan) return failure(new Error("Migration plan not found"), 404);
137
+ if (plan.request.scope.kind !== "tenants" || !plan.request.scope.tenantIds.includes(tenantId)) return failure(new Error("Migration plan tenant mismatch"), 409);
138
+ const previous = await options.store.getMigrationStatus(migrationId);
139
+ const current = await options.store.getTenantPlacement(tenantId);
140
+ if (previous?.status === "cutover") return c.json({ status: previous.status, cutover: previous.cutover, placement: current ? { ...current, backend: publicBackend(current.backend) } : null });
141
+ if (!current || current.backend.id !== plan.request.source.id || current.backend.databaseId !== plan.request.source.databaseId) return failure(new Error("Migration plan is stale"), 409);
142
+ const previousStatus = previous?.status;
143
+ const previousExecutionId = previous?.executionId;
144
+ const record = await options.store.beginMigrationExecution({ tenantId, migrationId, executionId });
145
+ if (record.status === "cutover") return c.json({ status: record.status, cutover: record.cutover, placement: { ...current, backend: publicBackend(current.backend) } });
146
+ if (previousStatus === "running" && previousExecutionId === executionId) return c.json({ status: "running", migrationId }, 202);
147
+ if (record.status === "running") {
148
+ const result = await options.placementExecutor.execute(plan);
149
+ const cutover2 = assertBackendMigrationCutover(plan, result.verification, result.cutover);
150
+ await options.store.recordMigrationVerification({ tenantId, plan, executionId, verification: result.verification, cutover: cutover2 });
151
+ } else if (record.status !== "verified" || !record.cutover) {
152
+ return failure(new Error("Migration is not executable"), 409);
153
+ }
154
+ const verified = await options.store.getMigrationStatus(migrationId);
155
+ if (!verified?.cutover) return failure(new Error("Migration verification is missing"), 409);
156
+ const cutover = verified.cutover;
157
+ const placement = await options.store.recordTenantPlacement({ tenantId, plan, cutover });
158
+ await options.audit({ action: "placement:cutover", actorId: authorized.principal.userId, tenantId, sourceBackendId: plan.request.source.id, targetBackendId: plan.request.target.id, migrationId: plan.id, outcome: "allowed", occurredAt: now().toISOString() });
159
+ return c.json({ cutover, placement: { ...placement, backend: publicBackend(placement.backend) } });
160
+ } catch (error) {
161
+ if (migrationId) await options.store.markMigrationFailure({ migrationId, executionId: executionId || void 0, status: "reconciling", message: error instanceof Error ? error.message : "Migration execution failed" }).catch(() => void 0);
162
+ return failure(error, 409);
163
+ }
164
+ });
165
+ app.get("/tenants/:tenantId/placement/migrations/:migrationId", async (c) => {
166
+ const tenantId = string(c.req.param("tenantId"), "tenant id");
167
+ const migrationId = string(c.req.param("migrationId"), "migration id");
168
+ const authorized = await access(c.req.raw, "placement:read", tenantId);
169
+ if (authorized instanceof Response) return authorized;
170
+ const plan = await options.store.getMigrationPlan(migrationId);
171
+ const migration = await options.store.getMigrationStatus(migrationId);
172
+ if (!plan || !migration) return failure(new Error("Migration not found"), 404);
173
+ if (plan.request.scope.kind !== "tenants" || !plan.request.scope.tenantIds.includes(tenantId)) return failure(new Error("Migration plan tenant mismatch"), 409);
174
+ return c.json({ migration: { ...migration, plan } });
175
+ });
176
+ app.post("/tenants/:tenantId/placement/rollback", async (c) => {
177
+ const tenantId = string(c.req.param("tenantId"), "tenant id");
178
+ const authorized = await access(c.req.raw, "placement:rollback", tenantId);
179
+ if (authorized instanceof Response) return authorized;
180
+ try {
181
+ const input = await body(c);
182
+ const migrationId = string(input.migrationId, "migration id");
183
+ const reason = string(input.reason, "rollback reason", 1024);
184
+ const plan = await options.store.createRollbackPlan({ tenantId, migrationId, reason, requestedAt: now().toISOString() });
185
+ await options.audit({ action: "placement:rollback", actorId: authorized.principal.userId, tenantId, sourceBackendId: plan.request.source.id, targetBackendId: plan.request.target.id, migrationId: plan.id, outcome: "allowed", occurredAt: now().toISOString() });
186
+ return c.json({ plan }, 201);
187
+ } catch (error) {
188
+ return failure(error, 409);
189
+ }
190
+ });
191
+ app.post("/tenants/:tenantId/placement/reconcile", async (c) => {
192
+ const tenantId = string(c.req.param("tenantId"), "tenant id");
193
+ const authorized = await access(c.req.raw, "placement:reconcile", tenantId);
194
+ if (authorized instanceof Response) return authorized;
195
+ try {
196
+ const input = await body(c);
197
+ const migrationId = string(input.migrationId, "migration id");
198
+ const action = string(input.action, "reconciliation action");
199
+ const note = string(input.note, "reconciliation note", 2048);
200
+ const plan = await options.store.getMigrationPlan(migrationId);
201
+ if (!plan || plan.request.scope.kind !== "tenants" || !plan.request.scope.tenantIds.includes(tenantId)) return failure(new Error("Migration plan not found"), 404);
202
+ if (action === "commit-verified") {
203
+ const migration2 = await options.store.getMigrationStatus(migrationId);
204
+ if (!migration2?.verification || !migration2.cutover) return failure(new Error("Verified migration data is missing"), 409);
205
+ const placement = await options.store.recordTenantPlacement({ tenantId, plan, cutover: migration2.cutover });
206
+ await options.audit({ action: "placement:reconcile", actorId: authorized.principal.userId, tenantId, sourceBackendId: plan.request.source.id, targetBackendId: plan.request.target.id, migrationId: plan.id, outcome: "allowed", occurredAt: now().toISOString() });
207
+ return c.json({ migration: await options.store.getMigrationStatus(migrationId), placement: { ...placement, backend: publicBackend(placement.backend) } });
208
+ }
209
+ const migration = await options.store.reconcileMigration({ migrationId, action, note });
210
+ await options.audit({ action: "placement:reconcile", actorId: authorized.principal.userId, tenantId, sourceBackendId: plan.request.source.id, targetBackendId: plan.request.target.id, migrationId: plan.id, outcome: "allowed", occurredAt: now().toISOString() });
211
+ return c.json({ migration });
212
+ } catch (error) {
213
+ return failure(error, 409);
214
+ }
215
+ });
216
+ return app;
217
+ }
218
+
219
+ export {
220
+ createPlatformAdminRouter
221
+ };
222
+ //# sourceMappingURL=chunk-753HWDSC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/platform-admin/index.ts"],"sourcesContent":["import { Hono } from 'hono'\nimport { assertBackendMigrationCutover, planBackendMigration } from '@alneas/eaos-server/lifecycle-engine'\nimport type { PlatformAdminAction, PlatformAdminAuditEvent, PlatformAdminAuthorization, PlatformAdminPrincipal, PlatformControlStore, PlatformPlacementExecutor } from '@alneas/eaos-server/platform'\nexport type { PlatformPlacementExecutor } from '@alneas/eaos-server/platform'\nexport { LifecyclePlatformControlStore } from './store'\n\n/**\n * Trusted control-plane authorization, persistence, audit, and optional migration execution dependencies.\n * @see createPlatformAdminRouter.\n */\nexport interface PlatformAdminRouterOptions extends PlatformAdminAuthorization {\n /** Shared authoritative tenant/backend/placement store. */\n store: PlatformControlStore\n /** Awaited on denied and successful mutations; receives operator/action/outcome/time, without request credentials. Audit failure may occur after persistence. */\n audit: (event: Readonly<PlatformAdminAuditEvent>) => Promise<void>\n /** Optional host migration executor; absent returns 501 for execute requests. Provisioning, credentials, and SQL remain host-owned. */\n placementExecutor?: PlatformPlacementExecutor\n /** Clock for audit/plan timestamps; defaults to fresh Date. */\n now?: () => Date\n}\n\ntype JsonObject = Record<string, unknown>\n\nfunction object(value: unknown): JsonObject {\n if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('Request body must be an object')\n return value as JsonObject\n}\n\nfunction string(value: unknown, name: string, max = 256): string {\n if (typeof value !== 'string' || !value.trim() || value.length > max) throw new Error(`Invalid ${name}`)\n return value\n}\n\nfunction stringArray(value: unknown, name: string, max = 128): string[] {\n if (!Array.isArray(value) || value.length === 0 || value.length > max || value.some(item => typeof item !== 'string' || !item.trim())) throw new Error(`Invalid ${name}`)\n return [...value]\n}\n\nasync function body(c: { req: { json: <T>() => Promise<T> } }): Promise<JsonObject> {\n return object(await c.req.json().catch(() => null))\n}\n\nfunction publicBackend(backend: Awaited<ReturnType<PlatformControlStore['listBackends']>>[number]) {\n return {\n id: backend.id,\n databaseId: backend.databaseId,\n dialect: backend.dialect,\n mode: backend.mode,\n ...(backend.tenantId === undefined ? {} : { tenantId: backend.tenantId }),\n ...(backend.label === undefined ? {} : { label: backend.label }),\n ...(backend.provider === undefined ? {} : { provider: backend.provider }),\n ...(backend.capabilities === undefined ? {} : { capabilities: backend.capabilities }),\n }\n}\n\n/**\n * Platform-wide control routes. They operate on host-registered opaque\n * backends; provisioning, credentials, SQL and tenant membership remain host-owned.\n * @param options - Shared store, live platform-admin authorization, audit sink, optional placement executor, and clock.\n * @returns A Hono router for tenants, backend discovery, placement planning/execution/status/rollback/reconciliation. Unauthenticated/unauthorized requests return 401/403.\n * @throws Synchronously for missing store/auth/audit dependencies. Request-time reads/auth/audit can fail through Hono error handling; mutation failures are generally 400 or migration conflict 409 data.\n * @remarks Every operation requires principal.isPlatformAdmin === true plus host authorize approval. Plan/rollback endpoints persist reviewed plans rather than directly changing routing. Execution verifies reports before cutover and records reconciling state on uncertain failures; host executor effects are not rolled back automatically. Reads expose opaque public backend metadata without credentials/SQL. A failed audit can follow a completed mutation, so errors do not prove no change occurred. No listener, deployment, or scheduler is started.\n * @example\n * ```typescript\n * import { createPlatformAdminRouter, type PlatformAdminRouterOptions } from \"@alneas/eaos-server/platform-admin\";\n * export function controlRoutes(options: PlatformAdminRouterOptions) { return createPlatformAdminRouter(options); }\n * ```\n */\nexport function createPlatformAdminRouter(options: PlatformAdminRouterOptions): Hono {\n if (!options?.store || !options.resolvePrincipal || !options.authorize || !options.audit) throw new Error('Platform admin router dependencies are required')\n const app = new Hono()\n const now = options.now ?? (() => new Date())\n\n const access = async (request: Request, action: PlatformAdminAction, tenantId?: string): Promise<{ principal: PlatformAdminPrincipal } | Response> => {\n const principal = await options.resolvePrincipal(request)\n if (!principal) return new Response(JSON.stringify({ error: 'Authentication required' }), { status: 401, headers: { 'content-type': 'application/json' } })\n const allowed = principal.isPlatformAdmin === true && await options.authorize(principal, action, tenantId)\n if (!allowed) {\n await options.audit({ action, actorId: principal.userId, ...(tenantId ? { tenantId } : {}), outcome: 'denied', occurredAt: now().toISOString() })\n return new Response(JSON.stringify({ error: 'Platform administrator access required' }), { status: 403, headers: { 'content-type': 'application/json' } })\n }\n return { principal }\n }\n\n const failure = (error: unknown, status = 400) => new Response(JSON.stringify({ error: error instanceof Error ? error.message : 'Request failed' }), { status, headers: { 'content-type': 'application/json' } })\n\n app.get('/tenants', async c => {\n const authorized = await access(c.req.raw, 'tenant:list')\n if (authorized instanceof Response) return authorized\n return c.json({ tenants: await options.store.listTenants() })\n })\n\n app.post('/tenants', async c => {\n const authorized = await access(c.req.raw, 'tenant:create')\n if (authorized instanceof Response) return authorized\n try {\n const input = await body(c)\n const tenant = await options.store.createTenant({ id: string(input.id, 'tenant id'), name: string(input.name, 'tenant name'), domains: stringArray(input.domains, 'domains'), backendId: string(input.backendId, 'initial backend id') })\n await options.audit({ action: 'tenant:create', actorId: authorized.principal.userId, tenantId: tenant.id, outcome: 'allowed', occurredAt: now().toISOString() })\n return c.json({ tenant }, 201)\n } catch (error) {\n return failure(error)\n }\n })\n\n app.patch('/tenants/:tenantId', async c => {\n const tenantId = string(c.req.param('tenantId'), 'tenant id')\n const authorized = await access(c.req.raw, 'tenant:update', tenantId)\n if (authorized instanceof Response) return authorized\n try {\n const input = await body(c)\n const patch = {\n ...(input.name === undefined ? {} : { name: string(input.name, 'tenant name') }),\n ...(input.active === undefined ? {} : { active: input.active === true }),\n ...(input.domains === undefined ? {} : { domains: stringArray(input.domains, 'domains') }),\n }\n if (!Object.keys(patch).length) throw new Error('Tenant patch is empty')\n const tenant = await options.store.updateTenant(tenantId, patch)\n await options.audit({ action: 'tenant:update', actorId: authorized.principal.userId, tenantId, outcome: 'allowed', occurredAt: now().toISOString() })\n return c.json({ tenant })\n } catch (error) {\n return failure(error)\n }\n })\n\n app.get('/backends', async c => {\n const authorized = await access(c.req.raw, 'backend:list')\n if (authorized instanceof Response) return authorized\n return c.json({ backends: (await options.store.listBackends()).map(publicBackend) })\n })\n\n app.get('/tenants/:tenantId/placement', async c => {\n const tenantId = string(c.req.param('tenantId'), 'tenant id')\n const authorized = await access(c.req.raw, 'placement:read', tenantId)\n if (authorized instanceof Response) return authorized\n const placement = await options.store.getTenantPlacement(tenantId)\n if (!placement) return failure(new Error('Tenant placement not found'), 404)\n return c.json({ placement: { ...placement, backend: publicBackend(placement.backend) } })\n })\n\n app.post('/tenants/:tenantId/placement/plan', async c => {\n const tenantId = string(c.req.param('tenantId'), 'tenant id')\n const authorized = await access(c.req.raw, 'placement:plan', tenantId)\n if (authorized instanceof Response) return authorized\n try {\n const input = await body(c)\n const targetBackendId = string(input.targetBackendId, 'target backend id')\n const pluginIds = stringArray(input.pluginIds, 'pluginIds')\n const reason = string(input.reason, 'migration reason', 1024)\n const current = await options.store.getTenantPlacement(tenantId)\n if (!current) return failure(new Error('Tenant placement not found'), 404)\n const target = await options.store.getBackend(targetBackendId)\n if (!target) return failure(new Error('Target backend not found'), 404)\n const plan = planBackendMigration({\n migrationId: `platform-${crypto.randomUUID()}`,\n source: current.backend,\n target,\n scope: { kind: 'tenants', tenantIds: [tenantId] },\n pluginIds,\n requestedAt: now().toISOString(),\n reason,\n })\n await options.store.saveMigrationPlan(plan)\n await options.audit({ action: 'placement:plan', actorId: authorized.principal.userId, tenantId, sourceBackendId: plan.request.source.id, targetBackendId: plan.request.target.id, migrationId: plan.id, outcome: 'allowed', occurredAt: now().toISOString() })\n return c.json({ plan }, 201)\n } catch (error) {\n return failure(error)\n }\n })\n\n app.post('/tenants/:tenantId/placement/execute', async c => {\n const tenantId = string(c.req.param('tenantId'), 'tenant id')\n const authorized = await access(c.req.raw, 'placement:cutover', tenantId)\n if (authorized instanceof Response) return authorized\n if (!options.placementExecutor) return failure(new Error('Placement execution is not configured'), 501)\n let migrationId = ''\n let executionId = ''\n try {\n const input = await body(c)\n migrationId = string(input.migrationId, 'migration id')\n executionId = string(input.executionId, 'execution id')\n const plan = await options.store.getMigrationPlan(migrationId)\n if (!plan) return failure(new Error('Migration plan not found'), 404)\n if (plan.request.scope.kind !== 'tenants' || !plan.request.scope.tenantIds.includes(tenantId)) return failure(new Error('Migration plan tenant mismatch'), 409)\n const previous = await options.store.getMigrationStatus(migrationId)\n const current = await options.store.getTenantPlacement(tenantId)\n if (previous?.status === 'cutover') return c.json({ status: previous.status, cutover: previous.cutover, placement: current ? { ...current, backend: publicBackend(current.backend) } : null })\n if (!current || current.backend.id !== plan.request.source.id || current.backend.databaseId !== plan.request.source.databaseId) return failure(new Error('Migration plan is stale'), 409)\n const previousStatus = previous?.status\n const previousExecutionId = previous?.executionId\n const record = await options.store.beginMigrationExecution({ tenantId, migrationId, executionId })\n if (record.status === 'cutover') return c.json({ status: record.status, cutover: record.cutover, placement: { ...current, backend: publicBackend(current.backend) } })\n if (previousStatus === 'running' && previousExecutionId === executionId) return c.json({ status: 'running', migrationId }, 202)\n if (record.status === 'running') {\n const result = await options.placementExecutor.execute(plan)\n const cutover = assertBackendMigrationCutover(plan, result.verification, result.cutover)\n await options.store.recordMigrationVerification({ tenantId, plan, executionId, verification: result.verification, cutover })\n } else if (record.status !== 'verified' || !record.cutover) {\n return failure(new Error('Migration is not executable'), 409)\n }\n const verified = await options.store.getMigrationStatus(migrationId)\n if (!verified?.cutover) return failure(new Error('Migration verification is missing'), 409)\n const cutover = verified.cutover\n const placement = await options.store.recordTenantPlacement({ tenantId, plan, cutover })\n await options.audit({ action: 'placement:cutover', actorId: authorized.principal.userId, tenantId, sourceBackendId: plan.request.source.id, targetBackendId: plan.request.target.id, migrationId: plan.id, outcome: 'allowed', occurredAt: now().toISOString() })\n return c.json({ cutover, placement: { ...placement, backend: publicBackend(placement.backend) } })\n } catch (error) {\n if (migrationId) await options.store.markMigrationFailure({ migrationId, executionId: executionId || undefined, status: 'reconciling', message: error instanceof Error ? error.message : 'Migration execution failed' }).catch(() => undefined)\n return failure(error, 409)\n }\n })\n\n app.get('/tenants/:tenantId/placement/migrations/:migrationId', async c => {\n const tenantId = string(c.req.param('tenantId'), 'tenant id')\n const migrationId = string(c.req.param('migrationId'), 'migration id')\n const authorized = await access(c.req.raw, 'placement:read', tenantId)\n if (authorized instanceof Response) return authorized\n const plan = await options.store.getMigrationPlan(migrationId)\n const migration = await options.store.getMigrationStatus(migrationId)\n if (!plan || !migration) return failure(new Error('Migration not found'), 404)\n if (plan.request.scope.kind !== 'tenants' || !plan.request.scope.tenantIds.includes(tenantId)) return failure(new Error('Migration plan tenant mismatch'), 409)\n return c.json({ migration: { ...migration, plan } })\n })\n\n app.post('/tenants/:tenantId/placement/rollback', async c => {\n const tenantId = string(c.req.param('tenantId'), 'tenant id')\n const authorized = await access(c.req.raw, 'placement:rollback', tenantId)\n if (authorized instanceof Response) return authorized\n try {\n const input = await body(c)\n const migrationId = string(input.migrationId, 'migration id')\n const reason = string(input.reason, 'rollback reason', 1024)\n const plan = await options.store.createRollbackPlan({ tenantId, migrationId, reason, requestedAt: now().toISOString() })\n await options.audit({ action: 'placement:rollback', actorId: authorized.principal.userId, tenantId, sourceBackendId: plan.request.source.id, targetBackendId: plan.request.target.id, migrationId: plan.id, outcome: 'allowed', occurredAt: now().toISOString() })\n return c.json({ plan }, 201)\n } catch (error) {\n return failure(error, 409)\n }\n })\n\n app.post('/tenants/:tenantId/placement/reconcile', async c => {\n const tenantId = string(c.req.param('tenantId'), 'tenant id')\n const authorized = await access(c.req.raw, 'placement:reconcile', tenantId)\n if (authorized instanceof Response) return authorized\n try {\n const input = await body(c)\n const migrationId = string(input.migrationId, 'migration id')\n const action = string(input.action, 'reconciliation action') as 'retry' | 'mark-failed' | 'mark-reconciling' | 'commit-verified'\n const note = string(input.note, 'reconciliation note', 2048)\n const plan = await options.store.getMigrationPlan(migrationId)\n if (!plan || plan.request.scope.kind !== 'tenants' || !plan.request.scope.tenantIds.includes(tenantId)) return failure(new Error('Migration plan not found'), 404)\n if (action === 'commit-verified') {\n const migration = await options.store.getMigrationStatus(migrationId)\n if (!migration?.verification || !migration.cutover) return failure(new Error('Verified migration data is missing'), 409)\n const placement = await options.store.recordTenantPlacement({ tenantId, plan, cutover: migration.cutover })\n await options.audit({ action: 'placement:reconcile', actorId: authorized.principal.userId, tenantId, sourceBackendId: plan.request.source.id, targetBackendId: plan.request.target.id, migrationId: plan.id, outcome: 'allowed', occurredAt: now().toISOString() })\n return c.json({ migration: await options.store.getMigrationStatus(migrationId), placement: { ...placement, backend: publicBackend(placement.backend) } })\n }\n const migration = await options.store.reconcileMigration({ migrationId, action, note })\n await options.audit({ action: 'placement:reconcile', actorId: authorized.principal.userId, tenantId, sourceBackendId: plan.request.source.id, targetBackendId: plan.request.target.id, migrationId: plan.id, outcome: 'allowed', occurredAt: now().toISOString() })\n return c.json({ migration })\n } catch (error) {\n return failure(error, 409)\n }\n })\n\n return app\n}\n"],"mappings":"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","names":["cutover","migration"]}
@@ -0,0 +1,81 @@
1
+ // src/agentic/workflow-catalog.ts
2
+ var WorkflowNodeCatalog = class {
3
+ registrations = /* @__PURE__ */ new Map();
4
+ /**
5
+ * Registers a unique node type and returns a safe unregister callback.
6
+ * @param registration - Descriptor with nonblank label and type matching lowercase letters/digits/dot/underscore/hyphen up to 128 characters, plus a handler resolver.
7
+ * @returns A no-argument callback returning no value; it removes only this registration and does not remove a later replacement.
8
+ * @throws Invalid type/label, duplicate type, missing resolver, or descriptor clone failure.
9
+ * @remarks The descriptor is cloned and its label trimmed; resolver function references are retained.
10
+ * @example
11
+ * ```typescript
12
+ * import { WorkflowNodeCatalog } from "@alneas/eaos-server/agentic/workflow-catalog";
13
+ * const catalog = new WorkflowNodeCatalog();
14
+ * const dispose = catalog.register({ descriptor: { type: "example.task", label: "Example", kind: "task" }, resolve: () => async () => ({}) });
15
+ * dispose();
16
+ * ```
17
+ */
18
+ register(registration) {
19
+ const type = registration?.descriptor?.type;
20
+ if (!type || !/^[a-z0-9][a-z0-9._-]{0,127}$/.test(type)) throw new Error("Invalid workflow node catalog type");
21
+ if (this.registrations.has(type)) throw new Error(`Workflow node type '${type}' is already registered`);
22
+ if (!registration.resolve || typeof registration.resolve !== "function") throw new Error(`Workflow node '${type}' must provide a resolver`);
23
+ const descriptor = structuredClone({ ...registration.descriptor, type, label: registration.descriptor.label?.trim() });
24
+ if (!descriptor.label) throw new Error(`Workflow node '${type}' must provide a label`);
25
+ this.registrations.set(type, { ...registration, descriptor });
26
+ return () => {
27
+ if (this.registrations.get(type)?.descriptor === descriptor) this.registrations.delete(type);
28
+ };
29
+ }
30
+ /**
31
+ * Reads a registered resolver by exact node type.
32
+ * @param type - Case-sensitive catalog type identifier.
33
+ * @returns The retained registration, or undefined; mutation is not isolated by cloning.
34
+ * @example
35
+ * ```typescript
36
+ * import { WorkflowNodeCatalog } from "@alneas/eaos-server/agentic/workflow-catalog";
37
+ * console.log(new WorkflowNodeCatalog().get("example.task")); // undefined
38
+ * ```
39
+ */
40
+ get(type) {
41
+ return this.registrations.get(type);
42
+ }
43
+ /**
44
+ * Reads a registered resolver or fails if the type is unavailable.
45
+ * @param type - Exact catalog node type required by a workflow definition.
46
+ * @returns The retained registration.
47
+ * @throws If no registration exists for type.
48
+ * @example
49
+ * ```typescript
50
+ * import { WorkflowNodeCatalog, type WorkflowNodeRegistration } from "@alneas/eaos-server/agentic/workflow-catalog";
51
+ * export function registered(registration: WorkflowNodeRegistration) {
52
+ * const catalog = new WorkflowNodeCatalog();
53
+ * catalog.register(registration);
54
+ * return catalog.require(registration.descriptor.type);
55
+ * }
56
+ * ```
57
+ */
58
+ require(type) {
59
+ const registration = this.get(type);
60
+ if (!registration) throw new Error(`Workflow node type '${type}' is not registered`);
61
+ return registration;
62
+ }
63
+ /**
64
+ * Lists cloned descriptors in registration insertion order.
65
+ * @returns A new descriptor array, empty for an empty catalog; caller changes do not affect stored descriptors.
66
+ * @throws If descriptors were externally mutated to contain uncloneable values.
67
+ * @example
68
+ * ```typescript
69
+ * import { WorkflowNodeCatalog } from "@alneas/eaos-server/agentic/workflow-catalog";
70
+ * console.log(new WorkflowNodeCatalog().list()); // []
71
+ * ```
72
+ */
73
+ list() {
74
+ return structuredClone([...this.registrations.values()].map((item) => item.descriptor));
75
+ }
76
+ };
77
+
78
+ export {
79
+ WorkflowNodeCatalog
80
+ };
81
+ //# sourceMappingURL=chunk-7AHSS7SO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/agentic/workflow-catalog.ts"],"sourcesContent":["import type { WorkflowDefinition, WorkflowDefinitionNode, WorkflowDefinitionNodeKind, WorkflowToolScopeDefinition } from '@alneas/eaos-core'\nimport type { AgentGraphState, GraphNodeHandler, GraphSubgraph } from './graph'\n\n/**\n * Serializable node metadata exposed to workflow editors by {@link WorkflowNodeCatalog}.\n */\nexport interface WorkflowNodeDescriptor {\n /** Unique lowercase catalog type identifier, at most 128 characters. */\n type: string\n /** Editor label, trimmed and required during registration. */\n label: string\n /** Optional human-readable editor description. */\n description?: string\n /** Optional owning plugin ID included in visual metadata. */\n pluginId?: string\n /** Workflow node category used unless a definition overrides it. */\n kind: WorkflowDefinitionNodeKind\n /** Optional declared tool-scope metadata; execution enforcement belongs to the host handler. */\n toolScope?: WorkflowToolScopeDefinition\n /** Optional visual capability flag; compilation defaults to true when no node approval is declared. */\n canRequestApproval?: boolean\n}\n\n/**\n * Definition and node context supplied when compiling a registered workflow node.\n * @see WorkflowNodeRegistration.\n */\nexport interface WorkflowNodeResolverInput {\n /** Validated serializable workflow definition being compiled. */\n definition: WorkflowDefinition\n /** Specific definition node being resolved. */\n node: WorkflowDefinitionNode\n /** Optional runtime state for host-specific resolution; the standard compiler omits it. */\n state?: AgentGraphState\n}\n\n/**\n * Trusted host/plugin handler and optional subgraph resolution for one catalog node type.\n * @see WorkflowNodeCatalog.register.\n */\nexport interface WorkflowNodeRegistration {\n /** Serializable editor metadata cloned at registration. */\n descriptor: WorkflowNodeDescriptor\n /**\n * Resolves a plugin/host handler while preserving the Effect/Receipt boundary.\n * @param input - Validated definition and node being compiled.\n * @returns A graph handler, synchronously or asynchronously; the compiler rejects nonfunctions.\n * @throws Resolver failures reject compilation.\n \n * @example\n * ```typescript\n * import type { WorkflowNodeRegistration } from \"@alneas/eaos-server\";\n * export async function resolveHostNode(\n * registration: WorkflowNodeRegistration,\n * validatedInput: Parameters<WorkflowNodeRegistration[\"resolve\"]>[0],\n * ) {\n * const handler = await registration.resolve(validatedInput);\n * return handler; // Resolving a handler does not execute its effects.\n * }\n * ```\n */\n resolve(input: WorkflowNodeResolverInput): GraphNodeHandler | Promise<GraphNodeHandler>\n /**\n * Resolves a compiled LangGraph subgraph for a definition declaring subflow.\n * @param input - Validated definition and subflow node.\n * @returns A graph exposing invoke, synchronously or asynchronously.\n * @throws Resolver failures reject compilation.\n \n * @example\n * ```typescript\n * import type { WorkflowNodeRegistration } from \"@alneas/eaos-server\";\n * export async function resolveHostSubflow(\n * registration: WorkflowNodeRegistration,\n * validatedInput: Parameters<NonNullable<WorkflowNodeRegistration[\"resolveSubgraph\"]>>[0],\n * ) {\n * if (!registration.resolveSubgraph) throw new Error(\"This node has no subgraph resolver\");\n * return await registration.resolveSubgraph(validatedInput);\n * }\n * ```\n */\n resolveSubgraph?(input: WorkflowNodeResolverInput): GraphSubgraph | Promise<GraphSubgraph>\n}\n\n/**\n * Registers trusted host/plugin node resolvers and cloned descriptors for workflow compilation and editors.\n * @remarks Storage is process-local; no persistence or authorization is supplied.\n * @example\n * ```typescript\n * import { WorkflowNodeCatalog } from \"@alneas/eaos-server/agentic/workflow-catalog\";\n * const catalog = new WorkflowNodeCatalog();\n * const unregister = catalog.register({ descriptor: { type: \"example.task\", label: \"Example\", kind: \"task\" }, resolve: () => async () => ({}) });\n * console.log(catalog.list().length); // 1\n * unregister();\n * ```\n */\nexport class WorkflowNodeCatalog {\n private readonly registrations = new Map<string, WorkflowNodeRegistration>()\n\n /**\n * Registers a unique node type and returns a safe unregister callback.\n * @param registration - Descriptor with nonblank label and type matching lowercase letters/digits/dot/underscore/hyphen up to 128 characters, plus a handler resolver.\n * @returns A no-argument callback returning no value; it removes only this registration and does not remove a later replacement.\n * @throws Invalid type/label, duplicate type, missing resolver, or descriptor clone failure.\n * @remarks The descriptor is cloned and its label trimmed; resolver function references are retained.\n * @example\n * ```typescript\n * import { WorkflowNodeCatalog } from \"@alneas/eaos-server/agentic/workflow-catalog\";\n * const catalog = new WorkflowNodeCatalog();\n * const dispose = catalog.register({ descriptor: { type: \"example.task\", label: \"Example\", kind: \"task\" }, resolve: () => async () => ({}) });\n * dispose();\n * ```\n */\n register(registration: WorkflowNodeRegistration): () => void {\n const type = registration?.descriptor?.type\n if (!type || !/^[a-z0-9][a-z0-9._-]{0,127}$/.test(type)) throw new Error('Invalid workflow node catalog type')\n if (this.registrations.has(type)) throw new Error(`Workflow node type '${type}' is already registered`)\n if (!registration.resolve || typeof registration.resolve !== 'function') throw new Error(`Workflow node '${type}' must provide a resolver`)\n const descriptor = structuredClone({ ...registration.descriptor, type, label: registration.descriptor.label?.trim() })\n if (!descriptor.label) throw new Error(`Workflow node '${type}' must provide a label`)\n this.registrations.set(type, { ...registration, descriptor })\n return () => {\n if (this.registrations.get(type)?.descriptor === descriptor) this.registrations.delete(type)\n }\n }\n\n /**\n * Reads a registered resolver by exact node type.\n * @param type - Case-sensitive catalog type identifier.\n * @returns The retained registration, or undefined; mutation is not isolated by cloning.\n * @example\n * ```typescript\n * import { WorkflowNodeCatalog } from \"@alneas/eaos-server/agentic/workflow-catalog\";\n * console.log(new WorkflowNodeCatalog().get(\"example.task\")); // undefined\n * ```\n */\n get(type: string): WorkflowNodeRegistration | undefined { return this.registrations.get(type) }\n\n /**\n * Reads a registered resolver or fails if the type is unavailable.\n * @param type - Exact catalog node type required by a workflow definition.\n * @returns The retained registration.\n * @throws If no registration exists for type.\n * @example\n * ```typescript\n * import { WorkflowNodeCatalog, type WorkflowNodeRegistration } from \"@alneas/eaos-server/agentic/workflow-catalog\";\n * export function registered(registration: WorkflowNodeRegistration) {\n * const catalog = new WorkflowNodeCatalog();\n * catalog.register(registration);\n * return catalog.require(registration.descriptor.type);\n * }\n * ```\n */\n require(type: string): WorkflowNodeRegistration {\n const registration = this.get(type)\n if (!registration) throw new Error(`Workflow node type '${type}' is not registered`)\n return registration\n }\n\n /**\n * Lists cloned descriptors in registration insertion order.\n * @returns A new descriptor array, empty for an empty catalog; caller changes do not affect stored descriptors.\n * @throws If descriptors were externally mutated to contain uncloneable values.\n * @example\n * ```typescript\n * import { WorkflowNodeCatalog } from \"@alneas/eaos-server/agentic/workflow-catalog\";\n * console.log(new WorkflowNodeCatalog().list()); // []\n * ```\n */\n list(): readonly WorkflowNodeDescriptor[] {\n return structuredClone([...this.registrations.values()].map(item => item.descriptor))\n }\n}\n"],"mappings":";AA+FO,IAAM,sBAAN,MAA0B;AAAA,EACd,gBAAgB,oBAAI,IAAsC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgB3E,SAAS,cAAoD;AAC3D,UAAM,OAAO,cAAc,YAAY;AACvC,QAAI,CAAC,QAAQ,CAAC,+BAA+B,KAAK,IAAI,EAAG,OAAM,IAAI,MAAM,oCAAoC;AAC7G,QAAI,KAAK,cAAc,IAAI,IAAI,EAAG,OAAM,IAAI,MAAM,uBAAuB,IAAI,yBAAyB;AACtG,QAAI,CAAC,aAAa,WAAW,OAAO,aAAa,YAAY,WAAY,OAAM,IAAI,MAAM,kBAAkB,IAAI,2BAA2B;AAC1I,UAAM,aAAa,gBAAgB,EAAE,GAAG,aAAa,YAAY,MAAM,OAAO,aAAa,WAAW,OAAO,KAAK,EAAE,CAAC;AACrH,QAAI,CAAC,WAAW,MAAO,OAAM,IAAI,MAAM,kBAAkB,IAAI,wBAAwB;AACrF,SAAK,cAAc,IAAI,MAAM,EAAE,GAAG,cAAc,WAAW,CAAC;AAC5D,WAAO,MAAM;AACX,UAAI,KAAK,cAAc,IAAI,IAAI,GAAG,eAAe,WAAY,MAAK,cAAc,OAAO,IAAI;AAAA,IAC7F;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,IAAI,MAAoD;AAAE,WAAO,KAAK,cAAc,IAAI,IAAI;AAAA,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiB9F,QAAQ,MAAwC;AAC9C,UAAM,eAAe,KAAK,IAAI,IAAI;AAClC,QAAI,CAAC,aAAc,OAAM,IAAI,MAAM,uBAAuB,IAAI,qBAAqB;AACnF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,OAA0C;AACxC,WAAO,gBAAgB,CAAC,GAAG,KAAK,cAAc,OAAO,CAAC,EAAE,IAAI,UAAQ,KAAK,UAAU,CAAC;AAAA,EACtF;AACF;","names":[]}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=chunk-7FTJN4SA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,24 @@
1
+ // src/middleware/error-handler.ts
2
+ function createErrorHandler(options) {
3
+ const isProduction = options?.isProduction ?? process.env.NODE_ENV === "production";
4
+ return async (err, c) => {
5
+ if (options?.logger) {
6
+ options.logger(err, c);
7
+ } else {
8
+ console.error(`[EaosServer:Error] ${c.req.method} ${c.req.path} -`, err);
9
+ }
10
+ const message = isProduction ? "Internal Server Error" : err.message;
11
+ return c.json(
12
+ {
13
+ error: message,
14
+ ...isProduction ? {} : { stack: err.stack }
15
+ },
16
+ 500
17
+ );
18
+ };
19
+ }
20
+
21
+ export {
22
+ createErrorHandler
23
+ };
24
+ //# sourceMappingURL=chunk-AVDMLTPF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/middleware/error-handler.ts"],"sourcesContent":["import type { Context } from 'hono'\n\n/**\n * Controls error response redaction and logging for {@link createErrorHandler}.\n */\nexport interface ErrorHandlerOptions {\n /** Hide message and stack when true; defaults to NODE_ENV === \"production\". */\n isProduction?: boolean\n /** Called synchronously with the original error and request context before rendering; defaults to console.error. A thrown logger error propagates. */\n logger?: (err: Error, c: Context) => void\n}\n\n/**\n * Creates a Hono error handler that logs errors and renders a JSON 500 response.\n * @param options - Logging and redaction settings; omitted settings use console.error and NODE_ENV.\n * @returns An async handler resolving to a 500 response; production responses omit stacks and use \"Internal Server Error\".\n * @throws The returned handler rejects if the host logger throws.\n * @remarks Nonproduction responses expose error messages and stacks. Choose production redaction explicitly for externally accessible services.\n * @example\n * ```typescript\n * import { Hono } from \"hono\";\n * import { createErrorHandler } from \"@alneas/eaos-server/middleware/error-handler\";\n * const app = new Hono();\n * app.onError(createErrorHandler({ isProduction: true }));\n * app.get(\"/example\", () => { throw new Error(\"example failure\"); });\n * console.log((await app.request(\"/example\")).status); // 500\n * ```\n */\nexport function createErrorHandler(options?: ErrorHandlerOptions) {\n const isProduction = options?.isProduction ?? process.env.NODE_ENV === 'production'\n\n return async (err: Error, c: Context) => {\n if (options?.logger) {\n options.logger(err, c)\n } else {\n console.error(`[EaosServer:Error] ${c.req.method} ${c.req.path} -`, err)\n }\n\n const message = isProduction ? 'Internal Server Error' : err.message\n return c.json(\n {\n error: message,\n ...(isProduction ? {} : { stack: err.stack }),\n },\n 500\n )\n }\n}\n"],"mappings":";AA4BO,SAAS,mBAAmB,SAA+B;AAChE,QAAM,eAAe,SAAS,gBAAgB,QAAQ,IAAI,aAAa;AAEvE,SAAO,OAAO,KAAY,MAAe;AACvC,QAAI,SAAS,QAAQ;AACnB,cAAQ,OAAO,KAAK,CAAC;AAAA,IACvB,OAAO;AACL,cAAQ,MAAM,sBAAsB,EAAE,IAAI,MAAM,IAAI,EAAE,IAAI,IAAI,MAAM,GAAG;AAAA,IACzE;AAEA,UAAM,UAAU,eAAe,0BAA0B,IAAI;AAC7D,WAAO,EAAE;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,GAAI,eAAe,CAAC,IAAI,EAAE,OAAO,IAAI,MAAM;AAAA,MAC7C;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;","names":[]}