dineway 0.1.3 → 0.1.5

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 (296) hide show
  1. package/README.md +6 -3
  2. package/dist/{apply-CAPvMfoU.mjs → apply-iVSqz2qs.mjs} +132 -39
  3. package/dist/astro/index.d.mts +18 -9
  4. package/dist/astro/index.mjs +238 -16
  5. package/dist/astro/middleware/auth.d.mts +16 -5
  6. package/dist/astro/middleware/auth.mjs +74 -37
  7. package/dist/astro/middleware/redirect.mjs +24 -8
  8. package/dist/astro/middleware/request-context.mjs +18 -5
  9. package/dist/astro/middleware/setup.mjs +1 -1
  10. package/dist/astro/middleware.mjs +411 -169
  11. package/dist/astro/types.d.mts +25 -8
  12. package/dist/{byline-DeWCMU_i.mjs → byline-OhH2dlRu.mjs} +6 -21
  13. package/dist/{bylines-DyqBV9EQ.mjs → bylines-BGpD9_hy.mjs} +16 -6
  14. package/dist/cache-BdSY-gQN.mjs +42 -0
  15. package/dist/chunks--4F8ddV4.mjs +18 -0
  16. package/dist/cli/index.mjs +935 -15
  17. package/dist/client/external-auth-headers.d.mts +1 -1
  18. package/dist/client/index.d.mts +11 -3
  19. package/dist/client/index.mjs +4 -3
  20. package/dist/{connection-C9pxzuag.mjs → connection-BCNICDWN.mjs} +22 -5
  21. package/dist/{content-zSgdNmnt.mjs → content-DWi4d0rT.mjs} +41 -2
  22. package/dist/database/instrumentation.d.mts +34 -0
  23. package/dist/database/instrumentation.mjs +53 -0
  24. package/dist/db/index.d.mts +3 -3
  25. package/dist/db/index.mjs +2 -2
  26. package/dist/db/libsql.d.mts +1 -1
  27. package/dist/db/libsql.mjs +11 -5
  28. package/dist/db/postgres.d.mts +1 -1
  29. package/dist/db/sqlite.d.mts +1 -1
  30. package/dist/db/sqlite.mjs +7 -1
  31. package/dist/db-errors-CEqD7qH9.mjs +23 -0
  32. package/dist/{default-WYlzADZL.mjs → default-VjJyuuG9.mjs} +2 -0
  33. package/dist/{dialect-helpers-B9uSp2GJ.mjs → dialect-helpers-DhTzaUxP.mjs} +3 -0
  34. package/dist/{error-DrxtnGPg.mjs → error-BmL6QipT.mjs} +7 -3
  35. package/dist/{index-C-jx21qs.d.mts → index-yvc6E_17.d.mts} +157 -30
  36. package/dist/index.d.mts +11 -11
  37. package/dist/index.mjs +24 -22
  38. package/dist/{loader-qKmo0wAY.mjs → loader-sMG4TZ-u.mjs} +9 -3
  39. package/dist/media/index.d.mts +1 -1
  40. package/dist/media/index.mjs +1 -1
  41. package/dist/media/local-runtime.d.mts +7 -7
  42. package/dist/page/index.d.mts +10 -2
  43. package/dist/page/index.mjs +22 -1
  44. package/dist/patterns-CrCYkMBb.mjs +92 -0
  45. package/dist/{placeholder-bOx1xCTY.d.mts → placeholder--wOi4TbO.d.mts} +1 -1
  46. package/dist/{placeholder-B3knXwNc.mjs → placeholder-Cp8g5Emj.mjs} +1 -1
  47. package/dist/plugins/adapt-sandbox-entry.d.mts +5 -5
  48. package/dist/plugins/adapt-sandbox-entry.mjs +1 -1
  49. package/dist/{query-BiaPl_g2.mjs → query-kDmwCsHh.mjs} +118 -50
  50. package/dist/{redirect-JPqLAbxa.mjs → redirect-DnEWAkVg.mjs} +43 -99
  51. package/dist/{registry-DSd1GWB8.mjs → registry-C0zjeB9P.mjs} +191 -123
  52. package/dist/request-cache-Dk5qPSOx.mjs +66 -0
  53. package/dist/request-context.d.mts +4 -16
  54. package/dist/{runner-B5l1JfOj.d.mts → runner-CFI6B6J2.d.mts} +1 -1
  55. package/dist/{runner-BGUGywgG.mjs → runner-DWZm2KQm.mjs} +589 -137
  56. package/dist/runtime.d.mts +6 -6
  57. package/dist/runtime.mjs +2 -2
  58. package/dist/{search-BNruJHDL.mjs → search-ByRGV2pq.mjs} +570 -424
  59. package/dist/seed/index.d.mts +2 -2
  60. package/dist/seed/index.mjs +11 -10
  61. package/dist/seo/index.d.mts +1 -1
  62. package/dist/storage/local.d.mts +1 -1
  63. package/dist/storage/local.mjs +1 -1
  64. package/dist/storage/s3.d.mts +11 -3
  65. package/dist/storage/s3.mjs +78 -15
  66. package/dist/taxonomies-1s5PaS_8.mjs +266 -0
  67. package/dist/transaction-Cn2rjY78.mjs +27 -0
  68. package/dist/{types-BgQeVaPj.d.mts → types-BuMDPy5C.d.mts} +52 -3
  69. package/dist/{types-DuNbGKjF.mjs → types-COeOq9nK.mjs} +6 -1
  70. package/dist/{types-ju-_ORz7.d.mts → types-CWbdtiux.d.mts} +13 -5
  71. package/dist/{types-D38djUXv.d.mts → types-Cj0KMIZV.d.mts} +16 -3
  72. package/dist/{types-DkvMXalq.d.mts → types-DOrVigru.d.mts} +159 -0
  73. package/dist/{validate-CXnRKfJK.mjs → validate-BZ5wnLLp.mjs} +2 -1
  74. package/dist/{validate-DVKJJ-M_.d.mts → validate-IPf8n4Fj.d.mts} +4 -51
  75. package/dist/{validate-CqRJb_xU.mjs → validate-VPnKoIzW.mjs} +10 -10
  76. package/dist/version-BKXPsfmJ.mjs +6 -0
  77. package/package.json +53 -39
  78. package/src/astro/routes/PluginRegistry.tsx +21 -0
  79. package/src/astro/routes/admin.astro +99 -0
  80. package/src/astro/routes/api/admin/allowed-domains/[domain].ts +112 -0
  81. package/src/astro/routes/api/admin/allowed-domains/index.ts +108 -0
  82. package/src/astro/routes/api/admin/api-tokens/[id].ts +44 -0
  83. package/src/astro/routes/api/admin/api-tokens/index.ts +90 -0
  84. package/src/astro/routes/api/admin/briefing.ts +76 -0
  85. package/src/astro/routes/api/admin/bylines/[id]/index.ts +90 -0
  86. package/src/astro/routes/api/admin/bylines/index.ts +74 -0
  87. package/src/astro/routes/api/admin/comments/[id]/status.ts +120 -0
  88. package/src/astro/routes/api/admin/comments/[id].ts +64 -0
  89. package/src/astro/routes/api/admin/comments/bulk.ts +42 -0
  90. package/src/astro/routes/api/admin/comments/counts.ts +30 -0
  91. package/src/astro/routes/api/admin/comments/index.ts +46 -0
  92. package/src/astro/routes/api/admin/context/[id]/history.ts +35 -0
  93. package/src/astro/routes/api/admin/context/[id]/index.ts +35 -0
  94. package/src/astro/routes/api/admin/context/[id]/review.ts +57 -0
  95. package/src/astro/routes/api/admin/context/[id]/supersede.ts +58 -0
  96. package/src/astro/routes/api/admin/context/diff.ts +35 -0
  97. package/src/astro/routes/api/admin/context/index.ts +69 -0
  98. package/src/astro/routes/api/admin/context/stale.ts +35 -0
  99. package/src/astro/routes/api/admin/hitl-requests/[id]/index.ts +38 -0
  100. package/src/astro/routes/api/admin/hitl-requests/[id]/resolve.ts +54 -0
  101. package/src/astro/routes/api/admin/hitl-requests/index.ts +38 -0
  102. package/src/astro/routes/api/admin/hooks/exclusive/[hookName].ts +132 -0
  103. package/src/astro/routes/api/admin/hooks/exclusive/index.ts +51 -0
  104. package/src/astro/routes/api/admin/oauth-clients/[id].ts +137 -0
  105. package/src/astro/routes/api/admin/oauth-clients/index.ts +95 -0
  106. package/src/astro/routes/api/admin/plugins/[id]/disable.ts +91 -0
  107. package/src/astro/routes/api/admin/plugins/[id]/enable.ts +91 -0
  108. package/src/astro/routes/api/admin/plugins/[id]/index.ts +38 -0
  109. package/src/astro/routes/api/admin/plugins/[id]/uninstall.ts +98 -0
  110. package/src/astro/routes/api/admin/plugins/[id]/update.ts +154 -0
  111. package/src/astro/routes/api/admin/plugins/index.ts +32 -0
  112. package/src/astro/routes/api/admin/plugins/marketplace/[id]/icon.ts +62 -0
  113. package/src/astro/routes/api/admin/plugins/marketplace/[id]/index.ts +33 -0
  114. package/src/astro/routes/api/admin/plugins/marketplace/[id]/install.ts +135 -0
  115. package/src/astro/routes/api/admin/plugins/marketplace/index.ts +38 -0
  116. package/src/astro/routes/api/admin/plugins/updates.ts +28 -0
  117. package/src/astro/routes/api/admin/review-requests/[id]/index.ts +35 -0
  118. package/src/astro/routes/api/admin/review-requests/[id]/resolve.ts +52 -0
  119. package/src/astro/routes/api/admin/review-requests/index.ts +35 -0
  120. package/src/astro/routes/api/admin/themes/marketplace/[id]/index.ts +33 -0
  121. package/src/astro/routes/api/admin/themes/marketplace/[id]/thumbnail.ts +62 -0
  122. package/src/astro/routes/api/admin/themes/marketplace/index.ts +45 -0
  123. package/src/astro/routes/api/admin/users/[id]/disable.ts +72 -0
  124. package/src/astro/routes/api/admin/users/[id]/enable.ts +48 -0
  125. package/src/astro/routes/api/admin/users/[id]/index.ts +166 -0
  126. package/src/astro/routes/api/admin/users/[id]/send-recovery.ts +72 -0
  127. package/src/astro/routes/api/admin/users/index.ts +66 -0
  128. package/src/astro/routes/api/auth/dev-bypass.ts +139 -0
  129. package/src/astro/routes/api/auth/invite/accept.ts +52 -0
  130. package/src/astro/routes/api/auth/invite/complete.ts +86 -0
  131. package/src/astro/routes/api/auth/invite/index.ts +99 -0
  132. package/src/astro/routes/api/auth/invite/register-options.ts +73 -0
  133. package/src/astro/routes/api/auth/logout.ts +40 -0
  134. package/src/astro/routes/api/auth/magic-link/send.ts +90 -0
  135. package/src/astro/routes/api/auth/magic-link/verify.ts +71 -0
  136. package/src/astro/routes/api/auth/me.ts +60 -0
  137. package/src/astro/routes/api/auth/oauth/[provider]/callback.ts +221 -0
  138. package/src/astro/routes/api/auth/oauth/[provider].ts +120 -0
  139. package/src/astro/routes/api/auth/passkey/[id].ts +124 -0
  140. package/src/astro/routes/api/auth/passkey/index.ts +54 -0
  141. package/src/astro/routes/api/auth/passkey/options.ts +85 -0
  142. package/src/astro/routes/api/auth/passkey/register/options.ts +88 -0
  143. package/src/astro/routes/api/auth/passkey/register/verify.ts +119 -0
  144. package/src/astro/routes/api/auth/passkey/verify.ts +72 -0
  145. package/src/astro/routes/api/auth/signup/complete.ts +87 -0
  146. package/src/astro/routes/api/auth/signup/request.ts +89 -0
  147. package/src/astro/routes/api/auth/signup/verify.ts +53 -0
  148. package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +310 -0
  149. package/src/astro/routes/api/content/[collection]/[id]/compare.ts +28 -0
  150. package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +68 -0
  151. package/src/astro/routes/api/content/[collection]/[id]/duplicate.ts +77 -0
  152. package/src/astro/routes/api/content/[collection]/[id]/permanent.ts +42 -0
  153. package/src/astro/routes/api/content/[collection]/[id]/preview-url.ts +107 -0
  154. package/src/astro/routes/api/content/[collection]/[id]/publish.ts +100 -0
  155. package/src/astro/routes/api/content/[collection]/[id]/restore.ts +64 -0
  156. package/src/astro/routes/api/content/[collection]/[id]/revisions.ts +31 -0
  157. package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +129 -0
  158. package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +143 -0
  159. package/src/astro/routes/api/content/[collection]/[id]/translations.ts +50 -0
  160. package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +69 -0
  161. package/src/astro/routes/api/content/[collection]/[id].ts +173 -0
  162. package/src/astro/routes/api/content/[collection]/index.ts +103 -0
  163. package/src/astro/routes/api/content/[collection]/trash.ts +33 -0
  164. package/src/astro/routes/api/dashboard.ts +32 -0
  165. package/src/astro/routes/api/dev/emails.ts +36 -0
  166. package/src/astro/routes/api/health.ts +54 -0
  167. package/src/astro/routes/api/import/probe.ts +47 -0
  168. package/src/astro/routes/api/import/wordpress/analyze.ts +523 -0
  169. package/src/astro/routes/api/import/wordpress/execute.ts +330 -0
  170. package/src/astro/routes/api/import/wordpress/media.ts +338 -0
  171. package/src/astro/routes/api/import/wordpress/prepare.ts +212 -0
  172. package/src/astro/routes/api/import/wordpress/rewrite-urls.ts +425 -0
  173. package/src/astro/routes/api/import/wordpress-plugin/analyze.ts +111 -0
  174. package/src/astro/routes/api/import/wordpress-plugin/callback.ts +58 -0
  175. package/src/astro/routes/api/import/wordpress-plugin/execute.ts +399 -0
  176. package/src/astro/routes/api/manifest.ts +75 -0
  177. package/src/astro/routes/api/mcp.ts +125 -0
  178. package/src/astro/routes/api/media/[id]/confirm.ts +93 -0
  179. package/src/astro/routes/api/media/[id].ts +145 -0
  180. package/src/astro/routes/api/media/file/[...key].ts +79 -0
  181. package/src/astro/routes/api/media/providers/[providerId]/[itemId].ts +91 -0
  182. package/src/astro/routes/api/media/providers/[providerId]/index.ts +111 -0
  183. package/src/astro/routes/api/media/providers/index.ts +30 -0
  184. package/src/astro/routes/api/media/upload-url.ts +146 -0
  185. package/src/astro/routes/api/media.ts +204 -0
  186. package/src/astro/routes/api/menus/[name]/items.ts +206 -0
  187. package/src/astro/routes/api/menus/[name]/reorder.ts +79 -0
  188. package/src/astro/routes/api/menus/[name].ts +145 -0
  189. package/src/astro/routes/api/menus/index.ts +91 -0
  190. package/src/astro/routes/api/oauth/authorize.ts +430 -0
  191. package/src/astro/routes/api/oauth/device/authorize.ts +45 -0
  192. package/src/astro/routes/api/oauth/device/code.ts +56 -0
  193. package/src/astro/routes/api/oauth/device/token.ts +70 -0
  194. package/src/astro/routes/api/oauth/register.ts +182 -0
  195. package/src/astro/routes/api/oauth/token/refresh.ts +38 -0
  196. package/src/astro/routes/api/oauth/token/revoke.ts +38 -0
  197. package/src/astro/routes/api/oauth/token.ts +195 -0
  198. package/src/astro/routes/api/openapi.json.ts +33 -0
  199. package/src/astro/routes/api/plugins/[pluginId]/[...path].ts +109 -0
  200. package/src/astro/routes/api/redirects/404s/index.ts +72 -0
  201. package/src/astro/routes/api/redirects/404s/summary.ts +33 -0
  202. package/src/astro/routes/api/redirects/[id].ts +183 -0
  203. package/src/astro/routes/api/redirects/index.ts +100 -0
  204. package/src/astro/routes/api/revisions/[revisionId]/index.ts +29 -0
  205. package/src/astro/routes/api/revisions/[revisionId]/restore.ts +62 -0
  206. package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +104 -0
  207. package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +67 -0
  208. package/src/astro/routes/api/schema/collections/[slug]/fields/reorder.ts +45 -0
  209. package/src/astro/routes/api/schema/collections/[slug]/index.ts +107 -0
  210. package/src/astro/routes/api/schema/collections/index.ts +61 -0
  211. package/src/astro/routes/api/schema/index.ts +109 -0
  212. package/src/astro/routes/api/schema/orphans/[slug].ts +36 -0
  213. package/src/astro/routes/api/schema/orphans/index.ts +26 -0
  214. package/src/astro/routes/api/search/enable.ts +64 -0
  215. package/src/astro/routes/api/search/index.ts +52 -0
  216. package/src/astro/routes/api/search/rebuild.ts +72 -0
  217. package/src/astro/routes/api/search/stats.ts +35 -0
  218. package/src/astro/routes/api/search/suggest.ts +50 -0
  219. package/src/astro/routes/api/sections/[slug].ts +203 -0
  220. package/src/astro/routes/api/sections/index.ts +107 -0
  221. package/src/astro/routes/api/settings/email.ts +150 -0
  222. package/src/astro/routes/api/settings.ts +116 -0
  223. package/src/astro/routes/api/setup/admin-verify.ts +122 -0
  224. package/src/astro/routes/api/setup/admin.ts +104 -0
  225. package/src/astro/routes/api/setup/dev-bypass.ts +200 -0
  226. package/src/astro/routes/api/setup/dev-reset.ts +40 -0
  227. package/src/astro/routes/api/setup/index.ts +128 -0
  228. package/src/astro/routes/api/setup/status.ts +122 -0
  229. package/src/astro/routes/api/snapshot.ts +76 -0
  230. package/src/astro/routes/api/taxonomies/[name]/terms/[slug].ts +232 -0
  231. package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +131 -0
  232. package/src/astro/routes/api/taxonomies/index.ts +114 -0
  233. package/src/astro/routes/api/themes/preview.ts +78 -0
  234. package/src/astro/routes/api/typegen.ts +114 -0
  235. package/src/astro/routes/api/well-known/auth.ts +71 -0
  236. package/src/astro/routes/api/well-known/oauth-authorization-server.ts +48 -0
  237. package/src/astro/routes/api/well-known/oauth-protected-resource.ts +39 -0
  238. package/src/astro/routes/api/widget-areas/[name]/reorder.ts +114 -0
  239. package/src/astro/routes/api/widget-areas/[name]/widgets/[id].ts +213 -0
  240. package/src/astro/routes/api/widget-areas/[name]/widgets.ts +126 -0
  241. package/src/astro/routes/api/widget-areas/[name].ts +135 -0
  242. package/src/astro/routes/api/widget-areas/index.ts +149 -0
  243. package/src/astro/routes/api/widget-components.ts +22 -0
  244. package/src/astro/routes/robots.txt.ts +81 -0
  245. package/src/astro/routes/sitemap-[collection].xml.ts +104 -0
  246. package/src/astro/routes/sitemap.xml.ts +92 -0
  247. package/src/components/Break.astro +45 -0
  248. package/src/components/Button.astro +71 -0
  249. package/src/components/Buttons.astro +49 -0
  250. package/src/components/Code.astro +59 -0
  251. package/src/components/Columns.astro +59 -0
  252. package/src/components/CommentForm.astro +315 -0
  253. package/src/components/Comments.astro +232 -0
  254. package/src/components/Cover.astro +128 -0
  255. package/src/components/DinewayBodyEnd.astro +32 -0
  256. package/src/components/DinewayBodyStart.astro +32 -0
  257. package/src/components/DinewayHead.astro +61 -0
  258. package/src/components/DinewayImage.astro +178 -0
  259. package/src/components/DinewayMedia.astro +167 -0
  260. package/src/components/Embed.astro +128 -0
  261. package/src/components/File.astro +122 -0
  262. package/src/components/Gallery.astro +93 -0
  263. package/src/components/HtmlBlock.astro +33 -0
  264. package/src/components/Image.astro +178 -0
  265. package/src/components/InlineEditor.astro +27 -0
  266. package/src/components/InlinePortableTextEditor.tsx +1937 -0
  267. package/src/components/LiveSearch.astro +614 -0
  268. package/src/components/PortableText.astro +51 -0
  269. package/src/components/Pullquote.astro +51 -0
  270. package/src/components/Table.astro +135 -0
  271. package/src/components/WidgetArea.astro +22 -0
  272. package/src/components/WidgetRenderer.astro +72 -0
  273. package/src/components/index.ts +106 -0
  274. package/src/components/marks/Link.astro +31 -0
  275. package/src/components/marks/StrikeThrough.astro +7 -0
  276. package/src/components/marks/Subscript.astro +7 -0
  277. package/src/components/marks/Superscript.astro +7 -0
  278. package/src/components/marks/Underline.astro +7 -0
  279. package/src/components/marks.ts +19 -0
  280. package/src/components/widgets/Archives.astro +65 -0
  281. package/src/components/widgets/Categories.astro +35 -0
  282. package/src/components/widgets/RecentPosts.astro +51 -0
  283. package/src/components/widgets/Search.astro +18 -0
  284. package/src/components/widgets/Tags.astro +38 -0
  285. package/src/ui.ts +75 -0
  286. package/LICENSE +0 -9
  287. /package/dist/{adapters-BlzWJG82.d.mts → adapters-C2ypTrZZ.d.mts} +0 -0
  288. /package/dist/{config-Cq8H0SfX.mjs → config-BXwuX8Bx.mjs} +0 -0
  289. /package/dist/{load-C6FCD1FU.mjs → load-Coc9HpHH.mjs} +0 -0
  290. /package/dist/{manifest-schema-CTSEyIJ3.mjs → manifest-schema-D1MSVnoI.mjs} +0 -0
  291. /package/dist/{mode-BlyYtIFO.mjs → mode-47goXBBK.mjs} +0 -0
  292. /package/dist/{tokens-4vgYuXsZ.mjs → tokens-CJz9ubV6.mjs} +0 -0
  293. /package/dist/{transport-C5FYnid7.mjs → transport-DB5eDN4x.mjs} +0 -0
  294. /package/dist/{transport-gIL-e43D.d.mts → transport-Wge_IzKl.d.mts} +0 -0
  295. /package/dist/{types-CLLdsG3g.d.mts → types-BzcUjoqg.d.mts} +0 -0
  296. /package/dist/{types-DShnjzb6.mjs → types-griIBQOQ.mjs} +0 -0
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Admin HITL request resolution
3
+ *
4
+ * POST /_dineway/api/admin/hitl-requests/:id/resolve - Approve or reject a generic HITL request
5
+ */
6
+
7
+ import { Role } from "@dineway-ai/auth";
8
+ import type { APIRoute } from "astro";
9
+
10
+ import { apiError, handleError, requireDb, unwrapResult } from "#api/error.js";
11
+ import { handleHitlRequestResolve } from "#api/handlers/hitl-requests.js";
12
+ import { logHitlRouteActivity, resolveHitlRouteActor } from "#api/hitl-route-helpers.js";
13
+ import { isParseError, parseBody } from "#api/parse.js";
14
+ import { hitlRequestResolveBody } from "#api/schemas.js";
15
+
16
+ export const prerender = false;
17
+
18
+ export const POST: APIRoute = async ({ params, request, locals }) => {
19
+ const { dineway, user } = locals;
20
+ const { id } = params;
21
+
22
+ if (!id) {
23
+ return apiError("VALIDATION_ERROR", "HITL request ID required", 400);
24
+ }
25
+
26
+ const dbErr = requireDb(dineway?.db);
27
+ if (dbErr) return dbErr;
28
+
29
+ if (!user || user.role < Role.ADMIN) {
30
+ return apiError("FORBIDDEN", "Admin privileges required", 403);
31
+ }
32
+
33
+ try {
34
+ const body = await parseBody(request, hitlRequestResolveBody);
35
+ if (isParseError(body)) return body;
36
+
37
+ const actor = resolveHitlRouteActor(locals);
38
+ const result = await handleHitlRequestResolve(dineway.db, id, {
39
+ decision: body.decision,
40
+ reviewNote: body.reviewNote,
41
+ actor: actor.access,
42
+ });
43
+ if (!result.success) return unwrapResult(result);
44
+
45
+ await logHitlRouteActivity(dineway.db, locals, {
46
+ actionType: body.decision === "approved" ? "hitl.approved" : "hitl.rejected",
47
+ item: result.data.item,
48
+ });
49
+
50
+ return unwrapResult(result);
51
+ } catch (error) {
52
+ return handleError(error, "Failed to resolve HITL request", "WORKFLOW_HITL_RESOLVE_ERROR");
53
+ }
54
+ };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Admin HITL requests
3
+ *
4
+ * GET /_dineway/api/admin/hitl-requests - List generic HITL requests
5
+ */
6
+
7
+ import { Role } from "@dineway-ai/auth";
8
+ import type { APIRoute } from "astro";
9
+
10
+ import { apiError, handleError, requireDb, unwrapResult } from "#api/error.js";
11
+ import { handleHitlRequestList } from "#api/handlers/hitl-requests.js";
12
+ import { resolveHitlRouteActor } from "#api/hitl-route-helpers.js";
13
+ import { isParseError, parseQuery } from "#api/parse.js";
14
+ import { hitlRequestListQuery } from "#api/schemas.js";
15
+
16
+ export const prerender = false;
17
+
18
+ export const GET: APIRoute = async ({ url, locals }) => {
19
+ const { dineway, user } = locals;
20
+
21
+ const dbErr = requireDb(dineway?.db);
22
+ if (dbErr) return dbErr;
23
+
24
+ if (!user || user.role < Role.ADMIN) {
25
+ return apiError("FORBIDDEN", "Admin privileges required", 403);
26
+ }
27
+
28
+ try {
29
+ const query = parseQuery(url, hitlRequestListQuery);
30
+ if (isParseError(query)) return query;
31
+
32
+ const actor = resolveHitlRouteActor(locals);
33
+ const result = await handleHitlRequestList(dineway.db, actor.access, query);
34
+ return unwrapResult(result);
35
+ } catch (error) {
36
+ return handleError(error, "Failed to list HITL requests", "WORKFLOW_HITL_LIST_ERROR");
37
+ }
38
+ };
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Exclusive hook selection endpoint
3
+ *
4
+ * PUT /_dineway/api/admin/hooks/exclusive/:hookName
5
+ *
6
+ * Sets or clears the selected provider for an exclusive hook.
7
+ * Body: { pluginId: string | null }
8
+ * Requires settings:manage permission.
9
+ */
10
+
11
+ import type { APIRoute } from "astro";
12
+ import { z } from "zod";
13
+
14
+ import { requirePerm } from "#api/authorize.js";
15
+ import { apiError, apiSuccess, handleError } from "#api/error.js";
16
+ import {
17
+ ensureWorkflowHitlRouteRequest,
18
+ hitlRequiredRouteError,
19
+ resolveHitlRouteActor,
20
+ } from "#api/hitl-route-helpers.js";
21
+ import { isParseError, parseBody } from "#api/parse.js";
22
+ import {
23
+ ExclusiveHookHitlPayloadBuilder,
24
+ exclusiveHookApiRouteSource,
25
+ logExclusiveHookActivity,
26
+ RiskPolicyEvaluator,
27
+ } from "#site-context/index.js";
28
+
29
+ export const prerender = false;
30
+
31
+ /** Hook name format: namespace:action (e.g., "content:beforeSave") */
32
+ const HOOK_NAME_RE = /^[a-z]+:[a-zA-Z]+$/;
33
+
34
+ const setSelectionSchema = z.object({
35
+ pluginId: z.string().min(1).nullable(),
36
+ hitlRequestId: z.string().min(1).optional(),
37
+ });
38
+
39
+ export const PUT: APIRoute = async ({ params, request, locals }) => {
40
+ const { dineway, user } = locals;
41
+
42
+ if (!dineway?.db) {
43
+ return apiError("NOT_CONFIGURED", "Dineway is not initialized", 500);
44
+ }
45
+
46
+ const denied = requirePerm(user, "settings:manage");
47
+ if (denied) return denied;
48
+
49
+ const hookName = params.hookName;
50
+ if (!hookName) {
51
+ return apiError("VALIDATION_ERROR", "Hook name is required", 400);
52
+ }
53
+
54
+ // Validate hook name format: must be namespace:action (e.g., "content:beforeSave")
55
+ if (!HOOK_NAME_RE.test(hookName)) {
56
+ return apiError("VALIDATION_ERROR", "Invalid hook name format", 400);
57
+ }
58
+
59
+ try {
60
+ const pipeline = dineway.hooks;
61
+
62
+ // Verify this is actually an exclusive hook
63
+ if (!pipeline.isExclusiveHook(hookName)) {
64
+ return apiError("NOT_FOUND", `Hook '${hookName}' is not a registered exclusive hook`, 404);
65
+ }
66
+
67
+ const body = await parseBody(request, setSelectionSchema);
68
+ if (isParseError(body)) return body;
69
+ const providers = pipeline
70
+ .getExclusiveHookProviders(hookName)
71
+ .map((provider: { pluginId: string; pluginName?: string }) => ({
72
+ pluginId: provider.pluginId,
73
+ pluginName: provider.pluginName ?? provider.pluginId,
74
+ }));
75
+ if (body.pluginId !== null) {
76
+ const isValidProvider = providers.some((provider) => provider.pluginId === body.pluginId);
77
+ if (!isValidProvider) {
78
+ return apiError(
79
+ "VALIDATION_ERROR",
80
+ `Plugin '${body.pluginId}' is not a provider for hook '${hookName}'`,
81
+ 400,
82
+ );
83
+ }
84
+ }
85
+
86
+ const previousPluginId = await pipeline.getExclusiveHookSelection(hookName);
87
+ const actor = resolveHitlRouteActor(locals);
88
+ const evaluator = new RiskPolicyEvaluator({
89
+ db: dineway.db,
90
+ handlers: dineway,
91
+ });
92
+ let approvedHitlRequestId: string | null = null;
93
+
94
+ if (evaluator.requiresWorkflowHitl(actor.identity)) {
95
+ const action = await new ExclusiveHookHitlPayloadBuilder().buildSetSelectionRequest({
96
+ hookName,
97
+ currentPluginId: previousPluginId,
98
+ requestedPluginId: body.pluginId,
99
+ providers,
100
+ });
101
+ const decision = await evaluator.evaluateWorkflowHitl({
102
+ actor: actor.identity,
103
+ hitlRequestId: body.hitlRequestId,
104
+ action,
105
+ });
106
+ if (!decision.allowed) {
107
+ const ensured = await ensureWorkflowHitlRouteRequest(dineway.db, locals, decision.action);
108
+ return hitlRequiredRouteError(decision, ensured);
109
+ }
110
+ approvedHitlRequestId = decision.hitlRequest.id;
111
+ }
112
+
113
+ await pipeline.setExclusiveHookSelection(hookName, body.pluginId);
114
+ await logExclusiveHookActivity(dineway.db, locals, {
115
+ action: "updated",
116
+ hookName,
117
+ previousPluginId,
118
+ selectedPluginId: body.pluginId,
119
+ ...exclusiveHookApiRouteSource("updated"),
120
+ detail: {
121
+ hitlRequestId: approvedHitlRequestId,
122
+ },
123
+ });
124
+
125
+ return apiSuccess({
126
+ hookName,
127
+ selectedPluginId: body.pluginId,
128
+ });
129
+ } catch (error) {
130
+ return handleError(error, "Failed to set exclusive hook selection", "EXCLUSIVE_HOOK_SET_ERROR");
131
+ }
132
+ };
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Exclusive hooks list endpoint
3
+ *
4
+ * GET /_dineway/api/admin/hooks/exclusive
5
+ *
6
+ * Lists all exclusive hooks with their providers and current selections.
7
+ * Requires admin role.
8
+ */
9
+
10
+ import type { APIRoute } from "astro";
11
+
12
+ import { requirePerm } from "#api/authorize.js";
13
+ import { apiError, apiSuccess, handleError } from "#api/error.js";
14
+ import { OptionsRepository } from "#db/repositories/options.js";
15
+
16
+ export const prerender = false;
17
+
18
+ export const GET: APIRoute = async ({ locals }) => {
19
+ const { dineway, user } = locals;
20
+
21
+ if (!dineway?.db) {
22
+ return apiError("NOT_CONFIGURED", "Dineway is not initialized", 500);
23
+ }
24
+
25
+ const denied = requirePerm(user, "settings:manage");
26
+ if (denied) return denied;
27
+
28
+ try {
29
+ const pipeline = dineway.hooks;
30
+ const exclusiveHookNames = pipeline.getRegisteredExclusiveHooks();
31
+ const optionsRepo = new OptionsRepository(dineway.db);
32
+
33
+ const hooks = [];
34
+ for (const hookName of exclusiveHookNames) {
35
+ const providers = pipeline.getExclusiveHookProviders(hookName);
36
+ const selection = await optionsRepo.get<string>(`dineway:exclusive_hook:${hookName}`);
37
+
38
+ hooks.push({
39
+ hookName,
40
+ providers: providers.map((provider: { pluginId: string }) => ({
41
+ pluginId: provider.pluginId,
42
+ })),
43
+ selectedPluginId: selection,
44
+ });
45
+ }
46
+
47
+ return apiSuccess({ items: hooks });
48
+ } catch (error) {
49
+ return handleError(error, "Failed to list exclusive hooks", "EXCLUSIVE_HOOKS_LIST_ERROR");
50
+ }
51
+ };
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Single OAuth client endpoints
3
+ *
4
+ * GET /_dineway/api/admin/oauth-clients/:id — Get a client
5
+ * PUT /_dineway/api/admin/oauth-clients/:id — Update a client
6
+ * DELETE /_dineway/api/admin/oauth-clients/:id — Delete a client
7
+ */
8
+
9
+ import { Role } from "@dineway-ai/auth";
10
+ import type { APIRoute } from "astro";
11
+ import { z } from "zod";
12
+
13
+ import { rejectApiTokenAuthControlWrite } from "#api/auth-control-guard.js";
14
+ import { apiError, handleError, unwrapResult } from "#api/error.js";
15
+ import {
16
+ handleOAuthClientDelete,
17
+ handleOAuthClientGet,
18
+ handleOAuthClientUpdate,
19
+ } from "#api/handlers/oauth-clients.js";
20
+ import { isParseError, parseBody } from "#api/parse.js";
21
+ import { ALL_VALID_SCOPES } from "#auth/api-tokens.js";
22
+ import {
23
+ disabledExperimentalSiteContextWorkflowScopes,
24
+ getExperimentalSiteContextWorkflowScopesDisabledMessage,
25
+ } from "#site-context/experimental-workflows.js";
26
+
27
+ export const prerender = false;
28
+
29
+ const updateClientSchema = z.object({
30
+ name: z.string().min(1).max(255).optional(),
31
+ redirectUris: z
32
+ .array(z.string().url("Each redirect URI must be a valid URL"))
33
+ .min(1, "At least one redirect URI is required")
34
+ .optional(),
35
+ scopes: z.array(z.enum(ALL_VALID_SCOPES)).nullable().optional(),
36
+ });
37
+
38
+ /**
39
+ * Get a single OAuth client.
40
+ */
41
+ export const GET: APIRoute = async ({ params, locals }) => {
42
+ const { dineway, user } = locals;
43
+
44
+ if (!dineway?.db) {
45
+ return apiError("NOT_CONFIGURED", "Dineway is not initialized", 500);
46
+ }
47
+
48
+ if (!user || user.role < Role.ADMIN) {
49
+ return apiError("FORBIDDEN", "Admin privileges required", 403);
50
+ }
51
+
52
+ const credentialGuard = rejectApiTokenAuthControlWrite(locals, "oauth_clients");
53
+ if (credentialGuard) return credentialGuard;
54
+
55
+ const clientId = params.id;
56
+ if (!clientId) {
57
+ return apiError("VALIDATION_ERROR", "Client ID is required", 400);
58
+ }
59
+
60
+ const result = await handleOAuthClientGet(dineway.db, clientId);
61
+ return unwrapResult(result);
62
+ };
63
+
64
+ /**
65
+ * Update an OAuth client.
66
+ */
67
+ export const PUT: APIRoute = async ({ params, request, locals }) => {
68
+ const { dineway, user } = locals;
69
+
70
+ if (!dineway?.db) {
71
+ return apiError("NOT_CONFIGURED", "Dineway is not initialized", 500);
72
+ }
73
+
74
+ if (!user || user.role < Role.ADMIN) {
75
+ return apiError("FORBIDDEN", "Admin privileges required", 403);
76
+ }
77
+
78
+ const credentialGuard = rejectApiTokenAuthControlWrite(locals, "oauth_clients");
79
+ if (credentialGuard) return credentialGuard;
80
+
81
+ const clientId = params.id;
82
+ if (!clientId) {
83
+ return apiError("VALIDATION_ERROR", "Client ID is required", 400);
84
+ }
85
+
86
+ try {
87
+ const body = await parseBody(request, updateClientSchema);
88
+ if (isParseError(body)) return body;
89
+ const requestedWorkflowScopes = disabledExperimentalSiteContextWorkflowScopes(
90
+ body.scopes ?? [],
91
+ );
92
+ if (requestedWorkflowScopes.length > 0) {
93
+ return apiError(
94
+ "NOT_IMPLEMENTED",
95
+ getExperimentalSiteContextWorkflowScopesDisabledMessage(),
96
+ 501,
97
+ {
98
+ status: "workflow_oauth_client_scopes_disabled",
99
+ reason: "workflow_oauth_client_scopes_disabled",
100
+ scopes: requestedWorkflowScopes,
101
+ },
102
+ );
103
+ }
104
+
105
+ const result = await handleOAuthClientUpdate(dineway.db, clientId, body);
106
+ return unwrapResult(result);
107
+ } catch (error) {
108
+ return handleError(error, "Failed to update OAuth client", "CLIENT_UPDATE_ERROR");
109
+ }
110
+ };
111
+
112
+ /**
113
+ * Delete an OAuth client.
114
+ */
115
+ export const DELETE: APIRoute = async ({ params, locals }) => {
116
+ const { dineway, user } = locals;
117
+
118
+ if (!dineway?.db) {
119
+ return apiError("NOT_CONFIGURED", "Dineway is not initialized", 500);
120
+ }
121
+
122
+ if (!user || user.role < Role.ADMIN) {
123
+ return apiError("FORBIDDEN", "Admin privileges required", 403);
124
+ }
125
+
126
+ const clientId = params.id;
127
+ if (!clientId) {
128
+ return apiError("VALIDATION_ERROR", "Client ID is required", 400);
129
+ }
130
+
131
+ try {
132
+ const result = await handleOAuthClientDelete(dineway.db, clientId);
133
+ return unwrapResult(result);
134
+ } catch (error) {
135
+ return handleError(error, "Failed to delete OAuth client", "CLIENT_DELETE_ERROR");
136
+ }
137
+ };
@@ -0,0 +1,95 @@
1
+ /**
2
+ * OAuth client management endpoints
3
+ *
4
+ * GET /_dineway/api/admin/oauth-clients — List all registered OAuth clients
5
+ * POST /_dineway/api/admin/oauth-clients — Register a new OAuth client
6
+ */
7
+
8
+ import { Role } from "@dineway-ai/auth";
9
+ import type { APIRoute } from "astro";
10
+ import { z } from "zod";
11
+
12
+ import { rejectApiTokenAuthControlWrite } from "#api/auth-control-guard.js";
13
+ import { apiError, handleError, unwrapResult } from "#api/error.js";
14
+ import { handleOAuthClientCreate, handleOAuthClientList } from "#api/handlers/oauth-clients.js";
15
+ import { isParseError, parseBody } from "#api/parse.js";
16
+ import { ALL_VALID_SCOPES } from "#auth/api-tokens.js";
17
+ import {
18
+ disabledExperimentalSiteContextWorkflowScopes,
19
+ getExperimentalSiteContextWorkflowScopesDisabledMessage,
20
+ } from "#site-context/experimental-workflows.js";
21
+
22
+ export const prerender = false;
23
+
24
+ const createClientSchema = z.object({
25
+ id: z
26
+ .string()
27
+ .min(1, "Client ID is required")
28
+ .max(255, "Client ID must be at most 255 characters"),
29
+ name: z.string().min(1, "Name is required").max(255, "Name must be at most 255 characters"),
30
+ redirectUris: z
31
+ .array(z.string().url("Each redirect URI must be a valid URL"))
32
+ .min(1, "At least one redirect URI is required"),
33
+ scopes: z.array(z.enum(ALL_VALID_SCOPES)).optional(),
34
+ });
35
+
36
+ /**
37
+ * List all registered OAuth clients.
38
+ */
39
+ export const GET: APIRoute = async ({ locals }) => {
40
+ const { dineway, user } = locals;
41
+
42
+ if (!dineway?.db) {
43
+ return apiError("NOT_CONFIGURED", "Dineway is not initialized", 500);
44
+ }
45
+
46
+ if (!user || user.role < Role.ADMIN) {
47
+ return apiError("FORBIDDEN", "Admin privileges required", 403);
48
+ }
49
+
50
+ const result = await handleOAuthClientList(dineway.db);
51
+ return unwrapResult(result);
52
+ };
53
+
54
+ /**
55
+ * Register a new OAuth client.
56
+ */
57
+ export const POST: APIRoute = async ({ request, locals }) => {
58
+ const { dineway, user } = locals;
59
+
60
+ if (!dineway?.db) {
61
+ return apiError("NOT_CONFIGURED", "Dineway is not initialized", 500);
62
+ }
63
+
64
+ if (!user || user.role < Role.ADMIN) {
65
+ return apiError("FORBIDDEN", "Admin privileges required", 403);
66
+ }
67
+
68
+ const credentialGuard = rejectApiTokenAuthControlWrite(locals, "oauth_clients");
69
+ if (credentialGuard) return credentialGuard;
70
+
71
+ try {
72
+ const body = await parseBody(request, createClientSchema);
73
+ if (isParseError(body)) return body;
74
+ const requestedWorkflowScopes = disabledExperimentalSiteContextWorkflowScopes(
75
+ body.scopes ?? [],
76
+ );
77
+ if (requestedWorkflowScopes.length > 0) {
78
+ return apiError(
79
+ "NOT_IMPLEMENTED",
80
+ getExperimentalSiteContextWorkflowScopesDisabledMessage(),
81
+ 501,
82
+ {
83
+ status: "workflow_oauth_client_scopes_disabled",
84
+ reason: "workflow_oauth_client_scopes_disabled",
85
+ scopes: requestedWorkflowScopes,
86
+ },
87
+ );
88
+ }
89
+
90
+ const result = await handleOAuthClientCreate(dineway.db, body);
91
+ return unwrapResult(result, 201);
92
+ } catch (error) {
93
+ return handleError(error, "Failed to create OAuth client", "CLIENT_CREATE_ERROR");
94
+ }
95
+ };
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Plugin disable endpoint
3
+ *
4
+ * POST /_dineway/api/admin/plugins/:id/disable - Disable a plugin
5
+ */
6
+
7
+ import type { APIRoute } from "astro";
8
+ import { z } from "zod";
9
+
10
+ import { requirePerm } from "#api/authorize.js";
11
+ import { apiError, unwrapResult } from "#api/error.js";
12
+ import {
13
+ ensureWorkflowHitlRouteRequest,
14
+ hitlRequiredRouteError,
15
+ resolveHitlRouteActor,
16
+ } from "#api/hitl-route-helpers.js";
17
+ import { handlePluginDisable, handlePluginGet } from "#api/index.js";
18
+ import { isParseError, parseOptionalBody } from "#api/parse.js";
19
+ import { setCronTasksEnabled } from "#plugins/cron.js";
20
+ import {
21
+ logPluginActivity,
22
+ pluginApiRouteSource,
23
+ PluginHitlPayloadBuilder,
24
+ RiskPolicyEvaluator,
25
+ } from "#site-context/index.js";
26
+
27
+ export const prerender = false;
28
+
29
+ const hitlBodySchema = z.object({
30
+ hitlRequestId: z.string().min(1).optional(),
31
+ });
32
+
33
+ export const POST: APIRoute = async ({ params, request, locals }) => {
34
+ const { dineway, user } = locals;
35
+ const { id } = params;
36
+
37
+ if (!dineway?.db) {
38
+ return apiError("NOT_CONFIGURED", "Dineway is not initialized", 500);
39
+ }
40
+
41
+ const denied = requirePerm(user, "plugins:manage");
42
+ if (denied) return denied;
43
+
44
+ if (!id) {
45
+ return apiError("INVALID_REQUEST", "Plugin ID required", 400);
46
+ }
47
+
48
+ const body = await parseOptionalBody(request, hitlBodySchema, {});
49
+ if (isParseError(body)) return body;
50
+
51
+ const current = await handlePluginGet(
52
+ dineway.db,
53
+ dineway.configuredPlugins,
54
+ id,
55
+ dineway.config.marketplace,
56
+ );
57
+ if (!current.success) return unwrapResult(current);
58
+
59
+ const actor = resolveHitlRouteActor(locals);
60
+ const action = await new PluginHitlPayloadBuilder().buildDisableRequest(current.data.item);
61
+ const decision = await new RiskPolicyEvaluator({
62
+ db: dineway.db,
63
+ handlers: dineway,
64
+ }).evaluateWorkflowHitl({
65
+ actor: actor.identity,
66
+ hitlRequestId: body.hitlRequestId,
67
+ action,
68
+ });
69
+ if (!decision.allowed) {
70
+ const ensured = await ensureWorkflowHitlRouteRequest(dineway.db, locals, decision.action);
71
+ return hitlRequiredRouteError(decision, ensured);
72
+ }
73
+
74
+ const result = await handlePluginDisable(dineway.db, dineway.configuredPlugins, id);
75
+
76
+ if (!result.success) return unwrapResult(result);
77
+
78
+ await dineway.setPluginStatus(id, "inactive");
79
+ await setCronTasksEnabled(dineway.db, id, false);
80
+ await logPluginActivity(dineway.db, locals, {
81
+ action: "disabled",
82
+ pluginId: id,
83
+ ...pluginApiRouteSource("disabled"),
84
+ summary: `Disabled plugin ${id}`,
85
+ detail: {
86
+ hitlRequestId: decision.required ? decision.hitlRequest.id : null,
87
+ },
88
+ });
89
+
90
+ return unwrapResult(result);
91
+ };
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Plugin enable endpoint
3
+ *
4
+ * POST /_dineway/api/admin/plugins/:id/enable - Enable a plugin
5
+ */
6
+
7
+ import type { APIRoute } from "astro";
8
+ import { z } from "zod";
9
+
10
+ import { requirePerm } from "#api/authorize.js";
11
+ import { apiError, unwrapResult } from "#api/error.js";
12
+ import {
13
+ ensureWorkflowHitlRouteRequest,
14
+ hitlRequiredRouteError,
15
+ resolveHitlRouteActor,
16
+ } from "#api/hitl-route-helpers.js";
17
+ import { handlePluginEnable, handlePluginGet } from "#api/index.js";
18
+ import { isParseError, parseOptionalBody } from "#api/parse.js";
19
+ import { setCronTasksEnabled } from "#plugins/cron.js";
20
+ import {
21
+ logPluginActivity,
22
+ pluginApiRouteSource,
23
+ PluginHitlPayloadBuilder,
24
+ RiskPolicyEvaluator,
25
+ } from "#site-context/index.js";
26
+
27
+ export const prerender = false;
28
+
29
+ const hitlBodySchema = z.object({
30
+ hitlRequestId: z.string().min(1).optional(),
31
+ });
32
+
33
+ export const POST: APIRoute = async ({ params, request, locals }) => {
34
+ const { dineway, user } = locals;
35
+ const { id } = params;
36
+
37
+ if (!dineway?.db) {
38
+ return apiError("NOT_CONFIGURED", "Dineway is not initialized", 500);
39
+ }
40
+
41
+ const denied = requirePerm(user, "plugins:manage");
42
+ if (denied) return denied;
43
+
44
+ if (!id) {
45
+ return apiError("INVALID_REQUEST", "Plugin ID required", 400);
46
+ }
47
+
48
+ const body = await parseOptionalBody(request, hitlBodySchema, {});
49
+ if (isParseError(body)) return body;
50
+
51
+ const current = await handlePluginGet(
52
+ dineway.db,
53
+ dineway.configuredPlugins,
54
+ id,
55
+ dineway.config.marketplace,
56
+ );
57
+ if (!current.success) return unwrapResult(current);
58
+
59
+ const actor = resolveHitlRouteActor(locals);
60
+ const action = await new PluginHitlPayloadBuilder().buildEnableRequest(current.data.item);
61
+ const decision = await new RiskPolicyEvaluator({
62
+ db: dineway.db,
63
+ handlers: dineway,
64
+ }).evaluateWorkflowHitl({
65
+ actor: actor.identity,
66
+ hitlRequestId: body.hitlRequestId,
67
+ action,
68
+ });
69
+ if (!decision.allowed) {
70
+ const ensured = await ensureWorkflowHitlRouteRequest(dineway.db, locals, decision.action);
71
+ return hitlRequiredRouteError(decision, ensured);
72
+ }
73
+
74
+ const result = await handlePluginEnable(dineway.db, dineway.configuredPlugins, id);
75
+
76
+ if (!result.success) return unwrapResult(result);
77
+
78
+ await dineway.setPluginStatus(id, "active");
79
+ await setCronTasksEnabled(dineway.db, id, true);
80
+ await logPluginActivity(dineway.db, locals, {
81
+ action: "enabled",
82
+ pluginId: id,
83
+ ...pluginApiRouteSource("enabled"),
84
+ summary: `Enabled plugin ${id}`,
85
+ detail: {
86
+ hitlRequestId: decision.required ? decision.hitlRequest.id : null,
87
+ },
88
+ });
89
+
90
+ return unwrapResult(result);
91
+ };