dineway 0.1.9 → 0.1.11

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 (689) hide show
  1. package/README.md +63 -17
  2. package/dist/activity-events-BsMaXdJa.mjs +540 -0
  3. package/dist/allowed-origins-DG86sH8U.mjs +68 -0
  4. package/dist/api/route-utils.d.mts +41 -0
  5. package/dist/api/route-utils.mjs +26 -0
  6. package/dist/api/schemas/index.d.mts +3 -0
  7. package/dist/api/schemas/index.mjs +6 -0
  8. package/dist/api/schemas/setup.d.mts +42 -0
  9. package/dist/api/schemas/setup.mjs +39 -0
  10. package/dist/api-Cmy8Rjk5.mjs +2704 -0
  11. package/dist/api-tokens-Bu3ez1MO.mjs +153 -0
  12. package/dist/api-tokens-DzloJxuh.mjs +3 -0
  13. package/dist/{apply-iVSqz2qs.mjs → apply-Co5imxxT.mjs} +15 -689
  14. package/dist/astro/index.d.mts +10 -6
  15. package/dist/astro/index.mjs +86 -11
  16. package/dist/astro/middleware/auth.d.mts +10 -7
  17. package/dist/astro/middleware/auth.mjs +19 -104
  18. package/dist/astro/middleware/redirect.mjs +24 -14
  19. package/dist/astro/middleware/request-context.mjs +9 -6
  20. package/dist/astro/middleware/setup.mjs +1 -1
  21. package/dist/astro/middleware.mjs +86 -145
  22. package/dist/astro/routes/PluginRegistry.d.mts +14 -0
  23. package/dist/astro/routes/PluginRegistry.mjs +24 -0
  24. package/dist/astro/routes/api/admin/allowed-domains/_domain_.d.mts +14 -0
  25. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +65 -0
  26. package/dist/astro/routes/api/admin/allowed-domains/index.d.mts +14 -0
  27. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +65 -0
  28. package/dist/astro/routes/api/admin/api-tokens/_id_.d.mts +10 -0
  29. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +33 -0
  30. package/dist/astro/routes/api/admin/api-tokens/index.d.mts +16 -0
  31. package/dist/astro/routes/api/admin/api-tokens/index.mjs +59 -0
  32. package/dist/astro/routes/api/admin/briefing.d.mts +7 -0
  33. package/dist/astro/routes/api/admin/briefing.mjs +71 -0
  34. package/dist/astro/routes/api/admin/bylines/_id_/index.d.mts +9 -0
  35. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +74 -0
  36. package/dist/astro/routes/api/admin/bylines/index.d.mts +8 -0
  37. package/dist/astro/routes/api/admin/bylines/index.mjs +61 -0
  38. package/dist/astro/routes/api/admin/comments/_id_/status.d.mts +7 -0
  39. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +80 -0
  40. package/dist/astro/routes/api/admin/comments/_id_.d.mts +14 -0
  41. package/dist/astro/routes/api/admin/comments/_id_.mjs +46 -0
  42. package/dist/astro/routes/api/admin/comments/bulk.d.mts +7 -0
  43. package/dist/astro/routes/api/admin/comments/bulk.mjs +36 -0
  44. package/dist/astro/routes/api/admin/comments/counts.d.mts +7 -0
  45. package/dist/astro/routes/api/admin/comments/counts.mjs +24 -0
  46. package/dist/astro/routes/api/admin/comments/index.d.mts +10 -0
  47. package/dist/astro/routes/api/admin/comments/index.mjs +40 -0
  48. package/dist/astro/routes/api/admin/context/_id_/history.d.mts +7 -0
  49. package/dist/astro/routes/api/admin/context/_id_/history.mjs +45 -0
  50. package/dist/astro/routes/api/admin/context/_id_/index.d.mts +7 -0
  51. package/dist/astro/routes/api/admin/context/_id_/index.mjs +45 -0
  52. package/dist/astro/routes/api/admin/context/_id_/review.d.mts +7 -0
  53. package/dist/astro/routes/api/admin/context/_id_/review.mjs +60 -0
  54. package/dist/astro/routes/api/admin/context/_id_/supersede.d.mts +7 -0
  55. package/dist/astro/routes/api/admin/context/_id_/supersede.mjs +63 -0
  56. package/dist/astro/routes/api/admin/context/diff.d.mts +7 -0
  57. package/dist/astro/routes/api/admin/context/diff.mjs +49 -0
  58. package/dist/astro/routes/api/admin/context/index.d.mts +8 -0
  59. package/dist/astro/routes/api/admin/context/index.mjs +71 -0
  60. package/dist/astro/routes/api/admin/context/stale.d.mts +7 -0
  61. package/dist/astro/routes/api/admin/context/stale.mjs +49 -0
  62. package/dist/astro/routes/api/admin/hitl-requests/_id_/index.d.mts +7 -0
  63. package/dist/astro/routes/api/admin/hitl-requests/_id_/index.mjs +51 -0
  64. package/dist/astro/routes/api/admin/hitl-requests/_id_/resolve.d.mts +7 -0
  65. package/dist/astro/routes/api/admin/hitl-requests/_id_/resolve.mjs +67 -0
  66. package/dist/astro/routes/api/admin/hitl-requests/index.d.mts +7 -0
  67. package/dist/astro/routes/api/admin/hitl-requests/index.mjs +55 -0
  68. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.d.mts +7 -0
  69. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +98 -0
  70. package/dist/astro/routes/api/admin/hooks/exclusive/index.d.mts +7 -0
  71. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +33 -0
  72. package/dist/astro/routes/api/admin/oauth-clients/_id_.d.mts +18 -0
  73. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +79 -0
  74. package/dist/astro/routes/api/admin/oauth-clients/index.d.mts +14 -0
  75. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +58 -0
  76. package/dist/astro/routes/api/admin/plugins/_id_/disable.d.mts +7 -0
  77. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +89 -0
  78. package/dist/astro/routes/api/admin/plugins/_id_/enable.d.mts +7 -0
  79. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +89 -0
  80. package/dist/astro/routes/api/admin/plugins/_id_/index.d.mts +7 -0
  81. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +54 -0
  82. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.d.mts +7 -0
  83. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +98 -0
  84. package/dist/astro/routes/api/admin/plugins/_id_/update.d.mts +7 -0
  85. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +131 -0
  86. package/dist/astro/routes/api/admin/plugins/index.d.mts +7 -0
  87. package/dist/astro/routes/api/admin/plugins/index.mjs +52 -0
  88. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.d.mts +7 -0
  89. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +36 -0
  90. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.d.mts +7 -0
  91. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +54 -0
  92. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.d.mts +7 -0
  93. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +128 -0
  94. package/dist/astro/routes/api/admin/plugins/marketplace/index.d.mts +7 -0
  95. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +61 -0
  96. package/dist/astro/routes/api/admin/plugins/updates.d.mts +7 -0
  97. package/dist/astro/routes/api/admin/plugins/updates.mjs +52 -0
  98. package/dist/astro/routes/api/admin/review-requests/_id_/index.d.mts +7 -0
  99. package/dist/astro/routes/api/admin/review-requests/_id_/index.mjs +26 -0
  100. package/dist/astro/routes/api/admin/review-requests/_id_/resolve.d.mts +7 -0
  101. package/dist/astro/routes/api/admin/review-requests/_id_/resolve.mjs +97 -0
  102. package/dist/astro/routes/api/admin/review-requests/index.d.mts +7 -0
  103. package/dist/astro/routes/api/admin/review-requests/index.mjs +31 -0
  104. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.d.mts +7 -0
  105. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +54 -0
  106. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.d.mts +7 -0
  107. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +36 -0
  108. package/dist/astro/routes/api/admin/themes/marketplace/index.d.mts +7 -0
  109. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +70 -0
  110. package/dist/astro/routes/api/admin/users/_id_/disable.d.mts +7 -0
  111. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +38 -0
  112. package/dist/astro/routes/api/admin/users/_id_/enable.d.mts +7 -0
  113. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +29 -0
  114. package/dist/astro/routes/api/admin/users/_id_/index.d.mts +8 -0
  115. package/dist/astro/routes/api/admin/users/_id_/index.mjs +104 -0
  116. package/dist/astro/routes/api/admin/users/_id_/send-recovery.d.mts +7 -0
  117. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +43 -0
  118. package/dist/astro/routes/api/admin/users/index.d.mts +7 -0
  119. package/dist/astro/routes/api/admin/users/index.mjs +54 -0
  120. package/dist/astro/routes/api/auth/dev-bypass.d.mts +8 -0
  121. package/dist/astro/routes/api/auth/dev-bypass.mjs +81 -0
  122. package/dist/astro/routes/api/auth/invite/accept.d.mts +7 -0
  123. package/dist/astro/routes/api/auth/invite/accept.mjs +31 -0
  124. package/dist/astro/routes/api/auth/invite/complete.d.mts +7 -0
  125. package/dist/astro/routes/api/auth/invite/complete.mjs +54 -0
  126. package/dist/astro/routes/api/auth/invite/index.d.mts +7 -0
  127. package/dist/astro/routes/api/auth/invite/index.mjs +51 -0
  128. package/dist/astro/routes/api/auth/invite/register-options.d.mts +7 -0
  129. package/dist/astro/routes/api/auth/invite/register-options.mjs +44 -0
  130. package/dist/astro/routes/api/auth/logout.d.mts +7 -0
  131. package/dist/astro/routes/api/auth/logout.mjs +24 -0
  132. package/dist/astro/routes/api/auth/magic-link/send.d.mts +7 -0
  133. package/dist/astro/routes/api/auth/magic-link/send.mjs +48 -0
  134. package/dist/astro/routes/api/auth/magic-link/verify.d.mts +7 -0
  135. package/dist/astro/routes/api/auth/magic-link/verify.mjs +32 -0
  136. package/dist/astro/routes/api/auth/me.d.mts +13 -0
  137. package/dist/astro/routes/api/auth/me.mjs +41 -0
  138. package/dist/astro/routes/api/auth/mode.d.mts +7 -0
  139. package/dist/astro/routes/api/auth/mode.mjs +28 -0
  140. package/dist/astro/routes/api/auth/oauth/_provider_/callback.d.mts +7 -0
  141. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +114 -0
  142. package/dist/astro/routes/api/auth/oauth/_provider_.d.mts +7 -0
  143. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +58 -0
  144. package/dist/astro/routes/api/auth/passkey/_id_.d.mts +14 -0
  145. package/dist/astro/routes/api/auth/passkey/_id_.mjs +62 -0
  146. package/dist/astro/routes/api/auth/passkey/index.d.mts +7 -0
  147. package/dist/astro/routes/api/auth/passkey/index.mjs +25 -0
  148. package/dist/astro/routes/api/auth/passkey/options.d.mts +7 -0
  149. package/dist/astro/routes/api/auth/passkey/options.mjs +46 -0
  150. package/dist/astro/routes/api/auth/passkey/register/options.d.mts +7 -0
  151. package/dist/astro/routes/api/auth/passkey/register/options.mjs +44 -0
  152. package/dist/astro/routes/api/auth/passkey/register/verify.d.mts +7 -0
  153. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +59 -0
  154. package/dist/astro/routes/api/auth/passkey/verify.d.mts +7 -0
  155. package/dist/astro/routes/api/auth/passkey/verify.mjs +47 -0
  156. package/dist/astro/routes/api/auth/signup/complete.d.mts +7 -0
  157. package/dist/astro/routes/api/auth/signup/complete.mjs +55 -0
  158. package/dist/astro/routes/api/auth/signup/request.d.mts +7 -0
  159. package/dist/astro/routes/api/auth/signup/request.mjs +44 -0
  160. package/dist/astro/routes/api/auth/signup/verify.d.mts +7 -0
  161. package/dist/astro/routes/api/auth/signup/verify.mjs +32 -0
  162. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.d.mts +14 -0
  163. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +193 -0
  164. package/dist/astro/routes/api/content/_collection_/_id_/compare.d.mts +7 -0
  165. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +17 -0
  166. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.d.mts +7 -0
  167. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +36 -0
  168. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.d.mts +7 -0
  169. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +39 -0
  170. package/dist/astro/routes/api/content/_collection_/_id_/permanent.d.mts +7 -0
  171. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +31 -0
  172. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.d.mts +7 -0
  173. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +78 -0
  174. package/dist/astro/routes/api/content/_collection_/_id_/publish.d.mts +7 -0
  175. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +92 -0
  176. package/dist/astro/routes/api/content/_collection_/_id_/restore.d.mts +7 -0
  177. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +36 -0
  178. package/dist/astro/routes/api/content/_collection_/_id_/revisions.d.mts +7 -0
  179. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +19 -0
  180. package/dist/astro/routes/api/content/_collection_/_id_/schedule.d.mts +8 -0
  181. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +75 -0
  182. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.d.mts +14 -0
  183. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +85 -0
  184. package/dist/astro/routes/api/content/_collection_/_id_/translations.d.mts +7 -0
  185. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +40 -0
  186. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.d.mts +7 -0
  187. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +36 -0
  188. package/dist/astro/routes/api/content/_collection_/_id_.d.mts +9 -0
  189. package/dist/astro/routes/api/content/_collection_/_id_.mjs +114 -0
  190. package/dist/astro/routes/api/content/_collection_/index.d.mts +8 -0
  191. package/dist/astro/routes/api/content/_collection_/index.mjs +74 -0
  192. package/dist/astro/routes/api/content/_collection_/trash.d.mts +7 -0
  193. package/dist/astro/routes/api/content/_collection_/trash.mjs +23 -0
  194. package/dist/astro/routes/api/dashboard.d.mts +7 -0
  195. package/dist/astro/routes/api/dashboard.mjs +26 -0
  196. package/dist/astro/routes/api/dev/emails.d.mts +8 -0
  197. package/dist/astro/routes/api/dev/emails.mjs +17 -0
  198. package/dist/astro/routes/api/health.d.mts +7 -0
  199. package/dist/astro/routes/api/health.mjs +34 -0
  200. package/dist/astro/routes/api/import/probe.d.mts +17 -0
  201. package/dist/astro/routes/api/import/probe.mjs +33 -0
  202. package/dist/astro/routes/api/import/wordpress/analyze.d.mts +87 -0
  203. package/dist/astro/routes/api/import/wordpress/analyze.mjs +305 -0
  204. package/dist/astro/routes/api/import/wordpress/execute.d.mts +37 -0
  205. package/dist/astro/routes/api/import/wordpress/execute.mjs +197 -0
  206. package/dist/astro/routes/api/import/wordpress/media.d.mts +35 -0
  207. package/dist/astro/routes/api/import/wordpress/media.mjs +222 -0
  208. package/dist/astro/routes/api/import/wordpress/prepare.d.mts +19 -0
  209. package/dist/astro/routes/api/import/wordpress/prepare.mjs +155 -0
  210. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +21 -0
  211. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +289 -0
  212. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +15 -0
  213. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +69 -0
  214. package/dist/astro/routes/api/import/wordpress-plugin/callback.d.mts +7 -0
  215. package/dist/astro/routes/api/import/wordpress-plugin/callback.mjs +28 -0
  216. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +19 -0
  217. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +268 -0
  218. package/dist/astro/routes/api/manifest.d.mts +7 -0
  219. package/dist/astro/routes/api/manifest.mjs +50 -0
  220. package/dist/astro/routes/api/mcp.d.mts +15 -0
  221. package/dist/astro/routes/api/mcp.mjs +2700 -0
  222. package/dist/astro/routes/api/media/_id_/confirm.d.mts +10 -0
  223. package/dist/astro/routes/api/media/_id_/confirm.mjs +59 -0
  224. package/dist/astro/routes/api/media/_id_.d.mts +22 -0
  225. package/dist/astro/routes/api/media/_id_.mjs +81 -0
  226. package/dist/astro/routes/api/media/file/_...key_.d.mts +7 -0
  227. package/dist/astro/routes/api/media/file/_...key_.mjs +49 -0
  228. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.d.mts +14 -0
  229. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +49 -0
  230. package/dist/astro/routes/api/media/providers/_providerId_/index.d.mts +14 -0
  231. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +72 -0
  232. package/dist/astro/routes/api/media/providers/index.d.mts +10 -0
  233. package/dist/astro/routes/api/media/providers/index.mjs +18 -0
  234. package/dist/astro/routes/api/media/upload-url.d.mts +10 -0
  235. package/dist/astro/routes/api/media/upload-url.mjs +82 -0
  236. package/dist/astro/routes/api/media.d.mts +16 -0
  237. package/dist/astro/routes/api/media.mjs +137 -0
  238. package/dist/astro/routes/api/menus/_name_/items.d.mts +9 -0
  239. package/{src/astro/routes/api/menus/[name]/items.ts → dist/astro/routes/api/menus/_name_/items.mjs} +63 -105
  240. package/dist/astro/routes/api/menus/_name_/reorder.d.mts +7 -0
  241. package/dist/astro/routes/api/menus/_name_/reorder.mjs +77 -0
  242. package/dist/astro/routes/api/menus/_name_.d.mts +9 -0
  243. package/dist/astro/routes/api/menus/_name_.mjs +123 -0
  244. package/dist/astro/routes/api/menus/index.d.mts +8 -0
  245. package/dist/astro/routes/api/menus/index.mjs +84 -0
  246. package/dist/astro/routes/api/oauth/authorize.d.mts +8 -0
  247. package/dist/astro/routes/api/oauth/authorize.mjs +265 -0
  248. package/dist/astro/routes/api/oauth/device/authorize.d.mts +7 -0
  249. package/dist/astro/routes/api/oauth/device/authorize.mjs +30 -0
  250. package/dist/astro/routes/api/oauth/device/code.d.mts +7 -0
  251. package/dist/astro/routes/api/oauth/device/code.mjs +34 -0
  252. package/dist/astro/routes/api/oauth/device/token.d.mts +7 -0
  253. package/dist/astro/routes/api/oauth/device/token.mjs +45 -0
  254. package/dist/astro/routes/api/oauth/register.d.mts +8 -0
  255. package/dist/astro/routes/api/oauth/register.mjs +115 -0
  256. package/dist/astro/routes/api/oauth/token/refresh.d.mts +7 -0
  257. package/dist/astro/routes/api/oauth/token/refresh.mjs +28 -0
  258. package/dist/astro/routes/api/oauth/token/revoke.d.mts +7 -0
  259. package/dist/astro/routes/api/oauth/token/revoke.mjs +25 -0
  260. package/dist/astro/routes/api/oauth/token.d.mts +8 -0
  261. package/dist/astro/routes/api/oauth/token.mjs +138 -0
  262. package/dist/astro/routes/api/openapi.json.d.mts +7 -0
  263. package/dist/astro/routes/api/openapi.json.mjs +2638 -0
  264. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.d.mts +11 -0
  265. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +77 -0
  266. package/dist/astro/routes/api/redirects/404s/index.d.mts +9 -0
  267. package/dist/astro/routes/api/redirects/404s/index.mjs +62 -0
  268. package/dist/astro/routes/api/redirects/404s/summary.d.mts +7 -0
  269. package/dist/astro/routes/api/redirects/404s/summary.mjs +34 -0
  270. package/dist/astro/routes/api/redirects/_id_.d.mts +9 -0
  271. package/dist/astro/routes/api/redirects/_id_.mjs +152 -0
  272. package/dist/astro/routes/api/redirects/index.d.mts +8 -0
  273. package/dist/astro/routes/api/redirects/index.mjs +97 -0
  274. package/dist/astro/routes/api/revisions/_revisionId_/index.d.mts +7 -0
  275. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +16 -0
  276. package/dist/astro/routes/api/revisions/_revisionId_/restore.d.mts +7 -0
  277. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +23 -0
  278. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.d.mts +9 -0
  279. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +98 -0
  280. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.d.mts +8 -0
  281. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +80 -0
  282. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.d.mts +7 -0
  283. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +67 -0
  284. package/dist/astro/routes/api/schema/collections/_slug_/index.d.mts +9 -0
  285. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +97 -0
  286. package/dist/astro/routes/api/schema/collections/index.d.mts +8 -0
  287. package/dist/astro/routes/api/schema/collections/index.mjs +77 -0
  288. package/dist/astro/routes/api/schema/index.d.mts +7 -0
  289. package/dist/astro/routes/api/schema/index.mjs +79 -0
  290. package/dist/astro/routes/api/schema/orphans/_slug_.d.mts +7 -0
  291. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +58 -0
  292. package/dist/astro/routes/api/schema/orphans/index.d.mts +7 -0
  293. package/dist/astro/routes/api/schema/orphans/index.mjs +53 -0
  294. package/dist/astro/routes/api/search/enable.d.mts +15 -0
  295. package/dist/astro/routes/api/search/enable.mjs +55 -0
  296. package/dist/astro/routes/api/search/index.d.mts +16 -0
  297. package/dist/astro/routes/api/search/index.mjs +52 -0
  298. package/dist/astro/routes/api/search/rebuild.d.mts +13 -0
  299. package/dist/astro/routes/api/search/rebuild.mjs +48 -0
  300. package/dist/astro/routes/api/search/stats.d.mts +10 -0
  301. package/dist/astro/routes/api/search/stats.mjs +28 -0
  302. package/dist/astro/routes/api/search/suggest.d.mts +15 -0
  303. package/dist/astro/routes/api/search/suggest.mjs +43 -0
  304. package/dist/astro/routes/api/sections/_slug_.d.mts +9 -0
  305. package/dist/astro/routes/api/sections/_slug_.mjs +156 -0
  306. package/dist/astro/routes/api/sections/index.d.mts +8 -0
  307. package/dist/astro/routes/api/sections/index.mjs +99 -0
  308. package/dist/astro/routes/api/settings/email.d.mts +17 -0
  309. package/dist/astro/routes/api/settings/email.mjs +102 -0
  310. package/dist/astro/routes/api/settings.d.mts +20 -0
  311. package/dist/astro/routes/api/settings.mjs +101 -0
  312. package/dist/astro/routes/api/setup/admin-verify.d.mts +7 -0
  313. package/dist/astro/routes/api/setup/admin-verify.mjs +67 -0
  314. package/dist/astro/routes/api/setup/admin.d.mts +7 -0
  315. package/dist/astro/routes/api/setup/admin.mjs +68 -0
  316. package/dist/astro/routes/api/setup/dev-bypass.d.mts +8 -0
  317. package/dist/astro/routes/api/setup/dev-bypass.mjs +137 -0
  318. package/dist/astro/routes/api/setup/dev-reset.d.mts +7 -0
  319. package/dist/astro/routes/api/setup/dev-reset.mjs +22 -0
  320. package/dist/astro/routes/api/setup/index.d.mts +7 -0
  321. package/dist/astro/routes/api/setup/index.mjs +93 -0
  322. package/dist/astro/routes/api/setup/status.d.mts +7 -0
  323. package/dist/astro/routes/api/setup/status.mjs +57 -0
  324. package/dist/astro/routes/api/snapshot.d.mts +7 -0
  325. package/dist/astro/routes/api/snapshot.mjs +227 -0
  326. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.d.mts +18 -0
  327. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +189 -0
  328. package/dist/astro/routes/api/taxonomies/_name_/terms/index.d.mts +14 -0
  329. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +113 -0
  330. package/dist/astro/routes/api/taxonomies/index.d.mts +14 -0
  331. package/dist/astro/routes/api/taxonomies/index.mjs +103 -0
  332. package/dist/astro/routes/api/themes/preview.d.mts +7 -0
  333. package/dist/astro/routes/api/themes/preview.mjs +47 -0
  334. package/dist/astro/routes/api/typegen.d.mts +17 -0
  335. package/dist/astro/routes/api/typegen.mjs +75 -0
  336. package/dist/astro/routes/api/well-known/auth.d.mts +7 -0
  337. package/dist/astro/routes/api/well-known/auth.mjs +42 -0
  338. package/dist/astro/routes/api/well-known/oauth-authorization-server.d.mts +7 -0
  339. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +33 -0
  340. package/dist/astro/routes/api/well-known/oauth-protected-resource.d.mts +7 -0
  341. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +21 -0
  342. package/dist/astro/routes/api/widget-areas/_name_/reorder.d.mts +7 -0
  343. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +88 -0
  344. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.d.mts +8 -0
  345. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +158 -0
  346. package/dist/astro/routes/api/widget-areas/_name_/widgets.d.mts +7 -0
  347. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +104 -0
  348. package/dist/astro/routes/api/widget-areas/_name_.d.mts +8 -0
  349. package/dist/astro/routes/api/widget-areas/_name_.mjs +99 -0
  350. package/dist/astro/routes/api/widget-areas/index.d.mts +8 -0
  351. package/dist/astro/routes/api/widget-areas/index.mjs +108 -0
  352. package/dist/astro/routes/api/widget-components.d.mts +7 -0
  353. package/dist/astro/routes/api/widget-components.mjs +15 -0
  354. package/dist/astro/routes/robots.txt.d.mts +7 -0
  355. package/dist/astro/routes/robots.txt.mjs +60 -0
  356. package/dist/astro/routes/sitemap-_collection_.xml.d.mts +7 -0
  357. package/dist/astro/routes/sitemap-_collection_.xml.mjs +70 -0
  358. package/dist/astro/routes/sitemap.xml.d.mts +7 -0
  359. package/dist/astro/routes/sitemap.xml.mjs +63 -0
  360. package/dist/astro/types.d.mts +41 -9
  361. package/dist/auth/providers/github-admin.d.mts +9 -0
  362. package/dist/auth/providers/github-admin.mjs +27 -0
  363. package/dist/auth/providers/github.d.mts +12 -0
  364. package/dist/auth/providers/github.mjs +17 -0
  365. package/dist/auth/providers/google-admin.d.mts +9 -0
  366. package/dist/auth/providers/google-admin.mjs +43 -0
  367. package/dist/auth/providers/google.d.mts +12 -0
  368. package/dist/auth/providers/google.mjs +17 -0
  369. package/dist/auth-control-guard-DKUe_1oa.mjs +13 -0
  370. package/dist/authorize-BBj8C6Y8.mjs +36 -0
  371. package/dist/briefing-BrXCuMEE.mjs +1294 -0
  372. package/dist/briefing-ClWw4mc9.mjs +29 -0
  373. package/dist/{byline-OhH2dlRu.mjs → byline-naZxOPSa.mjs} +3 -3
  374. package/dist/{bylines-BGpD9_hy.mjs → bylines-BcOPh6Ej.mjs} +20 -53
  375. package/dist/bylines-HfUKum_j.d.mts +2023 -0
  376. package/dist/{cache-BdSY-gQN.mjs → cache-DEbQ13c9.mjs} +21 -11
  377. package/dist/challenge-store-DHMgBGOq.mjs +48 -0
  378. package/dist/cli/index.mjs +142 -22
  379. package/dist/client/external-auth-headers.d.mts +1 -1
  380. package/dist/client/index.d.mts +1 -1
  381. package/dist/client/index.mjs +3 -3
  382. package/dist/comment-DFO-gWDH.mjs +246 -0
  383. package/dist/comments-Gy3zLBaP.mjs +186 -0
  384. package/dist/components-DND2rd3D.mjs +107 -0
  385. package/dist/{content-DWi4d0rT.mjs → content-CyLkb-qH.mjs} +33 -44
  386. package/dist/context-bE5Kyvcj.mjs +184 -0
  387. package/dist/context-nxMyOe3p.mjs +849 -0
  388. package/dist/context-route-helpers-D-6uCQ0S.mjs +45 -0
  389. package/dist/context-types-C-LwdAxx.mjs +23 -0
  390. package/dist/cron-DGzVTtJp.mjs +263 -0
  391. package/dist/dashboard-DqnYU8EU.mjs +120 -0
  392. package/dist/db/index.d.mts +3 -3
  393. package/dist/db/libsql.d.mts +1 -1
  394. package/dist/db/libsql.mjs +3 -3
  395. package/dist/db/postgres.d.mts +1 -1
  396. package/dist/db/sqlite.d.mts +1 -1
  397. package/dist/db/sqlite.mjs +1 -2
  398. package/dist/device-flow-7AhWNwCK.mjs +487 -0
  399. package/dist/email-console-CgLVZbcn.mjs +36 -0
  400. package/dist/entity-aliases-C0v-yNET.mjs +51 -0
  401. package/dist/error-DEGjx2Xw.mjs +435 -0
  402. package/dist/escape-mNZr4t2A.mjs +8 -0
  403. package/dist/experimental-workflows-DldxJlqV.mjs +38 -0
  404. package/dist/fts-manager-B1pTNEG_.mjs +297 -0
  405. package/dist/hash-CDX7M0ze.mjs +32 -0
  406. package/dist/hitl-requests-Bx3Bkk9l.mjs +118 -0
  407. package/dist/hitl-route-helpers-DMmJRS7B.mjs +96 -0
  408. package/dist/import-DD3f2jkc.mjs +243 -0
  409. package/dist/import-DVZcYlDp.mjs +1323 -0
  410. package/dist/index-CkljPf5F.d.mts +227 -0
  411. package/dist/index.d.mts +15 -11
  412. package/dist/index.mjs +60 -22
  413. package/dist/{loader-sMG4TZ-u.mjs → loader-PZnPxFLc.mjs} +42 -5
  414. package/dist/{manifest-schema-D1MSVnoI.mjs → manifest-schema-DYoCQ5np.mjs} +22 -10
  415. package/dist/media/index.d.mts +1 -1
  416. package/dist/media/index.mjs +2 -1
  417. package/dist/media/local-runtime.d.mts +11 -7
  418. package/dist/media/local-runtime.mjs +3 -3
  419. package/dist/{media-DMTr80Gv.mjs → media-_7Fxdu45.mjs} +1 -1
  420. package/dist/menus-BacxVCCo.mjs +312 -0
  421. package/dist/menus-CrzHokKj.mjs +3502 -0
  422. package/dist/normalize-C49G_o1k.mjs +126 -0
  423. package/dist/oauth-authorization-C1qiw4hd.mjs +283 -0
  424. package/dist/oauth-clients-CvWatf5p.mjs +298 -0
  425. package/dist/oauth-state-store-hSdzxsEe.mjs +48 -0
  426. package/dist/oauth-user-lookup-B4OcmsLV.mjs +25 -0
  427. package/dist/options-z8VVg1Ll.mjs +114 -0
  428. package/dist/page/index.d.mts +2 -2
  429. package/dist/parse-BeQXIt1U.mjs +88 -0
  430. package/dist/passkey-config-Daqs5fjq.mjs +42 -0
  431. package/dist/{patterns-CrCYkMBb.mjs → patterns-K0DLqWir.mjs} +53 -1
  432. package/dist/{placeholder-Cp8g5Emj.mjs → placeholder-C2P5fKa4.mjs} +1 -126
  433. package/dist/plugins/adapt-sandbox-entry.d.mts +9 -5
  434. package/dist/plugins/adapt-sandbox-entry.mjs +4 -4
  435. package/dist/preview-C_4DyVox.mjs +788 -0
  436. package/dist/public-url-BB_umF5G.mjs +71 -0
  437. package/dist/{query-kDmwCsHh.mjs → query-RiobVwB5.mjs} +93 -19
  438. package/dist/rate-limit-CbJoj_fT.mjs +112 -0
  439. package/dist/{redirect-DnEWAkVg.mjs → redirect-CGl64yOX.mjs} +9 -5
  440. package/dist/redirect-ClSmMOtC.mjs +16 -0
  441. package/dist/redirects-B69T59hK.mjs +499 -0
  442. package/dist/redirects-CqaxraTO.mjs +1070 -0
  443. package/dist/{registry-C0zjeB9P.mjs → registry-C-_hxLqa.mjs} +26 -294
  444. package/dist/request-meta-Bd0mQfiS.mjs +130 -0
  445. package/dist/review-requests-C2DIHwlJ.mjs +148 -0
  446. package/dist/review-requests-DIyjw-K_.mjs +79 -0
  447. package/dist/{runner-CFI6B6J2.d.mts → runner-9eIQXuc2.d.mts} +1 -1
  448. package/dist/{index-yvc6E_17.d.mts → runtime-C4-7y7xK.d.mts} +1539 -2007
  449. package/dist/runtime.d.mts +10 -6
  450. package/dist/runtime.mjs +3 -3
  451. package/dist/schema-BNpI53of.mjs +40 -0
  452. package/dist/search-DM6CVti3.mjs +337 -0
  453. package/dist/secrets-dI8zzTV7.mjs +160 -0
  454. package/dist/sections-DZFyAQXd.mjs +338 -0
  455. package/dist/seed/index.d.mts +2 -2
  456. package/dist/seed/index.mjs +18 -13
  457. package/dist/seo/index.d.mts +1 -1
  458. package/dist/seo-BBgTCOYU.mjs +85 -0
  459. package/dist/seo-CUQctrog.mjs +129 -0
  460. package/dist/service-CSfcQguB.mjs +194 -0
  461. package/dist/settings-4XnpVMOS.mjs +223 -0
  462. package/dist/settings-Bw93cLfe.mjs +50 -0
  463. package/dist/setup-complete-DidsDQ1e.mjs +21 -0
  464. package/dist/setup-nonce-pml1PMKo.mjs +17 -0
  465. package/dist/sidecar-client-vzwV98K4.mjs +66 -0
  466. package/dist/site-activity-B8FjLIVh.mjs +104 -0
  467. package/dist/site-context-Bpu_Paur.mjs +4122 -0
  468. package/dist/site-url-CYIcO0Tj.mjs +12 -0
  469. package/dist/slugify-PDTDtMXp.mjs +30 -0
  470. package/dist/ssrf-CmM76lLV.mjs +248 -0
  471. package/dist/storage/local.d.mts +1 -1
  472. package/dist/storage/local.mjs +1 -1
  473. package/dist/storage/s3.d.mts +1 -1
  474. package/dist/storage/s3.mjs +2 -2
  475. package/dist/{taxonomies-1s5PaS_8.mjs → taxonomies-BvBgfzn3.mjs} +11 -7
  476. package/dist/taxonomies-CpqGcIJD.mjs +355 -0
  477. package/dist/taxonomy-D5cbhc8u.mjs +165 -0
  478. package/dist/{tokens-CJz9ubV6.mjs → tokens-DLTo4dO2.mjs} +1 -1
  479. package/dist/{transport-DB5eDN4x.mjs → transport-C9e_h-BF.mjs} +5 -4
  480. package/dist/trusted-proxy-Bi0Cuk5n.mjs +30 -0
  481. package/dist/{types-BawVha09.mjs → types-Bs6lTBBW.mjs} +1 -1
  482. package/dist/types-C982qI5I.d.mts +344 -0
  483. package/dist/types-D4XVOt01.d.mts +165 -0
  484. package/dist/{types-Cj0KMIZV.d.mts → types-DgfUZqcd.d.mts} +54 -16
  485. package/dist/{types-BuMDPy5C.d.mts → types-IPACEM14.d.mts} +6 -0
  486. package/dist/user-CcXq-zoL.mjs +154 -0
  487. package/dist/utils-D2in-zwy.mjs +285 -0
  488. package/dist/{validate-BZ5wnLLp.mjs → validate-BJgA6TW_.mjs} +1 -1
  489. package/dist/{validate-IPf8n4Fj.d.mts → validate-JCZihRIa.d.mts} +3 -3
  490. package/dist/version-DH53KCQd.mjs +6 -0
  491. package/dist/widgets-B7Q_7bxN.mjs +104 -0
  492. package/dist/wordpress-slugs-BevajWrC.mjs +14 -0
  493. package/dist/zod-generator-DBVP8D0P.mjs +132 -0
  494. package/locals.d.ts +1 -6
  495. package/package.json +67 -11
  496. package/src/components/DinewayHead.astro +8 -4
  497. package/src/components/DinewayImage.astro +7 -5
  498. package/src/components/DinewayMedia.astro +9 -3
  499. package/src/components/Gallery.astro +5 -3
  500. package/src/components/Image.astro +5 -1
  501. package/src/components/InlinePortableTextEditor.tsx +68 -19
  502. package/dist/error-BmL6QipT.mjs +0 -30
  503. package/dist/search-DxopAWxs.mjs +0 -11200
  504. package/dist/version-BPz1imu2.mjs +0 -6
  505. package/src/astro/routes/PluginRegistry.tsx +0 -21
  506. package/src/astro/routes/api/admin/allowed-domains/[domain].ts +0 -112
  507. package/src/astro/routes/api/admin/allowed-domains/index.ts +0 -108
  508. package/src/astro/routes/api/admin/api-tokens/[id].ts +0 -44
  509. package/src/astro/routes/api/admin/api-tokens/index.ts +0 -90
  510. package/src/astro/routes/api/admin/briefing.ts +0 -76
  511. package/src/astro/routes/api/admin/bylines/[id]/index.ts +0 -90
  512. package/src/astro/routes/api/admin/bylines/index.ts +0 -74
  513. package/src/astro/routes/api/admin/comments/[id]/status.ts +0 -120
  514. package/src/astro/routes/api/admin/comments/[id].ts +0 -64
  515. package/src/astro/routes/api/admin/comments/bulk.ts +0 -42
  516. package/src/astro/routes/api/admin/comments/counts.ts +0 -30
  517. package/src/astro/routes/api/admin/comments/index.ts +0 -46
  518. package/src/astro/routes/api/admin/context/[id]/history.ts +0 -35
  519. package/src/astro/routes/api/admin/context/[id]/index.ts +0 -35
  520. package/src/astro/routes/api/admin/context/[id]/review.ts +0 -57
  521. package/src/astro/routes/api/admin/context/[id]/supersede.ts +0 -58
  522. package/src/astro/routes/api/admin/context/diff.ts +0 -35
  523. package/src/astro/routes/api/admin/context/index.ts +0 -69
  524. package/src/astro/routes/api/admin/context/stale.ts +0 -35
  525. package/src/astro/routes/api/admin/hitl-requests/[id]/index.ts +0 -38
  526. package/src/astro/routes/api/admin/hitl-requests/[id]/resolve.ts +0 -54
  527. package/src/astro/routes/api/admin/hitl-requests/index.ts +0 -38
  528. package/src/astro/routes/api/admin/hooks/exclusive/[hookName].ts +0 -132
  529. package/src/astro/routes/api/admin/hooks/exclusive/index.ts +0 -51
  530. package/src/astro/routes/api/admin/oauth-clients/[id].ts +0 -137
  531. package/src/astro/routes/api/admin/oauth-clients/index.ts +0 -95
  532. package/src/astro/routes/api/admin/plugins/[id]/disable.ts +0 -91
  533. package/src/astro/routes/api/admin/plugins/[id]/enable.ts +0 -91
  534. package/src/astro/routes/api/admin/plugins/[id]/index.ts +0 -38
  535. package/src/astro/routes/api/admin/plugins/[id]/uninstall.ts +0 -98
  536. package/src/astro/routes/api/admin/plugins/[id]/update.ts +0 -154
  537. package/src/astro/routes/api/admin/plugins/index.ts +0 -32
  538. package/src/astro/routes/api/admin/plugins/marketplace/[id]/icon.ts +0 -62
  539. package/src/astro/routes/api/admin/plugins/marketplace/[id]/index.ts +0 -33
  540. package/src/astro/routes/api/admin/plugins/marketplace/[id]/install.ts +0 -135
  541. package/src/astro/routes/api/admin/plugins/marketplace/index.ts +0 -38
  542. package/src/astro/routes/api/admin/plugins/updates.ts +0 -28
  543. package/src/astro/routes/api/admin/review-requests/[id]/index.ts +0 -35
  544. package/src/astro/routes/api/admin/review-requests/[id]/resolve.ts +0 -52
  545. package/src/astro/routes/api/admin/review-requests/index.ts +0 -35
  546. package/src/astro/routes/api/admin/themes/marketplace/[id]/index.ts +0 -33
  547. package/src/astro/routes/api/admin/themes/marketplace/[id]/thumbnail.ts +0 -62
  548. package/src/astro/routes/api/admin/themes/marketplace/index.ts +0 -45
  549. package/src/astro/routes/api/admin/users/[id]/disable.ts +0 -72
  550. package/src/astro/routes/api/admin/users/[id]/enable.ts +0 -48
  551. package/src/astro/routes/api/admin/users/[id]/index.ts +0 -166
  552. package/src/astro/routes/api/admin/users/[id]/send-recovery.ts +0 -72
  553. package/src/astro/routes/api/admin/users/index.ts +0 -66
  554. package/src/astro/routes/api/auth/dev-bypass.ts +0 -139
  555. package/src/astro/routes/api/auth/invite/accept.ts +0 -52
  556. package/src/astro/routes/api/auth/invite/complete.ts +0 -86
  557. package/src/astro/routes/api/auth/invite/index.ts +0 -99
  558. package/src/astro/routes/api/auth/invite/register-options.ts +0 -73
  559. package/src/astro/routes/api/auth/logout.ts +0 -40
  560. package/src/astro/routes/api/auth/magic-link/send.ts +0 -90
  561. package/src/astro/routes/api/auth/magic-link/verify.ts +0 -71
  562. package/src/astro/routes/api/auth/me.ts +0 -60
  563. package/src/astro/routes/api/auth/oauth/[provider]/callback.ts +0 -221
  564. package/src/astro/routes/api/auth/oauth/[provider].ts +0 -120
  565. package/src/astro/routes/api/auth/passkey/[id].ts +0 -124
  566. package/src/astro/routes/api/auth/passkey/index.ts +0 -54
  567. package/src/astro/routes/api/auth/passkey/options.ts +0 -85
  568. package/src/astro/routes/api/auth/passkey/register/options.ts +0 -88
  569. package/src/astro/routes/api/auth/passkey/register/verify.ts +0 -119
  570. package/src/astro/routes/api/auth/passkey/verify.ts +0 -72
  571. package/src/astro/routes/api/auth/signup/complete.ts +0 -87
  572. package/src/astro/routes/api/auth/signup/request.ts +0 -89
  573. package/src/astro/routes/api/auth/signup/verify.ts +0 -53
  574. package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +0 -310
  575. package/src/astro/routes/api/content/[collection]/[id]/compare.ts +0 -28
  576. package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +0 -68
  577. package/src/astro/routes/api/content/[collection]/[id]/duplicate.ts +0 -77
  578. package/src/astro/routes/api/content/[collection]/[id]/permanent.ts +0 -42
  579. package/src/astro/routes/api/content/[collection]/[id]/preview-url.ts +0 -107
  580. package/src/astro/routes/api/content/[collection]/[id]/publish.ts +0 -100
  581. package/src/astro/routes/api/content/[collection]/[id]/restore.ts +0 -64
  582. package/src/astro/routes/api/content/[collection]/[id]/revisions.ts +0 -31
  583. package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +0 -129
  584. package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +0 -143
  585. package/src/astro/routes/api/content/[collection]/[id]/translations.ts +0 -50
  586. package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +0 -69
  587. package/src/astro/routes/api/content/[collection]/[id].ts +0 -173
  588. package/src/astro/routes/api/content/[collection]/index.ts +0 -103
  589. package/src/astro/routes/api/content/[collection]/trash.ts +0 -33
  590. package/src/astro/routes/api/dashboard.ts +0 -32
  591. package/src/astro/routes/api/dev/emails.ts +0 -36
  592. package/src/astro/routes/api/health.ts +0 -54
  593. package/src/astro/routes/api/import/probe.ts +0 -47
  594. package/src/astro/routes/api/import/wordpress/analyze.ts +0 -523
  595. package/src/astro/routes/api/import/wordpress/execute.ts +0 -330
  596. package/src/astro/routes/api/import/wordpress/media.ts +0 -338
  597. package/src/astro/routes/api/import/wordpress/prepare.ts +0 -212
  598. package/src/astro/routes/api/import/wordpress/rewrite-urls.ts +0 -425
  599. package/src/astro/routes/api/import/wordpress-plugin/analyze.ts +0 -111
  600. package/src/astro/routes/api/import/wordpress-plugin/callback.ts +0 -58
  601. package/src/astro/routes/api/import/wordpress-plugin/execute.ts +0 -399
  602. package/src/astro/routes/api/manifest.ts +0 -75
  603. package/src/astro/routes/api/mcp.ts +0 -125
  604. package/src/astro/routes/api/media/[id]/confirm.ts +0 -93
  605. package/src/astro/routes/api/media/[id].ts +0 -145
  606. package/src/astro/routes/api/media/file/[...key].ts +0 -79
  607. package/src/astro/routes/api/media/providers/[providerId]/[itemId].ts +0 -91
  608. package/src/astro/routes/api/media/providers/[providerId]/index.ts +0 -111
  609. package/src/astro/routes/api/media/providers/index.ts +0 -30
  610. package/src/astro/routes/api/media/upload-url.ts +0 -146
  611. package/src/astro/routes/api/media.ts +0 -204
  612. package/src/astro/routes/api/menus/[name]/reorder.ts +0 -79
  613. package/src/astro/routes/api/menus/[name].ts +0 -145
  614. package/src/astro/routes/api/menus/index.ts +0 -91
  615. package/src/astro/routes/api/oauth/authorize.ts +0 -430
  616. package/src/astro/routes/api/oauth/device/authorize.ts +0 -45
  617. package/src/astro/routes/api/oauth/device/code.ts +0 -56
  618. package/src/astro/routes/api/oauth/device/token.ts +0 -70
  619. package/src/astro/routes/api/oauth/register.ts +0 -182
  620. package/src/astro/routes/api/oauth/token/refresh.ts +0 -38
  621. package/src/astro/routes/api/oauth/token/revoke.ts +0 -38
  622. package/src/astro/routes/api/oauth/token.ts +0 -195
  623. package/src/astro/routes/api/openapi.json.ts +0 -33
  624. package/src/astro/routes/api/plugins/[pluginId]/[...path].ts +0 -109
  625. package/src/astro/routes/api/redirects/404s/index.ts +0 -72
  626. package/src/astro/routes/api/redirects/404s/summary.ts +0 -33
  627. package/src/astro/routes/api/redirects/[id].ts +0 -183
  628. package/src/astro/routes/api/redirects/index.ts +0 -100
  629. package/src/astro/routes/api/revisions/[revisionId]/index.ts +0 -29
  630. package/src/astro/routes/api/revisions/[revisionId]/restore.ts +0 -62
  631. package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +0 -104
  632. package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +0 -67
  633. package/src/astro/routes/api/schema/collections/[slug]/fields/reorder.ts +0 -45
  634. package/src/astro/routes/api/schema/collections/[slug]/index.ts +0 -107
  635. package/src/astro/routes/api/schema/collections/index.ts +0 -61
  636. package/src/astro/routes/api/schema/index.ts +0 -109
  637. package/src/astro/routes/api/schema/orphans/[slug].ts +0 -36
  638. package/src/astro/routes/api/schema/orphans/index.ts +0 -26
  639. package/src/astro/routes/api/search/enable.ts +0 -64
  640. package/src/astro/routes/api/search/index.ts +0 -52
  641. package/src/astro/routes/api/search/rebuild.ts +0 -72
  642. package/src/astro/routes/api/search/stats.ts +0 -35
  643. package/src/astro/routes/api/search/suggest.ts +0 -50
  644. package/src/astro/routes/api/sections/[slug].ts +0 -203
  645. package/src/astro/routes/api/sections/index.ts +0 -107
  646. package/src/astro/routes/api/settings/email.ts +0 -150
  647. package/src/astro/routes/api/settings.ts +0 -116
  648. package/src/astro/routes/api/setup/admin-verify.ts +0 -122
  649. package/src/astro/routes/api/setup/admin.ts +0 -104
  650. package/src/astro/routes/api/setup/dev-bypass.ts +0 -200
  651. package/src/astro/routes/api/setup/dev-reset.ts +0 -40
  652. package/src/astro/routes/api/setup/index.ts +0 -128
  653. package/src/astro/routes/api/setup/status.ts +0 -122
  654. package/src/astro/routes/api/snapshot.ts +0 -76
  655. package/src/astro/routes/api/taxonomies/[name]/terms/[slug].ts +0 -232
  656. package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +0 -131
  657. package/src/astro/routes/api/taxonomies/index.ts +0 -114
  658. package/src/astro/routes/api/themes/preview.ts +0 -78
  659. package/src/astro/routes/api/typegen.ts +0 -114
  660. package/src/astro/routes/api/well-known/auth.ts +0 -71
  661. package/src/astro/routes/api/well-known/oauth-authorization-server.ts +0 -48
  662. package/src/astro/routes/api/well-known/oauth-protected-resource.ts +0 -39
  663. package/src/astro/routes/api/widget-areas/[name]/reorder.ts +0 -114
  664. package/src/astro/routes/api/widget-areas/[name]/widgets/[id].ts +0 -213
  665. package/src/astro/routes/api/widget-areas/[name]/widgets.ts +0 -126
  666. package/src/astro/routes/api/widget-areas/[name].ts +0 -135
  667. package/src/astro/routes/api/widget-areas/index.ts +0 -149
  668. package/src/astro/routes/api/widget-components.ts +0 -22
  669. package/src/astro/routes/robots.txt.ts +0 -81
  670. package/src/astro/routes/sitemap-[collection].xml.ts +0 -104
  671. package/src/astro/routes/sitemap.xml.ts +0 -92
  672. /package/dist/{adapters-C2ypTrZZ.d.mts → adapters-BLDldpJg.d.mts} +0 -0
  673. /package/{src → dist}/astro/routes/admin.astro +0 -0
  674. /package/dist/{base64-F8-DUraK.mjs → base64-Cz-aU0X1.mjs} +0 -0
  675. /package/dist/{chunks--4F8ddV4.mjs → chunks-D_jVet6z.mjs} +0 -0
  676. /package/dist/{config-BXwuX8Bx.mjs → config-CAMFxGaV.mjs} +0 -0
  677. /package/dist/{db-errors-CEqD7qH9.mjs → db-errors-DKUg_NgF.mjs} +0 -0
  678. /package/dist/{default-VjJyuuG9.mjs → default-C3PZN-bz.mjs} +0 -0
  679. /package/dist/{load-Coc9HpHH.mjs → load-D-9NhLmF.mjs} +0 -0
  680. /package/dist/{mode-47goXBBK.mjs → mode-C80mAZQv.mjs} +0 -0
  681. /package/dist/{placeholder--wOi4TbO.d.mts → placeholder-CHkLckzK.d.mts} +0 -0
  682. /package/dist/{request-cache-Dk5qPSOx.mjs → request-cache-DHMRr2Lf.mjs} +0 -0
  683. /package/dist/{transaction-Cn2rjY78.mjs → transaction-x2tJQ-A1.mjs} +0 -0
  684. /package/dist/{transport-Wge_IzKl.d.mts → transport-6RefuBdV.d.mts} +0 -0
  685. /package/dist/{types-griIBQOQ.mjs → types-B9gKVOHk.mjs} +0 -0
  686. /package/dist/{types-CWbdtiux.d.mts → types-B9qVtiHb.d.mts} +0 -0
  687. /package/dist/{types-COeOq9nK.mjs → types-DL7Y8D_t.mjs} +0 -0
  688. /package/dist/{types-BzcUjoqg.d.mts → types-Djdp0cZO.d.mts} +0 -0
  689. /package/dist/{types-DOrVigru.d.mts → types-Du8jreyC.d.mts} +0 -0
@@ -0,0 +1,4122 @@
1
+ import { t as validateIdentifier } from "./validate-VPnKoIzW.mjs";
2
+ import { t as ContentRepository } from "./content-CyLkb-qH.mjs";
3
+ import { n as decodeCursor, r as encodeCursor } from "./types-Bs6lTBBW.mjs";
4
+ import { t as SiteActivityRepository } from "./site-activity-B8FjLIVh.mjs";
5
+ import { t as ReviewRequestRepository } from "./review-requests-C2DIHwlJ.mjs";
6
+ import { n as normalizeEntityAlias, t as EntityAliasRepository } from "./entity-aliases-C0v-yNET.mjs";
7
+ import { r as isPattern } from "./patterns-K0DLqWir.mjs";
8
+ import { a as ContextRepository, i as parseSiteBriefingScope, l as handlePluginList } from "./briefing-BrXCuMEE.mjs";
9
+ import { t as FTSManager } from "./fts-manager-B1pTNEG_.mjs";
10
+ import { n as SchemaRegistry } from "./registry-C-_hxLqa.mjs";
11
+ import { a as getSiteSettingsWithDb } from "./settings-4XnpVMOS.mjs";
12
+ import { p as normalizeUrl } from "./utils-D2in-zwy.mjs";
13
+ import { t as sanitizeWordPressImportSlug } from "./wordpress-slugs-BevajWrC.mjs";
14
+ import { s as searchCollection } from "./search-DM6CVti3.mjs";
15
+ import { n as assertExperimentalSiteContextWorkflowsEnabled } from "./experimental-workflows-DldxJlqV.mjs";
16
+ import { sql } from "kysely";
17
+ import { ulid } from "ulidx";
18
+ import { Role } from "@dineway-ai/auth";
19
+
20
+ //#region src/database/repositories/assignments.ts
21
+ const ASSIGNMENT_ACTOR_TYPES = [
22
+ "user",
23
+ "api_token",
24
+ "system"
25
+ ];
26
+ const ASSIGNMENT_STATUSES = [
27
+ "pending",
28
+ "accepted",
29
+ "in_progress",
30
+ "blocked",
31
+ "completed",
32
+ "declined",
33
+ "cancelled"
34
+ ];
35
+ const ASSIGNMENT_PRIORITIES = [
36
+ "low",
37
+ "normal",
38
+ "high",
39
+ "urgent"
40
+ ];
41
+ var AssignmentRepository = class {
42
+ constructor(db) {
43
+ this.db = db;
44
+ }
45
+ async create(input) {
46
+ const id = ulid();
47
+ const now = input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
48
+ await this.db.insertInto("_dineway_assignments").values(toInsertableAssignment(id, input, now)).execute();
49
+ const assignment = await this.findById(id);
50
+ if (!assignment) throw new Error("Failed to create assignment");
51
+ return assignment;
52
+ }
53
+ async findById(id) {
54
+ const row = await this.db.selectFrom("_dineway_assignments").selectAll().where("id", "=", id).executeTakeFirst();
55
+ return row ? rowToAssignment(row) : null;
56
+ }
57
+ async list(query = {}) {
58
+ const limit = clampLimit$3(query.limit);
59
+ const rows = await this.queryRows(query).execute();
60
+ const items = rows.slice(0, limit).map(rowToAssignment);
61
+ const result = { items };
62
+ if (rows.length > limit && items.length > 0) {
63
+ const last = items.at(-1);
64
+ result.nextCursor = encodeCursor(last.createdAt, last.id);
65
+ }
66
+ return result;
67
+ }
68
+ async accept(id, input = {}) {
69
+ const value = input.acceptedAt ?? (/* @__PURE__ */ new Date()).toISOString();
70
+ return this.transition(id, ["pending"], {
71
+ status: "accepted",
72
+ assigned_to_actor_type: input.assignedToActorType ?? null,
73
+ assigned_to_actor_id: input.assignedToActorId ?? null,
74
+ accepted_at: value,
75
+ updated_at: value,
76
+ metadata: jsonString$1(input.metadata)
77
+ });
78
+ }
79
+ async start(id, input = {}) {
80
+ const value = input.at ?? (/* @__PURE__ */ new Date()).toISOString();
81
+ return this.transition(id, ["accepted", "blocked"], {
82
+ status: "in_progress",
83
+ started_at: value,
84
+ updated_at: value,
85
+ metadata: jsonString$1(input.metadata)
86
+ });
87
+ }
88
+ async block(id, input = {}) {
89
+ const value = input.at ?? (/* @__PURE__ */ new Date()).toISOString();
90
+ return this.transition(id, ["accepted", "in_progress"], {
91
+ status: "blocked",
92
+ blocked_at: value,
93
+ updated_at: value,
94
+ metadata: jsonString$1(input.metadata)
95
+ });
96
+ }
97
+ async complete(id, input = {}) {
98
+ const value = input.at ?? (/* @__PURE__ */ new Date()).toISOString();
99
+ return this.transition(id, [
100
+ "pending",
101
+ "accepted",
102
+ "in_progress"
103
+ ], {
104
+ status: "completed",
105
+ completed_at: value,
106
+ updated_at: value,
107
+ metadata: jsonString$1(input.metadata)
108
+ });
109
+ }
110
+ async decline(id, input = {}) {
111
+ const value = input.at ?? (/* @__PURE__ */ new Date()).toISOString();
112
+ return this.transition(id, ["pending", "accepted"], {
113
+ status: "declined",
114
+ declined_at: value,
115
+ updated_at: value,
116
+ metadata: jsonString$1(input.metadata)
117
+ });
118
+ }
119
+ async cancel(id, input = {}) {
120
+ const value = input.at ?? (/* @__PURE__ */ new Date()).toISOString();
121
+ return this.transition(id, [
122
+ "pending",
123
+ "accepted",
124
+ "in_progress",
125
+ "blocked"
126
+ ], {
127
+ status: "cancelled",
128
+ cancelled_at: value,
129
+ updated_at: value,
130
+ metadata: jsonString$1(input.metadata)
131
+ });
132
+ }
133
+ async linkHitlRequest(id, relatedHitlRequestId, at = (/* @__PURE__ */ new Date()).toISOString()) {
134
+ const result = await this.db.updateTable("_dineway_assignments").set({
135
+ related_hitl_request_id: relatedHitlRequestId,
136
+ updated_at: at
137
+ }).where("id", "=", id).executeTakeFirst();
138
+ if (Number(result.numUpdatedRows ?? 0) === 0) return null;
139
+ return this.findById(id);
140
+ }
141
+ queryRows(query) {
142
+ const limit = clampLimit$3(query.limit);
143
+ let q = this.db.selectFrom("_dineway_assignments").selectAll().orderBy("created_at", "desc").orderBy("id", "desc").limit(limit + 1);
144
+ if (query.scope) q = q.where("scope", "=", query.scope);
145
+ if (query.scopes && query.scopes.length > 0) q = q.where("scope", "in", query.scopes);
146
+ if (query.statuses && query.statuses.length > 0) q = q.where("status", "in", query.statuses);
147
+ if (query.priority) q = q.where("priority", "=", query.priority);
148
+ if (query.assignmentType) q = q.where("assignment_type", "=", query.assignmentType);
149
+ if (query.assignedToActorType && query.assignedToActorId) q = q.where("assigned_to_actor_type", "=", query.assignedToActorType).where("assigned_to_actor_id", "=", query.assignedToActorId);
150
+ if (query.assignedByActorType && query.assignedByActorId) q = q.where("assigned_by_actor_type", "=", query.assignedByActorType).where("assigned_by_actor_id", "=", query.assignedByActorId);
151
+ if (query.participantActor) q = q.where((eb) => eb.or([eb.and([eb("assigned_by_actor_type", "=", query.participantActor.actorType), eb("assigned_by_actor_id", "=", query.participantActor.actorId)]), eb.and([eb("assigned_to_actor_type", "=", query.participantActor.actorType), eb("assigned_to_actor_id", "=", query.participantActor.actorId)])]));
152
+ if (query.since) q = q.where("updated_at", ">=", query.since);
153
+ if (query.cursor) {
154
+ const decoded = decodeCursor(query.cursor);
155
+ if (decoded) q = q.where((eb) => eb.or([eb("created_at", "<", decoded.orderValue), eb.and([eb("created_at", "=", decoded.orderValue), eb("id", "<", decoded.id)])]));
156
+ }
157
+ return q;
158
+ }
159
+ async transition(id, validFrom, update) {
160
+ const result = await this.db.updateTable("_dineway_assignments").set(update).where("id", "=", id).where("status", "in", validFrom).executeTakeFirst();
161
+ if (Number(result.numUpdatedRows ?? 0) === 0) return null;
162
+ return this.findById(id);
163
+ }
164
+ };
165
+ function toInsertableAssignment(id, input, now) {
166
+ return {
167
+ id,
168
+ scope: input.scope,
169
+ assignment_type: input.assignmentType,
170
+ status: "pending",
171
+ priority: input.priority ?? "normal",
172
+ title: input.title,
173
+ summary: input.summary ?? null,
174
+ details: input.details ?? null,
175
+ assigned_by_actor_type: input.assignedByActorType,
176
+ assigned_by_actor_id: input.assignedByActorId,
177
+ assigned_to_actor_type: input.assignedToActorType ?? null,
178
+ assigned_to_actor_id: input.assignedToActorId ?? null,
179
+ metadata: jsonString$1(input.metadata),
180
+ related_handoff_snapshot_id: input.relatedHandoffSnapshotId ?? null,
181
+ related_hitl_request_id: input.relatedHitlRequestId ?? null,
182
+ due_at: input.dueAt ?? null,
183
+ created_at: now,
184
+ updated_at: now,
185
+ accepted_at: null,
186
+ started_at: null,
187
+ blocked_at: null,
188
+ completed_at: null,
189
+ declined_at: null,
190
+ cancelled_at: null
191
+ };
192
+ }
193
+ function rowToAssignment(row) {
194
+ return {
195
+ id: row.id,
196
+ scope: row.scope,
197
+ assignmentType: row.assignment_type,
198
+ status: row.status,
199
+ priority: row.priority,
200
+ title: row.title,
201
+ summary: row.summary,
202
+ details: row.details,
203
+ assignedByActorType: row.assigned_by_actor_type,
204
+ assignedByActorId: row.assigned_by_actor_id,
205
+ assignedToActorType: row.assigned_to_actor_type,
206
+ assignedToActorId: row.assigned_to_actor_id,
207
+ metadata: parseRecord$2(row.metadata),
208
+ relatedHandoffSnapshotId: row.related_handoff_snapshot_id,
209
+ relatedHitlRequestId: row.related_hitl_request_id,
210
+ dueAt: row.due_at,
211
+ createdAt: row.created_at,
212
+ updatedAt: row.updated_at,
213
+ acceptedAt: row.accepted_at,
214
+ startedAt: row.started_at,
215
+ blockedAt: row.blocked_at,
216
+ completedAt: row.completed_at,
217
+ declinedAt: row.declined_at,
218
+ cancelledAt: row.cancelled_at
219
+ };
220
+ }
221
+ function jsonString$1(value) {
222
+ return JSON.stringify(value ?? {});
223
+ }
224
+ function parseRecord$2(value) {
225
+ if (!value) return {};
226
+ try {
227
+ const parsed = JSON.parse(value);
228
+ return isRecord$5(parsed) ? parsed : {};
229
+ } catch {
230
+ return {};
231
+ }
232
+ }
233
+ function isRecord$5(value) {
234
+ return typeof value === "object" && value !== null && !Array.isArray(value);
235
+ }
236
+ function clampLimit$3(limit) {
237
+ if (!limit || limit < 1) return 50;
238
+ return Math.min(limit, 100);
239
+ }
240
+
241
+ //#endregion
242
+ //#region src/database/repositories/hitl-requests.ts
243
+ const HITL_REQUEST_STATUSES = [
244
+ "pending",
245
+ "approved",
246
+ "rejected"
247
+ ];
248
+ const HITL_REQUEST_PRIORITIES = [
249
+ "low",
250
+ "normal",
251
+ "high",
252
+ "urgent"
253
+ ];
254
+ var HitlRequestRepository = class {
255
+ constructor(db) {
256
+ this.db = db;
257
+ }
258
+ async create(input) {
259
+ const id = ulid();
260
+ const now = input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
261
+ await this.db.insertInto("_dineway_hitl_requests").values(toInsertableHitlRequest(id, input, now)).execute();
262
+ const request = await this.findById(id);
263
+ if (!request) throw new Error("Failed to create HITL request");
264
+ return request;
265
+ }
266
+ async findById(id) {
267
+ const row = await this.db.selectFrom("_dineway_hitl_requests").selectAll().where("id", "=", id).executeTakeFirst();
268
+ return row ? rowToHitlRequest(row) : null;
269
+ }
270
+ async list(query = {}) {
271
+ const limit = clampLimit$2(query.limit);
272
+ const rows = await this.queryRows(query).execute();
273
+ const items = rows.slice(0, limit).map(rowToHitlRequest);
274
+ const result = { items };
275
+ if (rows.length > limit && items.length > 0) {
276
+ const last = items.at(-1);
277
+ result.nextCursor = encodeCursor(last.createdAt, last.id);
278
+ }
279
+ return result;
280
+ }
281
+ async resolve(id, input) {
282
+ const resolvedAt = input.resolvedAt ?? (/* @__PURE__ */ new Date()).toISOString();
283
+ const result = await this.db.updateTable("_dineway_hitl_requests").set({
284
+ status: input.decision,
285
+ resolved_by_actor_type: input.resolvedByActorType,
286
+ resolved_by_actor_id: input.resolvedByActorId,
287
+ resolved_auth_metadata: jsonStringOrNull(input.resolvedAuthMetadata),
288
+ review_note: input.reviewNote ?? null,
289
+ resolved_at: resolvedAt,
290
+ updated_at: resolvedAt
291
+ }).where("id", "=", id).where("status", "=", "pending").executeTakeFirst();
292
+ if (Number(result.numUpdatedRows ?? 0) === 0) return null;
293
+ return this.findById(id);
294
+ }
295
+ queryRows(query) {
296
+ const limit = clampLimit$2(query.limit);
297
+ let q = this.db.selectFrom("_dineway_hitl_requests").selectAll().orderBy("created_at", "desc").orderBy("id", "desc").limit(limit + 1);
298
+ if (query.scope) q = q.where("scope", "=", query.scope);
299
+ if (query.scopes && query.scopes.length > 0) q = q.where("scope", "in", query.scopes);
300
+ if (query.statuses && query.statuses.length > 0) q = q.where("status", "in", query.statuses);
301
+ if (query.priority) q = q.where("priority", "=", query.priority);
302
+ if (query.actionType) q = q.where("action_type", "=", query.actionType);
303
+ if (query.targetRefType) q = q.where("target_ref_type", "=", query.targetRefType);
304
+ if (query.targetRefId) q = q.where("target_ref_id", "=", query.targetRefId);
305
+ if (query.relatedAssignmentId) q = q.where("related_assignment_id", "=", query.relatedAssignmentId);
306
+ if (query.requestedByActorType && query.requestedByActorId) q = q.where("requested_by_actor_type", "=", query.requestedByActorType).where("requested_by_actor_id", "=", query.requestedByActorId);
307
+ if (query.participantActor) q = q.where("requested_by_actor_type", "=", query.participantActor.actorType).where("requested_by_actor_id", "=", query.participantActor.actorId);
308
+ if (query.since) q = q.where("updated_at", ">=", query.since);
309
+ if (query.cursor) {
310
+ const decoded = decodeCursor(query.cursor);
311
+ if (decoded) q = q.where((eb) => eb.or([eb("created_at", "<", decoded.orderValue), eb.and([eb("created_at", "=", decoded.orderValue), eb("id", "<", decoded.id)])]));
312
+ }
313
+ return q;
314
+ }
315
+ };
316
+ function toInsertableHitlRequest(id, input, now) {
317
+ return {
318
+ id,
319
+ scope: input.scope,
320
+ action_type: input.actionType,
321
+ status: "pending",
322
+ priority: input.priority ?? "normal",
323
+ title: input.title,
324
+ summary: input.summary ?? null,
325
+ risk_reason: input.riskReason,
326
+ review_payload: JSON.stringify(input.reviewPayload),
327
+ target_ref_type: input.targetRefType,
328
+ target_ref_id: input.targetRefId,
329
+ requested_by_actor_type: input.requestedByActorType,
330
+ requested_by_actor_id: input.requestedByActorId,
331
+ requested_auth_metadata: jsonStringOrNull(input.requestedAuthMetadata),
332
+ resolved_by_actor_type: null,
333
+ resolved_by_actor_id: null,
334
+ resolved_auth_metadata: null,
335
+ review_note: null,
336
+ metadata: jsonString(input.metadata),
337
+ related_assignment_id: input.relatedAssignmentId ?? null,
338
+ related_handoff_snapshot_id: input.relatedHandoffSnapshotId ?? null,
339
+ sla_due_at: input.slaDueAt ?? null,
340
+ created_at: now,
341
+ updated_at: now,
342
+ resolved_at: null
343
+ };
344
+ }
345
+ function rowToHitlRequest(row) {
346
+ return {
347
+ id: row.id,
348
+ scope: row.scope,
349
+ actionType: row.action_type,
350
+ status: row.status,
351
+ priority: row.priority,
352
+ title: row.title,
353
+ summary: row.summary,
354
+ riskReason: row.risk_reason,
355
+ reviewPayload: parseRecord$1(row.review_payload),
356
+ targetRefType: row.target_ref_type,
357
+ targetRefId: row.target_ref_id,
358
+ requestedByActorType: row.requested_by_actor_type,
359
+ requestedByActorId: row.requested_by_actor_id,
360
+ requestedAuthMetadata: parseNullableRecord(row.requested_auth_metadata),
361
+ resolvedByActorType: row.resolved_by_actor_type,
362
+ resolvedByActorId: row.resolved_by_actor_id,
363
+ resolvedAuthMetadata: parseNullableRecord(row.resolved_auth_metadata),
364
+ reviewNote: row.review_note,
365
+ metadata: parseRecord$1(row.metadata),
366
+ relatedAssignmentId: row.related_assignment_id,
367
+ relatedHandoffSnapshotId: row.related_handoff_snapshot_id,
368
+ slaDueAt: row.sla_due_at,
369
+ createdAt: row.created_at,
370
+ updatedAt: row.updated_at,
371
+ resolvedAt: row.resolved_at
372
+ };
373
+ }
374
+ function jsonString(value) {
375
+ return JSON.stringify(value ?? {});
376
+ }
377
+ function jsonStringOrNull(value) {
378
+ return value ? JSON.stringify(value) : null;
379
+ }
380
+ function parseRecord$1(value) {
381
+ if (!value) return {};
382
+ try {
383
+ const parsed = JSON.parse(value);
384
+ return isRecord$4(parsed) ? parsed : {};
385
+ } catch {
386
+ return {};
387
+ }
388
+ }
389
+ function parseNullableRecord(value) {
390
+ if (!value) return null;
391
+ return parseRecord$1(value);
392
+ }
393
+ function isRecord$4(value) {
394
+ return typeof value === "object" && value !== null && !Array.isArray(value);
395
+ }
396
+ function clampLimit$2(limit) {
397
+ if (!limit || limit < 1) return 50;
398
+ return Math.min(limit, 100);
399
+ }
400
+
401
+ //#endregion
402
+ //#region src/site-context/context-entry-public.ts
403
+ function toPublicContextEntry(entry) {
404
+ return {
405
+ id: entry.id,
406
+ scope: entry.scope,
407
+ contextType: entry.contextType,
408
+ title: entry.title,
409
+ body: entry.body,
410
+ policyKey: entry.policyKey,
411
+ sourceActivityId: entry.sourceActivityId,
412
+ createdByActorType: entry.createdByActorType,
413
+ createdByActorId: entry.createdByActorId,
414
+ createdAuthMetadata: entry.createdAuthMetadata,
415
+ supersedesId: entry.supersedesId,
416
+ version: entry.version,
417
+ isCurrent: entry.isCurrent,
418
+ validUntil: entry.validUntil,
419
+ reviewedAt: entry.reviewedAt,
420
+ reviewedByActorType: entry.reviewedByActorType,
421
+ reviewedByActorId: entry.reviewedByActorId,
422
+ reviewNote: entry.reviewNote,
423
+ tags: entry.tags,
424
+ createdAt: entry.createdAt,
425
+ updatedAt: entry.updatedAt
426
+ };
427
+ }
428
+ function toPublicContextEntries(entries) {
429
+ return entries.map(toPublicContextEntry);
430
+ }
431
+ function toPublicContextEntryPage(page) {
432
+ return {
433
+ items: toPublicContextEntries(page.items),
434
+ nextCursor: page.nextCursor
435
+ };
436
+ }
437
+ function toPublicContextDiff(diff) {
438
+ return {
439
+ newEntries: toPublicContextEntries(diff.newEntries),
440
+ supersededEntries: toPublicContextEntries(diff.supersededEntries),
441
+ staleEntries: toPublicContextEntries(diff.staleEntries),
442
+ reviewedEntries: toPublicContextEntries(diff.reviewedEntries)
443
+ };
444
+ }
445
+
446
+ //#endregion
447
+ //#region src/site-context/action-hash.ts
448
+ async function buildStableActionHash(value) {
449
+ return sha256Hex(stableStringify(value));
450
+ }
451
+ function stableStringify(value) {
452
+ if (Array.isArray(value)) return `[${value.map((item) => stableStringify(item)).join(",")}]`;
453
+ if (isRecord$3(value)) return `{${Object.entries(value).filter(([, entryValue]) => entryValue !== void 0).toSorted(([left], [right]) => left.localeCompare(right)).map(([key, entryValue]) => `${JSON.stringify(key)}:${stableStringify(entryValue)}`).join(",")}}`;
454
+ return JSON.stringify(value ?? null);
455
+ }
456
+ function isRecord$3(value) {
457
+ return typeof value === "object" && value !== null && !Array.isArray(value);
458
+ }
459
+ async function sha256Hex(value) {
460
+ const buffer = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
461
+ return Array.from(new Uint8Array(buffer), (byte) => byte.toString(16).padStart(2, "0")).join("");
462
+ }
463
+
464
+ //#endregion
465
+ //#region src/site-context/review-payload.ts
466
+ var ReviewPayloadBuilder = class {
467
+ constructor(handlers) {
468
+ this.handlers = handlers;
469
+ }
470
+ async buildContentReviewPayload(input) {
471
+ const actionType = input.actionType ?? "content.publish";
472
+ const content = await this.loadContent(input.collection, input.id);
473
+ const compare = await this.loadCompare(input.collection, content.entryId);
474
+ const live = asRecord(compare.live);
475
+ const draft = asRecord(compare.draft) ?? content.data;
476
+ const hasChanges = typeof compare.hasChanges === "boolean" ? compare.hasChanges : stableStringify(live) !== stableStringify(draft);
477
+ const actionHash = await buildStableActionHash({
478
+ actionType,
479
+ collection: input.collection,
480
+ entryId: content.entryId,
481
+ liveRevisionId: content.liveRevisionId,
482
+ draftRevisionId: content.draftRevisionId,
483
+ reviewedRev: content.reviewedRev,
484
+ live,
485
+ draft
486
+ });
487
+ const scope = `content:${input.collection}:${content.entryId}`;
488
+ const summary = input.summary ?? `Review ${actionType} for ${input.collection}/${content.displayTitle ?? content.entryId}`;
489
+ return {
490
+ collection: input.collection,
491
+ entryId: content.entryId,
492
+ scope,
493
+ liveRevisionId: content.liveRevisionId,
494
+ draftRevisionId: content.draftRevisionId,
495
+ reviewedRev: content.reviewedRev,
496
+ actionType,
497
+ actionHash,
498
+ reviewPayload: {
499
+ kind: "content_review",
500
+ actionType,
501
+ summary,
502
+ target: {
503
+ collection: input.collection,
504
+ entryId: content.entryId,
505
+ scope,
506
+ liveRevisionId: content.liveRevisionId,
507
+ draftRevisionId: content.draftRevisionId,
508
+ reviewedRev: content.reviewedRev,
509
+ actionHash
510
+ },
511
+ content: {
512
+ id: content.entryId,
513
+ slug: content.slug,
514
+ status: content.status,
515
+ title: content.displayTitle,
516
+ updatedAt: content.updatedAt
517
+ },
518
+ diff: {
519
+ hasChanges,
520
+ live,
521
+ draft
522
+ }
523
+ }
524
+ };
525
+ }
526
+ async loadContent(collection, id) {
527
+ const result = await this.handlers.handleContentGet(collection, id);
528
+ if (!result.success) throw new Error(result.error?.message ?? `Content item not found: ${collection}/${id}`);
529
+ const payload = asRecord(result.data);
530
+ const item = asRecord(payload?.item);
531
+ if (!payload || !item) throw new Error("Content get response did not include an item");
532
+ const entryId = stringOrNull(item.id);
533
+ const reviewedRev = stringOrNull(payload._rev);
534
+ if (!entryId) throw new Error("Content item is missing id");
535
+ if (!reviewedRev) throw new Error("Content item is missing _rev for review binding");
536
+ const data = asRecord(item.data) ?? {};
537
+ const title = stringOrNull(data.title) ?? stringOrNull(item.title) ?? stringOrNull(item.slug);
538
+ return {
539
+ entryId,
540
+ reviewedRev,
541
+ liveRevisionId: stringOrNull(item.liveRevisionId),
542
+ draftRevisionId: stringOrNull(item.draftRevisionId),
543
+ slug: stringOrNull(item.slug),
544
+ status: stringOrNull(item.status),
545
+ updatedAt: stringOrNull(item.updatedAt),
546
+ displayTitle: title,
547
+ data
548
+ };
549
+ }
550
+ async loadCompare(collection, id) {
551
+ const result = await this.handlers.handleContentCompare(collection, id);
552
+ if (!result.success) throw new Error(result.error?.message ?? `Failed to compare content: ${collection}/${id}`);
553
+ return asRecord(result.data) ?? {};
554
+ }
555
+ };
556
+ function asRecord(value) {
557
+ return isRecord$2(value) ? value : null;
558
+ }
559
+ function isRecord$2(value) {
560
+ return typeof value === "object" && value !== null && !Array.isArray(value);
561
+ }
562
+ function stringOrNull(value) {
563
+ return typeof value === "string" && value.length > 0 ? value : null;
564
+ }
565
+
566
+ //#endregion
567
+ //#region src/site-context/risk-policy.ts
568
+ var RiskPolicyEvaluator = class {
569
+ repository;
570
+ hitlRepository;
571
+ payloadBuilder;
572
+ constructor(options) {
573
+ this.repository = new ReviewRequestRepository(options.db);
574
+ this.hitlRepository = new HitlRequestRepository(options.db);
575
+ this.payloadBuilder = new ReviewPayloadBuilder(options.handlers);
576
+ }
577
+ requiresContentPublishReview(actor) {
578
+ return isTokenAuthenticatedActor(actor);
579
+ }
580
+ requiresWorkflowHitl(actor) {
581
+ return isTokenAuthenticatedActor(actor);
582
+ }
583
+ async evaluateContentPublishReview(input) {
584
+ if (!this.requiresContentPublishReview(input.actor)) return {
585
+ allowed: true,
586
+ required: false
587
+ };
588
+ if (!input.reviewRequestId) return {
589
+ allowed: false,
590
+ required: true,
591
+ reason: "missing_review_request",
592
+ message: "content.publish requires an approved review_request_id for token-authenticated actors. Submit review_request_submit, resolve it as approved, then retry publish with that id."
593
+ };
594
+ const built = await this.payloadBuilder.buildContentReviewPayload({
595
+ collection: input.collection,
596
+ id: input.id,
597
+ actionType: "content.publish"
598
+ });
599
+ const target = {
600
+ collection: built.collection,
601
+ entryId: built.entryId,
602
+ liveRevisionId: built.liveRevisionId,
603
+ draftRevisionId: built.draftRevisionId,
604
+ reviewedRev: built.reviewedRev,
605
+ actionType: built.actionType,
606
+ actionHash: built.actionHash
607
+ };
608
+ const approved = await this.repository.findApprovedForTarget(target);
609
+ if (approved?.id === input.reviewRequestId) return {
610
+ allowed: true,
611
+ required: true,
612
+ reviewRequest: approved,
613
+ target
614
+ };
615
+ return {
616
+ allowed: false,
617
+ required: true,
618
+ reason: "stale_or_unapproved_review",
619
+ message: "The supplied review_request_id is not approved for the current content draft/action. Submit and approve a fresh review request before publishing.",
620
+ target
621
+ };
622
+ }
623
+ async evaluateWorkflowHitl(input) {
624
+ if (!this.requiresWorkflowHitl(input.actor)) return {
625
+ allowed: true,
626
+ required: false
627
+ };
628
+ if (!input.hitlRequestId) return {
629
+ allowed: false,
630
+ required: true,
631
+ reason: "missing_hitl_request",
632
+ message: `${input.action.actionType} requires an approved hitl_request_id for token-authenticated actors. Resolve the generated HITL request, then retry this tool with that id.`,
633
+ action: input.action
634
+ };
635
+ const request = await this.hitlRepository.findById(input.hitlRequestId);
636
+ if (request && this.matchesApprovedWorkflowHitl(request, input.action)) return {
637
+ allowed: true,
638
+ required: true,
639
+ hitlRequest: request,
640
+ action: input.action
641
+ };
642
+ return {
643
+ allowed: false,
644
+ required: true,
645
+ reason: "stale_or_unapproved_hitl",
646
+ message: "The supplied hitl_request_id is not approved for the current action target or payload. Resolve a matching HITL request, then retry this tool with that id.",
647
+ action: input.action
648
+ };
649
+ }
650
+ matchesApprovedWorkflowHitl(request, action) {
651
+ return request.status === "approved" && request.scope === action.scope && request.actionType === action.actionType && request.targetRefType === action.targetRefType && request.targetRefId === action.targetRefId && extractActionHash(request.metadata) === action.actionHash;
652
+ }
653
+ };
654
+ function extractActionHash(metadata) {
655
+ const value = metadata.actionHash;
656
+ return typeof value === "string" && value.length > 0 ? value : null;
657
+ }
658
+ function isTokenAuthenticatedActor(actor) {
659
+ if (actor.actorType === "api_token") return true;
660
+ const authMethod = actor.authMetadata.auth_method;
661
+ return authMethod === "api_token" || authMethod === "oauth_token";
662
+ }
663
+
664
+ //#endregion
665
+ //#region src/site-context/schema-hitl.ts
666
+ var SchemaHitlPayloadBuilder = class {
667
+ constructor(db) {
668
+ this.db = db;
669
+ }
670
+ async buildDeleteCollectionRequest(input) {
671
+ const collection = await this.requireCollection(input.slug);
672
+ const collectionSummary = summarizeCollection(collection);
673
+ const actionHash = await buildStableActionHash({
674
+ actionType: "schema.delete_collection",
675
+ scope: collectionScope(collection.slug),
676
+ targetRefType: "collection",
677
+ targetRefId: collection.slug,
678
+ force: input.force === true,
679
+ collection: collectionSummary
680
+ });
681
+ const title = `Approve deleting collection ${collection.slug}`;
682
+ const summary = `Delete collection ${collection.slug} (${collection.label}) and its content table` + (input.force ? " with force enabled." : ".");
683
+ return {
684
+ scope: collectionScope(collection.slug),
685
+ actionType: "schema.delete_collection",
686
+ title,
687
+ summary,
688
+ riskReason: "destructive_schema_change",
689
+ targetRefType: "collection",
690
+ targetRefId: collection.slug,
691
+ priority: "high",
692
+ actionHash,
693
+ metadata: {
694
+ actionHash,
695
+ force: input.force === true
696
+ },
697
+ reviewPayload: {
698
+ kind: "schema_delete_collection",
699
+ actionType: "schema.delete_collection",
700
+ title,
701
+ summary,
702
+ target: {
703
+ scope: collectionScope(collection.slug),
704
+ targetRefType: "collection",
705
+ targetRefId: collection.slug,
706
+ actionHash
707
+ },
708
+ collection: collectionSummary,
709
+ options: { force: input.force === true }
710
+ }
711
+ };
712
+ }
713
+ async buildDeleteFieldRequest(input) {
714
+ const collection = await this.requireCollection(input.collection);
715
+ const field = collection.fields.find((item) => item.slug === input.fieldSlug);
716
+ if (!field) throw new Error(`Field not found: ${input.collection}.${input.fieldSlug}`);
717
+ const fieldSummary = summarizeField(field);
718
+ const actionHash = await buildStableActionHash({
719
+ actionType: "schema.delete_field",
720
+ scope: collectionScope(collection.slug),
721
+ targetRefType: "collection_field",
722
+ targetRefId: `${collection.slug}:${field.slug}`,
723
+ collection: summarizeCollection(collection),
724
+ field: fieldSummary
725
+ });
726
+ const title = `Approve deleting field ${collection.slug}.${field.slug}`;
727
+ const summary = `Delete field ${field.slug} (${field.label}) from collection ${collection.slug}.`;
728
+ return {
729
+ scope: collectionScope(collection.slug),
730
+ actionType: "schema.delete_field",
731
+ title,
732
+ summary,
733
+ riskReason: "destructive_schema_change",
734
+ targetRefType: "collection_field",
735
+ targetRefId: `${collection.slug}:${field.slug}`,
736
+ priority: "high",
737
+ actionHash,
738
+ metadata: { actionHash },
739
+ reviewPayload: {
740
+ kind: "schema_delete_field",
741
+ actionType: "schema.delete_field",
742
+ title,
743
+ summary,
744
+ target: {
745
+ scope: collectionScope(collection.slug),
746
+ targetRefType: "collection_field",
747
+ targetRefId: `${collection.slug}:${field.slug}`,
748
+ actionHash
749
+ },
750
+ collection: summarizeCollection(collection),
751
+ field: fieldSummary
752
+ }
753
+ };
754
+ }
755
+ async requireCollection(slug) {
756
+ const collection = await new SchemaRegistry(this.db).getCollectionWithFields(slug);
757
+ if (!collection) throw new Error(`Collection not found: ${slug}`);
758
+ return collection;
759
+ }
760
+ };
761
+ function collectionScope(slug) {
762
+ return `collection:${slug}`;
763
+ }
764
+ function summarizeCollection(collection) {
765
+ return {
766
+ id: collection.id,
767
+ slug: collection.slug,
768
+ label: collection.label,
769
+ labelSingular: collection.labelSingular,
770
+ description: collection.description,
771
+ icon: collection.icon,
772
+ supports: collection.supports,
773
+ hasSeo: collection.hasSeo,
774
+ commentsEnabled: collection.commentsEnabled,
775
+ fieldCount: collection.fields.length,
776
+ fields: collection.fields.map((field) => summarizeField(field))
777
+ };
778
+ }
779
+ function summarizeField(field) {
780
+ return {
781
+ id: field.id,
782
+ slug: field.slug,
783
+ label: field.label,
784
+ type: field.type,
785
+ required: field.required,
786
+ unique: field.unique,
787
+ searchable: field.searchable,
788
+ translatable: field.translatable,
789
+ defaultValue: field.defaultValue ?? null,
790
+ validation: field.validation ?? null,
791
+ options: field.options ?? null
792
+ };
793
+ }
794
+
795
+ //#endregion
796
+ //#region src/site-context/plugin-hitl.ts
797
+ var PluginHitlPayloadBuilder = class {
798
+ async buildEnableRequest(plugin) {
799
+ return this.build(plugin, {
800
+ actionType: "plugin.enable",
801
+ action: "enable",
802
+ title: `Enable plugin ${plugin.name}`,
803
+ summary: `Activate plugin ${plugin.id} and re-enable its hooks, routes, and scheduled work.`,
804
+ riskReason: "Enabling a plugin can change site behavior, expose routes, and restart plugin automation."
805
+ });
806
+ }
807
+ async buildDisableRequest(plugin) {
808
+ return this.build(plugin, {
809
+ actionType: "plugin.disable",
810
+ action: "disable",
811
+ title: `Disable plugin ${plugin.name}`,
812
+ summary: `Deactivate plugin ${plugin.id} and stop its hooks, routes, and scheduled work.`,
813
+ riskReason: "Disabling a plugin can remove site functionality and interrupt scheduled or automated behavior."
814
+ });
815
+ }
816
+ async buildUninstallRequest(plugin, input) {
817
+ const reviewPayload = {
818
+ plugin: summarizePlugin(plugin),
819
+ requestedChange: {
820
+ action: "uninstall",
821
+ deleteData: input.deleteData
822
+ }
823
+ };
824
+ const actionHash = await buildStableActionHash({
825
+ actionType: "plugin.uninstall",
826
+ plugin: summarizePlugin(plugin),
827
+ requestedChange: reviewPayload.requestedChange
828
+ });
829
+ return {
830
+ scope: pluginScope(plugin.id),
831
+ actionType: "plugin.uninstall",
832
+ title: `Uninstall plugin ${plugin.name}`,
833
+ summary: `Remove plugin ${plugin.id} from the site${input.deleteData ? " and delete its stored data" : ""}.`,
834
+ riskReason: "Uninstalling a plugin removes site functionality and may permanently delete plugin-managed state.",
835
+ reviewPayload,
836
+ targetRefType: "plugin",
837
+ targetRefId: plugin.id,
838
+ priority: "high",
839
+ metadata: { actionHash },
840
+ actionHash
841
+ };
842
+ }
843
+ async buildInstallRequest(plugin) {
844
+ const reviewPayload = {
845
+ plugin: summarizeMarketplacePlugin(plugin),
846
+ requestedChange: {
847
+ action: "install",
848
+ version: plugin.version
849
+ }
850
+ };
851
+ const actionHash = await buildStableActionHash({
852
+ actionType: "plugin.install",
853
+ plugin: summarizeMarketplacePlugin(plugin),
854
+ requestedChange: reviewPayload.requestedChange
855
+ });
856
+ return {
857
+ scope: pluginScope(plugin.id),
858
+ actionType: "plugin.install",
859
+ title: `Install marketplace plugin ${plugin.name}`,
860
+ summary: `Install marketplace plugin ${plugin.id} at version ${plugin.version}.`,
861
+ riskReason: "Installing a marketplace plugin downloads remote code, adds new capabilities, and can change site behavior immediately.",
862
+ reviewPayload,
863
+ targetRefType: "plugin",
864
+ targetRefId: plugin.id,
865
+ priority: "high",
866
+ metadata: { actionHash },
867
+ actionHash
868
+ };
869
+ }
870
+ async buildMarketplaceUpdateRequest(plugin) {
871
+ const reviewPayload = {
872
+ plugin: summarizeMarketplacePlugin(plugin),
873
+ currentVersion: plugin.oldVersion,
874
+ requestedChange: {
875
+ action: "update",
876
+ version: plugin.version
877
+ },
878
+ capabilityChanges: {
879
+ added: [...plugin.capabilityChanges.added],
880
+ removed: [...plugin.capabilityChanges.removed]
881
+ },
882
+ routeVisibilityChanges: { newlyPublic: [...plugin.routeVisibilityChanges.newlyPublic] }
883
+ };
884
+ const actionHash = await buildStableActionHash({
885
+ actionType: "plugin.update",
886
+ plugin: summarizeMarketplacePlugin(plugin),
887
+ currentVersion: plugin.oldVersion,
888
+ requestedChange: reviewPayload.requestedChange,
889
+ capabilityChanges: reviewPayload.capabilityChanges,
890
+ routeVisibilityChanges: reviewPayload.routeVisibilityChanges
891
+ });
892
+ return {
893
+ scope: pluginScope(plugin.id),
894
+ actionType: "plugin.update",
895
+ title: `Update marketplace plugin ${plugin.name}`,
896
+ summary: `Update marketplace plugin ${plugin.id} from ${plugin.oldVersion} to ${plugin.version}.`,
897
+ riskReason: "Updating a marketplace plugin replaces remote code and may add capabilities or expose new public routes.",
898
+ reviewPayload,
899
+ targetRefType: "plugin",
900
+ targetRefId: plugin.id,
901
+ priority: "high",
902
+ metadata: { actionHash },
903
+ actionHash
904
+ };
905
+ }
906
+ async build(plugin, input) {
907
+ const reviewPayload = {
908
+ plugin: summarizePlugin(plugin),
909
+ requestedChange: { action: input.action }
910
+ };
911
+ const actionHash = await buildStableActionHash({
912
+ actionType: input.actionType,
913
+ plugin: summarizePlugin(plugin),
914
+ requestedChange: reviewPayload.requestedChange
915
+ });
916
+ return {
917
+ scope: pluginScope(plugin.id),
918
+ actionType: input.actionType,
919
+ title: input.title,
920
+ summary: input.summary,
921
+ riskReason: input.riskReason,
922
+ reviewPayload,
923
+ targetRefType: "plugin",
924
+ targetRefId: plugin.id,
925
+ priority: "high",
926
+ metadata: { actionHash },
927
+ actionHash
928
+ };
929
+ }
930
+ };
931
+ function summarizePlugin(plugin) {
932
+ return {
933
+ id: plugin.id,
934
+ name: plugin.name,
935
+ status: plugin.status,
936
+ source: plugin.source ?? "config",
937
+ version: plugin.marketplaceVersion ?? plugin.version,
938
+ capabilities: [...plugin.capabilities].toSorted(),
939
+ hasAdminPages: plugin.hasAdminPages,
940
+ hasDashboardWidgets: plugin.hasDashboardWidgets,
941
+ hasHooks: plugin.hasHooks
942
+ };
943
+ }
944
+ function summarizeMarketplacePlugin(plugin) {
945
+ return {
946
+ id: plugin.id,
947
+ name: plugin.name,
948
+ description: plugin.description,
949
+ authorName: plugin.authorName,
950
+ version: plugin.version,
951
+ minDinewayVersion: plugin.minDinewayVersion,
952
+ bundleSize: plugin.bundleSize,
953
+ checksum: plugin.checksum,
954
+ changelog: plugin.changelog,
955
+ capabilities: [...plugin.capabilities].toSorted(),
956
+ status: plugin.status,
957
+ auditVerdict: plugin.auditVerdict,
958
+ imageAuditVerdict: plugin.imageAuditVerdict,
959
+ publishedAt: plugin.publishedAt
960
+ };
961
+ }
962
+ function pluginScope(pluginId) {
963
+ return `plugin:${pluginId}`;
964
+ }
965
+
966
+ //#endregion
967
+ //#region src/site-context/exclusive-hook-hitl.ts
968
+ var ExclusiveHookHitlPayloadBuilder = class {
969
+ async buildSetSelectionRequest(input) {
970
+ const providers = normalizeProviders(input.providers);
971
+ const actionHash = await buildStableActionHash({
972
+ actionType: "hook.exclusive.update",
973
+ hookName: input.hookName,
974
+ currentPluginId: input.currentPluginId,
975
+ requestedPluginId: input.requestedPluginId,
976
+ providers: providers.map((provider) => provider.pluginId)
977
+ });
978
+ const title = input.requestedPluginId ? `Approve exclusive hook provider change for ${input.hookName}` : `Approve clearing exclusive hook provider for ${input.hookName}`;
979
+ const summary = input.requestedPluginId ? `Select ${input.requestedPluginId} as the provider for ${input.hookName}.` : `Clear the selected provider for ${input.hookName}.`;
980
+ return {
981
+ scope: "site",
982
+ actionType: "hook.exclusive.update",
983
+ title,
984
+ summary,
985
+ riskReason: "exclusive_hook_selection_change",
986
+ targetRefType: "exclusive_hook",
987
+ targetRefId: input.hookName,
988
+ priority: "high",
989
+ metadata: {
990
+ actionHash,
991
+ hookName: input.hookName,
992
+ currentPluginId: input.currentPluginId,
993
+ requestedPluginId: input.requestedPluginId,
994
+ providerIds: providers.map((provider) => provider.pluginId)
995
+ },
996
+ reviewPayload: {
997
+ kind: "exclusive_hook_update",
998
+ actionType: "hook.exclusive.update",
999
+ title,
1000
+ summary,
1001
+ target: {
1002
+ scope: "site",
1003
+ targetRefType: "exclusive_hook",
1004
+ targetRefId: input.hookName,
1005
+ actionHash
1006
+ },
1007
+ hookName: input.hookName,
1008
+ currentPluginId: input.currentPluginId,
1009
+ requestedPluginId: input.requestedPluginId,
1010
+ providers
1011
+ },
1012
+ actionHash
1013
+ };
1014
+ }
1015
+ };
1016
+ function normalizeProviders(providers) {
1017
+ return providers.map((provider) => ({
1018
+ pluginId: provider.pluginId,
1019
+ pluginName: provider.pluginName
1020
+ })).toSorted((left, right) => left.pluginId.localeCompare(right.pluginId));
1021
+ }
1022
+
1023
+ //#endregion
1024
+ //#region src/site-context/import-hitl.ts
1025
+ var WordPressImportHitlPayloadBuilder = class {
1026
+ async buildPrepareRequest(input) {
1027
+ const plan = normalizePreparePlan(input.postTypes);
1028
+ const targetRefId = plan.postTypes.length > 0 ? plan.postTypes.map((item) => item.collection).join(",") : "site";
1029
+ const title = "Approve WordPress schema prepare";
1030
+ const summary = plan.postTypes.length === 1 ? `Create or update import-ready schema for collection ${plan.postTypes[0]?.collection}.` : `Create or update import-ready schema for ${plan.postTypes.length} WordPress collection mappings.`;
1031
+ const actionHash = await buildStableActionHash({
1032
+ actionType: "import.wordpress.prepare",
1033
+ plan
1034
+ });
1035
+ return {
1036
+ scope: "site",
1037
+ actionType: "import.wordpress.prepare",
1038
+ title,
1039
+ summary,
1040
+ riskReason: "Preparing WordPress import schema can create collections, add fields, and enable search behavior.",
1041
+ reviewPayload: {
1042
+ kind: "wordpress_import_prepare",
1043
+ actionType: "import.wordpress.prepare",
1044
+ title,
1045
+ summary,
1046
+ target: {
1047
+ scope: "site",
1048
+ targetRefType: "wordpress_import_plan",
1049
+ targetRefId,
1050
+ actionHash
1051
+ },
1052
+ plan
1053
+ },
1054
+ targetRefType: "wordpress_import_plan",
1055
+ targetRefId,
1056
+ priority: "high",
1057
+ metadata: {
1058
+ actionHash,
1059
+ collectionCount: plan.postTypes.length
1060
+ },
1061
+ actionHash
1062
+ };
1063
+ }
1064
+ async buildExecuteRequest(input) {
1065
+ const fileDigest = await sha256BufferHex(input.fileBuffer);
1066
+ const config = normalizeExecuteConfig(input.config);
1067
+ const targetRefId = `wxr:${fileDigest}`;
1068
+ const enabledMappings = Object.entries(config.postTypeMappings).filter(([, mapping]) => mapping.enabled);
1069
+ const title = "Approve WordPress WXR import";
1070
+ const summary = enabledMappings.length === 0 ? "Run a WordPress WXR import with no enabled post-type mappings." : `Run a WordPress WXR import into ${enabledMappings.length} enabled Dineway collection mappings.`;
1071
+ const actionHash = await buildStableActionHash({
1072
+ actionType: "import.wordpress.execute",
1073
+ fileDigest,
1074
+ config
1075
+ });
1076
+ return {
1077
+ scope: "site",
1078
+ actionType: "import.wordpress.execute",
1079
+ title,
1080
+ summary,
1081
+ riskReason: "Running a WordPress WXR import can create or overwrite large amounts of site content in bulk.",
1082
+ reviewPayload: {
1083
+ kind: "wordpress_import_execute",
1084
+ actionType: "import.wordpress.execute",
1085
+ title,
1086
+ summary,
1087
+ target: {
1088
+ scope: "site",
1089
+ targetRefType: "wordpress_import_file",
1090
+ targetRefId,
1091
+ actionHash
1092
+ },
1093
+ file: {
1094
+ name: input.fileName,
1095
+ digest: fileDigest
1096
+ },
1097
+ config
1098
+ },
1099
+ targetRefType: "wordpress_import_file",
1100
+ targetRefId,
1101
+ priority: "high",
1102
+ metadata: {
1103
+ actionHash,
1104
+ fileDigest,
1105
+ fileName: input.fileName
1106
+ },
1107
+ actionHash
1108
+ };
1109
+ }
1110
+ async buildPluginExecuteRequest(input) {
1111
+ const source = normalizePluginExecuteSource(input.siteUrl, input.items);
1112
+ const config = normalizeExecuteConfig(input.config);
1113
+ const enabledMappings = Object.entries(config.postTypeMappings).filter(([, mapping]) => mapping.enabled);
1114
+ const targetRefId = source.siteUrl;
1115
+ const sourceFingerprint = await buildStableActionHash(source.fingerprintItems);
1116
+ const title = "Approve WordPress plugin import";
1117
+ const summary = enabledMappings.length === 0 ? `Run a WordPress plugin import from ${source.siteUrl} with no enabled post-type mappings.` : `Run a WordPress plugin import from ${source.siteUrl} into ${enabledMappings.length} enabled Dineway collection mappings using ${source.totalItems} reviewed remote items.`;
1118
+ const actionHash = await buildStableActionHash({
1119
+ actionType: "import.wordpress_plugin.execute",
1120
+ siteUrl: source.siteUrl,
1121
+ sourceFingerprint,
1122
+ config
1123
+ });
1124
+ return {
1125
+ scope: "site",
1126
+ actionType: "import.wordpress_plugin.execute",
1127
+ title,
1128
+ summary,
1129
+ riskReason: "Running a remote WordPress plugin import can create or overwrite large amounts of site content in bulk from a live external source.",
1130
+ reviewPayload: {
1131
+ kind: "wordpress_plugin_import_execute",
1132
+ actionType: "import.wordpress_plugin.execute",
1133
+ title,
1134
+ summary,
1135
+ target: {
1136
+ scope: "site",
1137
+ targetRefType: "wordpress_plugin_source",
1138
+ targetRefId,
1139
+ actionHash
1140
+ },
1141
+ source: {
1142
+ siteUrl: source.siteUrl,
1143
+ totalItems: source.totalItems,
1144
+ postTypes: source.postTypes,
1145
+ fingerprint: sourceFingerprint
1146
+ },
1147
+ config
1148
+ },
1149
+ targetRefType: "wordpress_plugin_source",
1150
+ targetRefId,
1151
+ priority: "high",
1152
+ metadata: {
1153
+ actionHash,
1154
+ sourceFingerprint,
1155
+ siteUrl: source.siteUrl,
1156
+ itemCount: source.totalItems
1157
+ },
1158
+ actionHash
1159
+ };
1160
+ }
1161
+ async buildRewriteUrlsRequest(input) {
1162
+ const rewrite = normalizeRewriteRequest(input);
1163
+ const targetRefId = rewrite.collections?.length ? rewrite.collections.join(",") : "all";
1164
+ const title = "Approve WordPress URL rewrite";
1165
+ const summary = rewrite.collections?.length ? `Rewrite imported WordPress URLs across ${rewrite.collections.length} selected collections.` : "Rewrite imported WordPress URLs across all collections.";
1166
+ const actionHash = await buildStableActionHash({
1167
+ actionType: "import.wordpress.rewrite_urls",
1168
+ rewrite
1169
+ });
1170
+ return {
1171
+ scope: "site",
1172
+ actionType: "import.wordpress.rewrite_urls",
1173
+ title,
1174
+ summary,
1175
+ riskReason: "Rewriting imported WordPress URLs updates existing content in bulk and can change many references at once.",
1176
+ reviewPayload: {
1177
+ kind: "wordpress_import_rewrite_urls",
1178
+ actionType: "import.wordpress.rewrite_urls",
1179
+ title,
1180
+ summary,
1181
+ target: {
1182
+ scope: "site",
1183
+ targetRefType: "wordpress_url_rewrite",
1184
+ targetRefId,
1185
+ actionHash
1186
+ },
1187
+ rewrite
1188
+ },
1189
+ targetRefType: "wordpress_url_rewrite",
1190
+ targetRefId,
1191
+ priority: "high",
1192
+ metadata: {
1193
+ actionHash,
1194
+ urlCount: Object.keys(rewrite.urlMap).length
1195
+ },
1196
+ actionHash
1197
+ };
1198
+ }
1199
+ };
1200
+ function normalizePreparePlan(postTypes) {
1201
+ return { postTypes: postTypes.map((postType) => ({
1202
+ name: postType.name,
1203
+ collection: sanitizeWordPressImportSlug(postType.collection),
1204
+ fields: (postType.fields ?? []).map((field) => ({
1205
+ slug: sanitizeWordPressImportSlug(field.slug),
1206
+ label: field.label,
1207
+ type: field.type,
1208
+ required: field.required,
1209
+ searchable: field.searchable ?? false
1210
+ }))
1211
+ })) };
1212
+ }
1213
+ function normalizeExecuteConfig(input) {
1214
+ return {
1215
+ postTypeMappings: Object.fromEntries(Object.entries(input.postTypeMappings).map(([postType, mapping]) => [postType, {
1216
+ collection: sanitizeWordPressImportSlug(mapping.collection),
1217
+ enabled: mapping.enabled
1218
+ }])),
1219
+ skipExisting: input.skipExisting,
1220
+ importSections: input.importSections !== false,
1221
+ authorMappings: input.authorMappings ?? null,
1222
+ locale: input.locale ?? null
1223
+ };
1224
+ }
1225
+ function normalizeRewriteRequest(input) {
1226
+ return {
1227
+ urlMap: input.urlMap,
1228
+ collections: input.collections && input.collections.length > 0 ? [...new Set(input.collections.map((collection) => sanitizeWordPressImportSlug(collection)))].toSorted() : null
1229
+ };
1230
+ }
1231
+ function normalizePluginExecuteSource(siteUrl, items) {
1232
+ const normalizedSiteUrl = normalizeUrl(siteUrl);
1233
+ const fingerprintItems = items.map((item) => ({
1234
+ sourceId: String(item.sourceId),
1235
+ postType: item.postType,
1236
+ status: item.status,
1237
+ slug: item.slug,
1238
+ title: item.title,
1239
+ content: item.content,
1240
+ excerpt: item.excerpt ?? null,
1241
+ featuredImage: item.featuredImage ?? null,
1242
+ author: item.author ?? null,
1243
+ date: normalizeItemDate(item.date),
1244
+ locale: item.locale ?? null,
1245
+ translationGroup: item.translationGroup ?? null
1246
+ })).toSorted(comparePluginFingerprintItems);
1247
+ const postTypes = summarizePluginPostTypes(fingerprintItems);
1248
+ return {
1249
+ siteUrl: normalizedSiteUrl,
1250
+ totalItems: fingerprintItems.length,
1251
+ postTypes,
1252
+ fingerprintItems
1253
+ };
1254
+ }
1255
+ function summarizePluginPostTypes(items) {
1256
+ const grouped = /* @__PURE__ */ new Map();
1257
+ for (const item of items) {
1258
+ const existing = grouped.get(item.postType) ?? {
1259
+ count: 0,
1260
+ statuses: /* @__PURE__ */ new Map(),
1261
+ newestDate: null
1262
+ };
1263
+ existing.count += 1;
1264
+ existing.statuses.set(item.status, (existing.statuses.get(item.status) ?? 0) + 1);
1265
+ if (item.date && (!existing.newestDate || item.date > existing.newestDate)) existing.newestDate = item.date;
1266
+ grouped.set(item.postType, existing);
1267
+ }
1268
+ return Array.from(grouped.entries(), ([postType, summary]) => ({
1269
+ postType,
1270
+ count: summary.count,
1271
+ newestDate: summary.newestDate,
1272
+ statuses: Object.fromEntries([...summary.statuses.entries()].toSorted(([left], [right]) => left.localeCompare(right)))
1273
+ })).toSorted((left, right) => left.postType.localeCompare(right.postType));
1274
+ }
1275
+ function comparePluginFingerprintItems(left, right) {
1276
+ return left.postType.localeCompare(right.postType) || (left.locale ?? "").localeCompare(right.locale ?? "") || left.slug.localeCompare(right.slug) || left.sourceId.localeCompare(right.sourceId);
1277
+ }
1278
+ function normalizeItemDate(value) {
1279
+ if (!value) return null;
1280
+ const time = value.getTime();
1281
+ return Number.isNaN(time) ? null : value.toISOString();
1282
+ }
1283
+ async function sha256BufferHex(buffer) {
1284
+ const digest = await crypto.subtle.digest("SHA-256", buffer);
1285
+ return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
1286
+ }
1287
+
1288
+ //#endregion
1289
+ //#region src/site-context/settings-hitl.ts
1290
+ var SettingsHitlPayloadBuilder = class {
1291
+ constructor(db) {
1292
+ this.db = db;
1293
+ }
1294
+ async buildUpdateSettingsRequest(input) {
1295
+ const current = normalizeSiteSettings(await getSiteSettingsWithDb(this.db));
1296
+ const requestedChange = normalizeSiteSettings(input);
1297
+ const changedKeys = Object.keys(requestedChange).toSorted();
1298
+ const seoOnly = changedKeys.length === 1 && changedKeys[0] === "seo";
1299
+ const actionHash = await buildStableActionHash({
1300
+ actionType: "settings.update",
1301
+ current,
1302
+ requestedChange
1303
+ });
1304
+ const title = seoOnly ? "Approve updating site SEO defaults" : "Approve updating site settings";
1305
+ const summary = seoOnly ? "Update site-level SEO defaults and verification settings." : `Update site settings: ${formatChangedKeys(changedKeys)}.`;
1306
+ return {
1307
+ scope: "site",
1308
+ actionType: "settings.update",
1309
+ title,
1310
+ summary,
1311
+ riskReason: seoOnly ? "seo_strategy_change" : "site_configuration_change",
1312
+ targetRefType: "site_settings",
1313
+ targetRefId: "site",
1314
+ priority: "high",
1315
+ metadata: {
1316
+ actionHash,
1317
+ changedKeys,
1318
+ touchesSeo: changedKeys.includes("seo")
1319
+ },
1320
+ reviewPayload: {
1321
+ kind: "site_settings_update",
1322
+ actionType: "settings.update",
1323
+ title,
1324
+ summary,
1325
+ target: {
1326
+ scope: "site",
1327
+ targetRefType: "site_settings",
1328
+ targetRefId: "site",
1329
+ actionHash
1330
+ },
1331
+ changedKeys,
1332
+ current,
1333
+ requestedChange
1334
+ },
1335
+ actionHash
1336
+ };
1337
+ }
1338
+ };
1339
+ function normalizeSiteSettings(input) {
1340
+ return {
1341
+ title: input.title,
1342
+ tagline: input.tagline,
1343
+ logo: normalizeMediaReference(input.logo),
1344
+ favicon: normalizeMediaReference(input.favicon),
1345
+ url: input.url,
1346
+ postsPerPage: input.postsPerPage,
1347
+ dateFormat: input.dateFormat,
1348
+ timezone: input.timezone,
1349
+ social: input.social ? {
1350
+ twitter: input.social.twitter,
1351
+ github: input.social.github,
1352
+ facebook: input.social.facebook,
1353
+ instagram: input.social.instagram,
1354
+ linkedin: input.social.linkedin,
1355
+ youtube: input.social.youtube
1356
+ } : void 0,
1357
+ seo: input.seo ? {
1358
+ titleSeparator: input.seo.titleSeparator,
1359
+ defaultOgImage: normalizeMediaReference(input.seo.defaultOgImage),
1360
+ robotsTxt: input.seo.robotsTxt,
1361
+ googleVerification: input.seo.googleVerification,
1362
+ bingVerification: input.seo.bingVerification
1363
+ } : void 0
1364
+ };
1365
+ }
1366
+ function normalizeMediaReference(value) {
1367
+ if (!value) return void 0;
1368
+ return {
1369
+ mediaId: value.mediaId,
1370
+ alt: value.alt
1371
+ };
1372
+ }
1373
+ function formatChangedKeys(keys) {
1374
+ if (keys.length === 0) return "no fields";
1375
+ if (keys.length === 1) return keys[0];
1376
+ return keys.join(", ");
1377
+ }
1378
+
1379
+ //#endregion
1380
+ //#region src/site-context/redirect-hitl.ts
1381
+ var RedirectHitlPayloadBuilder = class {
1382
+ async buildCreateRedirectRequest(input) {
1383
+ const requestedChange = normalizeCreateRedirect(input);
1384
+ const actionHash = await buildStableActionHash({
1385
+ actionType: "redirect.create",
1386
+ requestedChange
1387
+ });
1388
+ const title = `Approve creating redirect ${input.source}`;
1389
+ const summary = `Create redirect ${input.source} -> ${input.destination} (${requestedChange.type}).`;
1390
+ return {
1391
+ scope: "site",
1392
+ actionType: "redirect.create",
1393
+ title,
1394
+ summary,
1395
+ riskReason: "seo_redirect_change",
1396
+ targetRefType: "redirect",
1397
+ targetRefId: input.source,
1398
+ priority: "high",
1399
+ metadata: {
1400
+ actionHash,
1401
+ source: requestedChange.source,
1402
+ destination: requestedChange.destination,
1403
+ redirectType: requestedChange.type,
1404
+ enabled: requestedChange.enabled,
1405
+ isPattern: requestedChange.isPattern
1406
+ },
1407
+ reviewPayload: {
1408
+ kind: "redirect_create",
1409
+ actionType: "redirect.create",
1410
+ title,
1411
+ summary,
1412
+ target: {
1413
+ scope: "site",
1414
+ targetRefType: "redirect",
1415
+ targetRefId: input.source,
1416
+ actionHash
1417
+ },
1418
+ requestedChange
1419
+ },
1420
+ actionHash
1421
+ };
1422
+ }
1423
+ async buildUpdateRedirectRequest(input) {
1424
+ const current = normalizeRedirect(input.redirect);
1425
+ const requestedChange = normalizeUpdateRedirect(input);
1426
+ const changedKeys = Object.keys(requestedChange).toSorted();
1427
+ const actionHash = await buildStableActionHash({
1428
+ actionType: "redirect.update",
1429
+ current,
1430
+ requestedChange
1431
+ });
1432
+ const title = `Approve updating redirect ${input.redirect.source}`;
1433
+ const summary = `Update redirect ${input.redirect.source} -> ${input.redirect.destination}.`;
1434
+ return {
1435
+ scope: "site",
1436
+ actionType: "redirect.update",
1437
+ title,
1438
+ summary,
1439
+ riskReason: "seo_redirect_change",
1440
+ targetRefType: "redirect",
1441
+ targetRefId: input.redirect.id,
1442
+ priority: "high",
1443
+ metadata: {
1444
+ actionHash,
1445
+ redirectId: input.redirect.id,
1446
+ source: input.redirect.source,
1447
+ destination: input.redirect.destination,
1448
+ changedKeys
1449
+ },
1450
+ reviewPayload: {
1451
+ kind: "redirect_update",
1452
+ actionType: "redirect.update",
1453
+ title,
1454
+ summary,
1455
+ target: {
1456
+ scope: "site",
1457
+ targetRefType: "redirect",
1458
+ targetRefId: input.redirect.id,
1459
+ actionHash
1460
+ },
1461
+ changedKeys,
1462
+ current,
1463
+ requestedChange
1464
+ },
1465
+ actionHash
1466
+ };
1467
+ }
1468
+ async buildDeleteRedirectRequest(input) {
1469
+ const current = normalizeRedirect(input.redirect);
1470
+ const actionHash = await buildStableActionHash({
1471
+ actionType: "redirect.delete",
1472
+ current
1473
+ });
1474
+ const title = `Approve deleting redirect ${input.redirect.source}`;
1475
+ const summary = `Delete redirect ${input.redirect.source} -> ${input.redirect.destination}.`;
1476
+ return {
1477
+ scope: "site",
1478
+ actionType: "redirect.delete",
1479
+ title,
1480
+ summary,
1481
+ riskReason: "seo_redirect_change",
1482
+ targetRefType: "redirect",
1483
+ targetRefId: input.redirect.id,
1484
+ priority: "high",
1485
+ metadata: {
1486
+ actionHash,
1487
+ redirectId: input.redirect.id,
1488
+ source: input.redirect.source,
1489
+ destination: input.redirect.destination
1490
+ },
1491
+ reviewPayload: {
1492
+ kind: "redirect_delete",
1493
+ actionType: "redirect.delete",
1494
+ title,
1495
+ summary,
1496
+ target: {
1497
+ scope: "site",
1498
+ targetRefType: "redirect",
1499
+ targetRefId: input.redirect.id,
1500
+ actionHash
1501
+ },
1502
+ current
1503
+ },
1504
+ actionHash
1505
+ };
1506
+ }
1507
+ };
1508
+ function normalizeCreateRedirect(input) {
1509
+ return {
1510
+ source: input.source,
1511
+ destination: input.destination,
1512
+ type: input.type ?? 301,
1513
+ enabled: input.enabled ?? true,
1514
+ groupName: input.groupName ?? null,
1515
+ isPattern: isPattern(input.source),
1516
+ auto: false
1517
+ };
1518
+ }
1519
+ function normalizeUpdateRedirect(input) {
1520
+ const requestedChange = {};
1521
+ if (input.source !== void 0) {
1522
+ requestedChange.source = input.source;
1523
+ requestedChange.isPattern = isPattern(input.source);
1524
+ }
1525
+ if (input.destination !== void 0) requestedChange.destination = input.destination;
1526
+ if (input.type !== void 0) requestedChange.type = input.type;
1527
+ if (input.enabled !== void 0) requestedChange.enabled = input.enabled;
1528
+ if (input.groupName !== void 0) requestedChange.groupName = input.groupName;
1529
+ return requestedChange;
1530
+ }
1531
+ function normalizeRedirect(redirect) {
1532
+ return {
1533
+ id: redirect.id,
1534
+ source: redirect.source,
1535
+ destination: redirect.destination,
1536
+ type: redirect.type,
1537
+ isPattern: redirect.isPattern,
1538
+ enabled: redirect.enabled,
1539
+ groupName: redirect.groupName,
1540
+ auto: redirect.auto
1541
+ };
1542
+ }
1543
+
1544
+ //#endregion
1545
+ //#region src/site-context/menu-hitl.ts
1546
+ var MenuHitlPayloadBuilder = class {
1547
+ constructor(db) {
1548
+ this.db = db;
1549
+ }
1550
+ async buildCreateMenuRequest(input) {
1551
+ const requestedChange = normalizeCreateMenuInput(input);
1552
+ const actionHash = await buildStableActionHash({
1553
+ actionType: "menu.create",
1554
+ requestedChange
1555
+ });
1556
+ const title = `Approve creating menu ${input.name}`;
1557
+ const summary = `Create navigation menu ${input.name} (${input.label}).`;
1558
+ return {
1559
+ scope: "site",
1560
+ actionType: "menu.create",
1561
+ title,
1562
+ summary,
1563
+ riskReason: "navigation_restructure",
1564
+ targetRefType: "menu",
1565
+ targetRefId: input.name,
1566
+ priority: "high",
1567
+ metadata: {
1568
+ actionHash,
1569
+ menuName: input.name
1570
+ },
1571
+ reviewPayload: {
1572
+ kind: "menu_create",
1573
+ actionType: "menu.create",
1574
+ title,
1575
+ summary,
1576
+ target: {
1577
+ scope: "site",
1578
+ targetRefType: "menu",
1579
+ targetRefId: input.name,
1580
+ actionHash
1581
+ },
1582
+ requestedChange
1583
+ },
1584
+ actionHash
1585
+ };
1586
+ }
1587
+ async buildUpdateMenuRequest(input) {
1588
+ const snapshot = await this.requireMenuSnapshot(input.name);
1589
+ const requestedChange = normalizeUpdateMenuInput(input);
1590
+ const current = summarizeMenuSnapshot(snapshot);
1591
+ const actionHash = await buildStableActionHash({
1592
+ actionType: "menu.update",
1593
+ current,
1594
+ requestedChange
1595
+ });
1596
+ const title = `Approve updating menu ${snapshot.menu.name}`;
1597
+ const summary = requestedChange.label !== null ? `Update navigation menu ${snapshot.menu.name} label to ${requestedChange.label}.` : `Update navigation menu ${snapshot.menu.name}.`;
1598
+ return {
1599
+ scope: "site",
1600
+ actionType: "menu.update",
1601
+ title,
1602
+ summary,
1603
+ riskReason: "navigation_restructure",
1604
+ targetRefType: "menu",
1605
+ targetRefId: snapshot.menu.name,
1606
+ priority: "high",
1607
+ metadata: {
1608
+ actionHash,
1609
+ menuName: snapshot.menu.name,
1610
+ menuId: snapshot.menu.id
1611
+ },
1612
+ reviewPayload: {
1613
+ kind: "menu_update",
1614
+ actionType: "menu.update",
1615
+ title,
1616
+ summary,
1617
+ target: {
1618
+ scope: "site",
1619
+ targetRefType: "menu",
1620
+ targetRefId: snapshot.menu.name,
1621
+ actionHash
1622
+ },
1623
+ current,
1624
+ requestedChange
1625
+ },
1626
+ actionHash
1627
+ };
1628
+ }
1629
+ async buildDeleteMenuRequest(input) {
1630
+ const snapshot = await this.requireMenuSnapshot(input.name);
1631
+ const current = summarizeMenuSnapshot(snapshot);
1632
+ const actionHash = await buildStableActionHash({
1633
+ actionType: "menu.delete",
1634
+ current
1635
+ });
1636
+ const title = `Approve deleting menu ${snapshot.menu.name}`;
1637
+ const summary = current.itemCount > 0 ? `Delete navigation menu ${snapshot.menu.name} and remove ${current.itemCount} menu items.` : `Delete navigation menu ${snapshot.menu.name}.`;
1638
+ return {
1639
+ scope: "site",
1640
+ actionType: "menu.delete",
1641
+ title,
1642
+ summary,
1643
+ riskReason: "navigation_restructure",
1644
+ targetRefType: "menu",
1645
+ targetRefId: snapshot.menu.name,
1646
+ priority: "high",
1647
+ metadata: {
1648
+ actionHash,
1649
+ menuName: snapshot.menu.name,
1650
+ menuId: snapshot.menu.id
1651
+ },
1652
+ reviewPayload: {
1653
+ kind: "menu_delete",
1654
+ actionType: "menu.delete",
1655
+ title,
1656
+ summary,
1657
+ target: {
1658
+ scope: "site",
1659
+ targetRefType: "menu",
1660
+ targetRefId: snapshot.menu.name,
1661
+ actionHash
1662
+ },
1663
+ current
1664
+ },
1665
+ actionHash
1666
+ };
1667
+ }
1668
+ async buildCreateMenuItemRequest(input) {
1669
+ const snapshot = await this.requireMenuSnapshot(input.menuName);
1670
+ const current = summarizeMenuSnapshot(snapshot);
1671
+ const requestedChange = normalizeCreateMenuItemInput(input);
1672
+ const actionHash = await buildStableActionHash({
1673
+ actionType: "menu.create_item",
1674
+ current,
1675
+ requestedChange
1676
+ });
1677
+ const title = `Approve adding item to menu ${snapshot.menu.name}`;
1678
+ const summary = `Add navigation item ${requestedChange.label} to menu ${snapshot.menu.name}.`;
1679
+ return {
1680
+ scope: "site",
1681
+ actionType: "menu.create_item",
1682
+ title,
1683
+ summary,
1684
+ riskReason: "navigation_restructure",
1685
+ targetRefType: "menu",
1686
+ targetRefId: snapshot.menu.name,
1687
+ priority: "high",
1688
+ metadata: {
1689
+ actionHash,
1690
+ menuName: snapshot.menu.name,
1691
+ menuId: snapshot.menu.id
1692
+ },
1693
+ reviewPayload: {
1694
+ kind: "menu_create_item",
1695
+ actionType: "menu.create_item",
1696
+ title,
1697
+ summary,
1698
+ target: {
1699
+ scope: "site",
1700
+ targetRefType: "menu",
1701
+ targetRefId: snapshot.menu.name,
1702
+ actionHash
1703
+ },
1704
+ current,
1705
+ requestedChange
1706
+ },
1707
+ actionHash
1708
+ };
1709
+ }
1710
+ async buildUpdateMenuItemRequest(input) {
1711
+ const snapshot = await this.requireMenuSnapshot(input.menuName);
1712
+ const item = requireMenuItem(snapshot, input.itemId);
1713
+ const current = summarizeMenuSnapshot(snapshot);
1714
+ const currentItem = summarizeMenuItem(item);
1715
+ const requestedChange = normalizeUpdateMenuItemInput(input);
1716
+ const actionHash = await buildStableActionHash({
1717
+ actionType: "menu.update_item",
1718
+ current,
1719
+ currentItem,
1720
+ requestedChange
1721
+ });
1722
+ const title = `Approve updating menu item ${item.label}`;
1723
+ const summary = `Update navigation item ${item.id} in menu ${snapshot.menu.name}.`;
1724
+ return {
1725
+ scope: "site",
1726
+ actionType: "menu.update_item",
1727
+ title,
1728
+ summary,
1729
+ riskReason: "navigation_restructure",
1730
+ targetRefType: "menu_item",
1731
+ targetRefId: item.id,
1732
+ priority: "high",
1733
+ metadata: {
1734
+ actionHash,
1735
+ menuName: snapshot.menu.name,
1736
+ menuId: snapshot.menu.id,
1737
+ itemId: item.id
1738
+ },
1739
+ reviewPayload: {
1740
+ kind: "menu_update_item",
1741
+ actionType: "menu.update_item",
1742
+ title,
1743
+ summary,
1744
+ target: {
1745
+ scope: "site",
1746
+ targetRefType: "menu_item",
1747
+ targetRefId: item.id,
1748
+ actionHash
1749
+ },
1750
+ current,
1751
+ currentItem,
1752
+ requestedChange
1753
+ },
1754
+ actionHash
1755
+ };
1756
+ }
1757
+ async buildDeleteMenuItemRequest(input) {
1758
+ const snapshot = await this.requireMenuSnapshot(input.menuName);
1759
+ const item = requireMenuItem(snapshot, input.itemId);
1760
+ const current = summarizeMenuSnapshot(snapshot);
1761
+ const currentItem = summarizeMenuItem(item);
1762
+ const actionHash = await buildStableActionHash({
1763
+ actionType: "menu.delete_item",
1764
+ current,
1765
+ currentItem
1766
+ });
1767
+ const title = `Approve deleting menu item ${item.label}`;
1768
+ const summary = `Delete navigation item ${item.id} from menu ${snapshot.menu.name}.`;
1769
+ return {
1770
+ scope: "site",
1771
+ actionType: "menu.delete_item",
1772
+ title,
1773
+ summary,
1774
+ riskReason: "navigation_restructure",
1775
+ targetRefType: "menu_item",
1776
+ targetRefId: item.id,
1777
+ priority: "high",
1778
+ metadata: {
1779
+ actionHash,
1780
+ menuName: snapshot.menu.name,
1781
+ menuId: snapshot.menu.id,
1782
+ itemId: item.id
1783
+ },
1784
+ reviewPayload: {
1785
+ kind: "menu_delete_item",
1786
+ actionType: "menu.delete_item",
1787
+ title,
1788
+ summary,
1789
+ target: {
1790
+ scope: "site",
1791
+ targetRefType: "menu_item",
1792
+ targetRefId: item.id,
1793
+ actionHash
1794
+ },
1795
+ current,
1796
+ currentItem
1797
+ },
1798
+ actionHash
1799
+ };
1800
+ }
1801
+ async buildReorderMenuItemsRequest(input) {
1802
+ const snapshot = await this.requireMenuSnapshot(input.menuName);
1803
+ const current = summarizeMenuSnapshot(snapshot);
1804
+ const requestedChange = normalizeReorderMenuItemsInput(input.items);
1805
+ const actionHash = await buildStableActionHash({
1806
+ actionType: "menu.reorder",
1807
+ current,
1808
+ requestedChange
1809
+ });
1810
+ const title = `Approve reordering menu ${snapshot.menu.name}`;
1811
+ const summary = requestedChange.items.length > 0 ? `Reorder ${requestedChange.items.length} navigation items in menu ${snapshot.menu.name}.` : `Reorder navigation items in menu ${snapshot.menu.name}.`;
1812
+ return {
1813
+ scope: "site",
1814
+ actionType: "menu.reorder",
1815
+ title,
1816
+ summary,
1817
+ riskReason: "navigation_restructure",
1818
+ targetRefType: "menu",
1819
+ targetRefId: snapshot.menu.name,
1820
+ priority: "high",
1821
+ metadata: {
1822
+ actionHash,
1823
+ menuName: snapshot.menu.name,
1824
+ menuId: snapshot.menu.id,
1825
+ itemCount: requestedChange.items.length
1826
+ },
1827
+ reviewPayload: {
1828
+ kind: "menu_reorder",
1829
+ actionType: "menu.reorder",
1830
+ title,
1831
+ summary,
1832
+ target: {
1833
+ scope: "site",
1834
+ targetRefType: "menu",
1835
+ targetRefId: snapshot.menu.name,
1836
+ actionHash
1837
+ },
1838
+ current,
1839
+ requestedChange
1840
+ },
1841
+ actionHash
1842
+ };
1843
+ }
1844
+ async requireMenuSnapshot(name) {
1845
+ const menu = await this.db.selectFrom("_dineway_menus").selectAll().where("name", "=", name).executeTakeFirst();
1846
+ if (!menu) throw new Error(`Menu not found: ${name}`);
1847
+ return {
1848
+ menu,
1849
+ items: await this.db.selectFrom("_dineway_menu_items").selectAll().where("menu_id", "=", menu.id).orderBy("sort_order", "asc").orderBy("id", "asc").execute()
1850
+ };
1851
+ }
1852
+ };
1853
+ function requireMenuItem(snapshot, itemId) {
1854
+ const item = snapshot.items.find((entry) => entry.id === itemId);
1855
+ if (!item) throw new Error(`Menu item not found: ${itemId}`);
1856
+ return item;
1857
+ }
1858
+ function summarizeMenuSnapshot(snapshot) {
1859
+ return {
1860
+ id: snapshot.menu.id,
1861
+ name: snapshot.menu.name,
1862
+ label: snapshot.menu.label,
1863
+ itemCount: snapshot.items.length,
1864
+ items: snapshot.items.map((item) => summarizeMenuItem(item))
1865
+ };
1866
+ }
1867
+ function summarizeMenuItem(item) {
1868
+ return {
1869
+ id: item.id,
1870
+ parentId: item.parent_id,
1871
+ sortOrder: item.sort_order,
1872
+ type: item.type,
1873
+ referenceCollection: item.reference_collection,
1874
+ referenceId: item.reference_id,
1875
+ customUrl: item.custom_url,
1876
+ label: item.label,
1877
+ titleAttr: item.title_attr,
1878
+ target: item.target,
1879
+ cssClasses: item.css_classes
1880
+ };
1881
+ }
1882
+ function normalizeCreateMenuInput(input) {
1883
+ return {
1884
+ name: input.name,
1885
+ label: input.label
1886
+ };
1887
+ }
1888
+ function normalizeUpdateMenuInput(input) {
1889
+ return { label: input.label ?? null };
1890
+ }
1891
+ function normalizeCreateMenuItemInput(input) {
1892
+ return {
1893
+ type: input.type,
1894
+ label: input.label,
1895
+ referenceCollection: input.referenceCollection ?? null,
1896
+ referenceId: input.referenceId ?? null,
1897
+ customUrl: input.customUrl ?? null,
1898
+ target: input.target ?? null,
1899
+ titleAttr: input.titleAttr ?? null,
1900
+ cssClasses: input.cssClasses ?? null,
1901
+ parentId: input.parentId ?? null,
1902
+ sortOrder: input.sortOrder ?? null
1903
+ };
1904
+ }
1905
+ function normalizeUpdateMenuItemInput(input) {
1906
+ return {
1907
+ label: input.label ?? null,
1908
+ customUrl: input.customUrl ?? null,
1909
+ target: input.target ?? null,
1910
+ titleAttr: input.titleAttr ?? null,
1911
+ cssClasses: input.cssClasses ?? null,
1912
+ parentId: input.parentId ?? null,
1913
+ sortOrder: input.sortOrder ?? null
1914
+ };
1915
+ }
1916
+ function normalizeReorderMenuItemsInput(items) {
1917
+ return { items: items.map((item) => ({
1918
+ id: item.id,
1919
+ parentId: item.parentId,
1920
+ sortOrder: item.sortOrder
1921
+ })).toSorted((left, right) => left.id.localeCompare(right.id)) };
1922
+ }
1923
+
1924
+ //#endregion
1925
+ //#region src/site-context/taxonomy-hitl.ts
1926
+ var TaxonomyHitlPayloadBuilder = class {
1927
+ constructor(db) {
1928
+ this.db = db;
1929
+ }
1930
+ async loadTaxonomyDefinition(name) {
1931
+ const row = await this.db.selectFrom("_dineway_taxonomy_defs").selectAll().where("name", "=", name).executeTakeFirst();
1932
+ return row ? normalizeTaxonomyDefinition(row) : null;
1933
+ }
1934
+ async buildCreateTaxonomyRequest(input) {
1935
+ const requestedChange = normalizeCreateTaxonomyInput(input);
1936
+ const actionHash = await buildStableActionHash({
1937
+ actionType: "taxonomy.create",
1938
+ requestedChange
1939
+ });
1940
+ const title = `Approve creating taxonomy ${requestedChange.name}`;
1941
+ const summary = requestedChange.collections.length > 0 ? `Create taxonomy ${requestedChange.name} (${requestedChange.label}) for ${requestedChange.collections.join(", ")}.` : `Create taxonomy ${requestedChange.name} (${requestedChange.label}).`;
1942
+ return {
1943
+ scope: "site",
1944
+ actionType: "taxonomy.create",
1945
+ title,
1946
+ summary,
1947
+ riskReason: "taxonomy_structure_change",
1948
+ targetRefType: "taxonomy",
1949
+ targetRefId: requestedChange.name,
1950
+ priority: "high",
1951
+ metadata: {
1952
+ actionHash,
1953
+ taxonomyName: requestedChange.name,
1954
+ hierarchical: requestedChange.hierarchical,
1955
+ collections: requestedChange.collections
1956
+ },
1957
+ reviewPayload: {
1958
+ kind: "taxonomy_create",
1959
+ actionType: "taxonomy.create",
1960
+ title,
1961
+ summary,
1962
+ target: {
1963
+ scope: "site",
1964
+ targetRefType: "taxonomy",
1965
+ targetRefId: requestedChange.name,
1966
+ actionHash
1967
+ },
1968
+ requestedChange
1969
+ },
1970
+ actionHash
1971
+ };
1972
+ }
1973
+ async buildCreateTermRequest(input) {
1974
+ const currentTaxonomy = normalizeTaxonomyDefinitionInput(input.taxonomy);
1975
+ const requestedChange = normalizeCreateTermInput(input);
1976
+ const actionHash = await buildStableActionHash({
1977
+ actionType: "taxonomy.term_create",
1978
+ currentTaxonomy,
1979
+ requestedChange
1980
+ });
1981
+ const title = `Approve creating term ${requestedChange.slug} in ${input.taxonomy.name}`;
1982
+ const summary = `Create taxonomy term ${requestedChange.label} in ${input.taxonomy.name}.`;
1983
+ return {
1984
+ scope: "site",
1985
+ actionType: "taxonomy.term_create",
1986
+ title,
1987
+ summary,
1988
+ riskReason: "taxonomy_structure_change",
1989
+ targetRefType: "taxonomy_term",
1990
+ targetRefId: taxonomyTermRefId(input.taxonomy.name, requestedChange.slug),
1991
+ priority: "high",
1992
+ metadata: {
1993
+ actionHash,
1994
+ taxonomyId: input.taxonomy.id,
1995
+ taxonomyName: input.taxonomy.name,
1996
+ termSlug: requestedChange.slug
1997
+ },
1998
+ reviewPayload: {
1999
+ kind: "taxonomy_term_create",
2000
+ actionType: "taxonomy.term_create",
2001
+ title,
2002
+ summary,
2003
+ target: {
2004
+ scope: "site",
2005
+ targetRefType: "taxonomy_term",
2006
+ targetRefId: taxonomyTermRefId(input.taxonomy.name, requestedChange.slug),
2007
+ actionHash
2008
+ },
2009
+ currentTaxonomy,
2010
+ requestedChange
2011
+ },
2012
+ actionHash
2013
+ };
2014
+ }
2015
+ async buildUpdateTermRequest(input) {
2016
+ const currentTaxonomy = normalizeTaxonomyDefinitionInput(input.taxonomy);
2017
+ const current = normalizeTerm(input.currentTerm);
2018
+ const requestedChange = normalizeUpdateTermInput(input);
2019
+ const changedKeys = Object.keys(requestedChange).toSorted();
2020
+ const actionHash = await buildStableActionHash({
2021
+ actionType: "taxonomy.term_update",
2022
+ currentTaxonomy,
2023
+ current,
2024
+ requestedChange
2025
+ });
2026
+ const title = `Approve updating term ${input.currentTerm.slug} in ${input.taxonomy.name}`;
2027
+ const summary = `Update taxonomy term ${input.currentTerm.slug} in ${input.taxonomy.name}.`;
2028
+ return {
2029
+ scope: "site",
2030
+ actionType: "taxonomy.term_update",
2031
+ title,
2032
+ summary,
2033
+ riskReason: "taxonomy_structure_change",
2034
+ targetRefType: "taxonomy_term",
2035
+ targetRefId: input.currentTerm.id,
2036
+ priority: "high",
2037
+ metadata: {
2038
+ actionHash,
2039
+ taxonomyId: input.taxonomy.id,
2040
+ taxonomyName: input.taxonomy.name,
2041
+ termId: input.currentTerm.id,
2042
+ termSlug: input.currentTerm.slug,
2043
+ changedKeys
2044
+ },
2045
+ reviewPayload: {
2046
+ kind: "taxonomy_term_update",
2047
+ actionType: "taxonomy.term_update",
2048
+ title,
2049
+ summary,
2050
+ target: {
2051
+ scope: "site",
2052
+ targetRefType: "taxonomy_term",
2053
+ targetRefId: input.currentTerm.id,
2054
+ actionHash
2055
+ },
2056
+ changedKeys,
2057
+ currentTaxonomy,
2058
+ current,
2059
+ requestedChange
2060
+ },
2061
+ actionHash
2062
+ };
2063
+ }
2064
+ async buildDeleteTermRequest(input) {
2065
+ const currentTaxonomy = normalizeTaxonomyDefinitionInput(input.taxonomy);
2066
+ const current = normalizeTerm(input.currentTerm);
2067
+ const actionHash = await buildStableActionHash({
2068
+ actionType: "taxonomy.term_delete",
2069
+ currentTaxonomy,
2070
+ current
2071
+ });
2072
+ const title = `Approve deleting term ${input.currentTerm.slug} from ${input.taxonomy.name}`;
2073
+ const summary = `Delete taxonomy term ${input.currentTerm.slug} from ${input.taxonomy.name}.`;
2074
+ return {
2075
+ scope: "site",
2076
+ actionType: "taxonomy.term_delete",
2077
+ title,
2078
+ summary,
2079
+ riskReason: "taxonomy_structure_change",
2080
+ targetRefType: "taxonomy_term",
2081
+ targetRefId: input.currentTerm.id,
2082
+ priority: "high",
2083
+ metadata: {
2084
+ actionHash,
2085
+ taxonomyId: input.taxonomy.id,
2086
+ taxonomyName: input.taxonomy.name,
2087
+ termId: input.currentTerm.id,
2088
+ termSlug: input.currentTerm.slug
2089
+ },
2090
+ reviewPayload: {
2091
+ kind: "taxonomy_term_delete",
2092
+ actionType: "taxonomy.term_delete",
2093
+ title,
2094
+ summary,
2095
+ target: {
2096
+ scope: "site",
2097
+ targetRefType: "taxonomy_term",
2098
+ targetRefId: input.currentTerm.id,
2099
+ actionHash
2100
+ },
2101
+ currentTaxonomy,
2102
+ current
2103
+ },
2104
+ actionHash
2105
+ };
2106
+ }
2107
+ };
2108
+ function normalizeTaxonomyDefinition(row) {
2109
+ return {
2110
+ id: row.id,
2111
+ name: row.name,
2112
+ label: row.label,
2113
+ labelSingular: row.label_singular,
2114
+ hierarchical: row.hierarchical === 1,
2115
+ collections: normalizeCollections(row.collections ? JSON.parse(row.collections) : [])
2116
+ };
2117
+ }
2118
+ function normalizeTaxonomyDefinitionInput(taxonomy) {
2119
+ return {
2120
+ id: taxonomy.id,
2121
+ name: taxonomy.name,
2122
+ label: taxonomy.label,
2123
+ labelSingular: taxonomy.labelSingular,
2124
+ hierarchical: taxonomy.hierarchical,
2125
+ collections: normalizeCollections(taxonomy.collections)
2126
+ };
2127
+ }
2128
+ function normalizeCreateTaxonomyInput(input) {
2129
+ return {
2130
+ name: input.name,
2131
+ label: input.label,
2132
+ hierarchical: input.hierarchical ?? false,
2133
+ collections: normalizeCollections(input.collections ?? [])
2134
+ };
2135
+ }
2136
+ function normalizeCreateTermInput(input) {
2137
+ return {
2138
+ slug: input.slug,
2139
+ label: input.label,
2140
+ parentId: input.parentId ?? null,
2141
+ description: input.description ?? null
2142
+ };
2143
+ }
2144
+ function normalizeUpdateTermInput(input) {
2145
+ const requestedChange = {};
2146
+ if (input.slug !== void 0) requestedChange.slug = input.slug;
2147
+ if (input.label !== void 0) requestedChange.label = input.label;
2148
+ if (input.parentId !== void 0) requestedChange.parentId = input.parentId;
2149
+ if (input.description !== void 0) requestedChange.description = input.description;
2150
+ return requestedChange;
2151
+ }
2152
+ function normalizeTerm(term) {
2153
+ return {
2154
+ id: term.id,
2155
+ name: term.name,
2156
+ slug: term.slug,
2157
+ label: term.label,
2158
+ parentId: term.parentId,
2159
+ description: term.description ?? null
2160
+ };
2161
+ }
2162
+ function normalizeCollections(collections) {
2163
+ if (!Array.isArray(collections)) return [];
2164
+ return [...new Set(collections.filter((value) => typeof value === "string"))].toSorted();
2165
+ }
2166
+ function taxonomyTermRefId(taxonomyName, termSlug) {
2167
+ return `${taxonomyName}:${termSlug}`;
2168
+ }
2169
+
2170
+ //#endregion
2171
+ //#region src/site-context/section-hitl.ts
2172
+ var SectionHitlPayloadBuilder = class {
2173
+ constructor(db) {
2174
+ this.db = db;
2175
+ }
2176
+ async loadSectionSnapshot(slug) {
2177
+ const row = await this.db.selectFrom("_dineway_sections").selectAll().where("slug", "=", slug).executeTakeFirst();
2178
+ return row ? normalizeSection(row) : null;
2179
+ }
2180
+ async buildCreateSectionRequest(input) {
2181
+ const requestedChange = normalizeCreateSectionInput(input);
2182
+ const actionHash = await buildStableActionHash({
2183
+ actionType: "section.create",
2184
+ requestedChange
2185
+ });
2186
+ const title = `Approve creating section ${requestedChange.slug}`;
2187
+ const summary = `Create reusable section ${requestedChange.slug} (${requestedChange.title}).`;
2188
+ return {
2189
+ scope: "site",
2190
+ actionType: "section.create",
2191
+ title,
2192
+ summary,
2193
+ riskReason: "reusable_content_change",
2194
+ targetRefType: "section",
2195
+ targetRefId: requestedChange.slug,
2196
+ priority: "high",
2197
+ metadata: {
2198
+ actionHash,
2199
+ sectionSlug: requestedChange.slug,
2200
+ source: requestedChange.source,
2201
+ themeId: requestedChange.themeId
2202
+ },
2203
+ reviewPayload: {
2204
+ kind: "section_create",
2205
+ actionType: "section.create",
2206
+ title,
2207
+ summary,
2208
+ target: {
2209
+ scope: "site",
2210
+ targetRefType: "section",
2211
+ targetRefId: requestedChange.slug,
2212
+ actionHash
2213
+ },
2214
+ requestedChange
2215
+ },
2216
+ actionHash
2217
+ };
2218
+ }
2219
+ async buildUpdateSectionRequest(input) {
2220
+ const current = normalizeSectionInput(input.section);
2221
+ const requestedChange = normalizeUpdateSectionInput(input);
2222
+ const changedKeys = Object.keys(requestedChange).toSorted();
2223
+ const actionHash = await buildStableActionHash({
2224
+ actionType: "section.update",
2225
+ current,
2226
+ requestedChange
2227
+ });
2228
+ const title = `Approve updating section ${input.section.slug}`;
2229
+ const summary = `Update reusable section ${input.section.slug}.`;
2230
+ return {
2231
+ scope: "site",
2232
+ actionType: "section.update",
2233
+ title,
2234
+ summary,
2235
+ riskReason: "reusable_content_change",
2236
+ targetRefType: "section",
2237
+ targetRefId: input.section.id,
2238
+ priority: "high",
2239
+ metadata: {
2240
+ actionHash,
2241
+ sectionId: input.section.id,
2242
+ sectionSlug: input.section.slug,
2243
+ source: input.section.source,
2244
+ themeId: input.section.themeId,
2245
+ changedKeys
2246
+ },
2247
+ reviewPayload: {
2248
+ kind: "section_update",
2249
+ actionType: "section.update",
2250
+ title,
2251
+ summary,
2252
+ target: {
2253
+ scope: "site",
2254
+ targetRefType: "section",
2255
+ targetRefId: input.section.id,
2256
+ actionHash
2257
+ },
2258
+ changedKeys,
2259
+ current,
2260
+ requestedChange
2261
+ },
2262
+ actionHash
2263
+ };
2264
+ }
2265
+ async buildDeleteSectionRequest(input) {
2266
+ const current = normalizeSectionInput(input.section);
2267
+ const actionHash = await buildStableActionHash({
2268
+ actionType: "section.delete",
2269
+ current
2270
+ });
2271
+ const title = `Approve deleting section ${input.section.slug}`;
2272
+ const summary = `Delete reusable section ${input.section.slug}.`;
2273
+ return {
2274
+ scope: "site",
2275
+ actionType: "section.delete",
2276
+ title,
2277
+ summary,
2278
+ riskReason: "reusable_content_change",
2279
+ targetRefType: "section",
2280
+ targetRefId: input.section.id,
2281
+ priority: "high",
2282
+ metadata: {
2283
+ actionHash,
2284
+ sectionId: input.section.id,
2285
+ sectionSlug: input.section.slug,
2286
+ source: input.section.source,
2287
+ themeId: input.section.themeId
2288
+ },
2289
+ reviewPayload: {
2290
+ kind: "section_delete",
2291
+ actionType: "section.delete",
2292
+ title,
2293
+ summary,
2294
+ target: {
2295
+ scope: "site",
2296
+ targetRefType: "section",
2297
+ targetRefId: input.section.id,
2298
+ actionHash
2299
+ },
2300
+ current
2301
+ },
2302
+ actionHash
2303
+ };
2304
+ }
2305
+ };
2306
+ function normalizeSection(row) {
2307
+ return {
2308
+ id: row.id,
2309
+ slug: row.slug,
2310
+ title: row.title,
2311
+ description: row.description,
2312
+ keywords: parseStringArray(row.keywords),
2313
+ content: parseUnknownArray$1(row.content),
2314
+ previewMediaId: row.preview_media_id,
2315
+ source: row.source,
2316
+ themeId: row.theme_id
2317
+ };
2318
+ }
2319
+ function normalizeSectionInput(section) {
2320
+ return {
2321
+ id: section.id,
2322
+ slug: section.slug,
2323
+ title: section.title,
2324
+ description: section.description,
2325
+ keywords: [...section.keywords],
2326
+ content: [...section.content],
2327
+ previewMediaId: section.previewMediaId,
2328
+ source: section.source,
2329
+ themeId: section.themeId
2330
+ };
2331
+ }
2332
+ function normalizeCreateSectionInput(input) {
2333
+ return {
2334
+ slug: input.slug,
2335
+ title: input.title,
2336
+ description: input.description ?? null,
2337
+ keywords: input.keywords ?? [],
2338
+ content: input.content,
2339
+ previewMediaId: input.previewMediaId ?? null,
2340
+ source: input.source ?? "user",
2341
+ themeId: input.themeId ?? null
2342
+ };
2343
+ }
2344
+ function normalizeUpdateSectionInput(input) {
2345
+ const requestedChange = {};
2346
+ if (input.slug !== void 0) requestedChange.slug = input.slug;
2347
+ if (input.title !== void 0) requestedChange.title = input.title;
2348
+ if (input.description !== void 0) requestedChange.description = input.description;
2349
+ if (input.keywords !== void 0) requestedChange.keywords = input.keywords;
2350
+ if (input.content !== void 0) requestedChange.content = input.content;
2351
+ if (input.previewMediaId !== void 0) requestedChange.previewMediaId = input.previewMediaId;
2352
+ return requestedChange;
2353
+ }
2354
+ function parseStringArray(value) {
2355
+ if (!value) return [];
2356
+ try {
2357
+ const parsed = JSON.parse(value);
2358
+ return Array.isArray(parsed) ? parsed.filter((entry) => typeof entry === "string") : [];
2359
+ } catch {
2360
+ return [];
2361
+ }
2362
+ }
2363
+ function parseUnknownArray$1(value) {
2364
+ try {
2365
+ const parsed = JSON.parse(value);
2366
+ return Array.isArray(parsed) ? parsed : [];
2367
+ } catch {
2368
+ return [];
2369
+ }
2370
+ }
2371
+
2372
+ //#endregion
2373
+ //#region src/site-context/widget-hitl.ts
2374
+ var WidgetHitlPayloadBuilder = class {
2375
+ constructor(db) {
2376
+ this.db = db;
2377
+ }
2378
+ async loadWidgetAreaSnapshot(name) {
2379
+ const area = await this.db.selectFrom("_dineway_widget_areas").selectAll().where("name", "=", name).executeTakeFirst();
2380
+ if (!area) return null;
2381
+ const widgets = await this.db.selectFrom("_dineway_widgets").selectAll().where("area_id", "=", area.id).orderBy("sort_order", "asc").execute();
2382
+ return {
2383
+ ...normalizeWidgetArea(area),
2384
+ widgets: widgets.map(normalizeWidget)
2385
+ };
2386
+ }
2387
+ async buildCreateWidgetAreaRequest(input) {
2388
+ const requestedChange = normalizeCreateWidgetAreaInput(input);
2389
+ const actionHash = await buildStableActionHash({
2390
+ actionType: "widget_area.create",
2391
+ requestedChange
2392
+ });
2393
+ const title = `Approve creating widget area ${requestedChange.name}`;
2394
+ const summary = `Create widget area ${requestedChange.name} (${requestedChange.label}).`;
2395
+ return {
2396
+ scope: "site",
2397
+ actionType: "widget_area.create",
2398
+ title,
2399
+ summary,
2400
+ riskReason: "layout_structure_change",
2401
+ targetRefType: "widget_area",
2402
+ targetRefId: requestedChange.name,
2403
+ priority: "high",
2404
+ metadata: {
2405
+ actionHash,
2406
+ areaName: requestedChange.name
2407
+ },
2408
+ reviewPayload: {
2409
+ kind: "widget_area_create",
2410
+ actionType: "widget_area.create",
2411
+ title,
2412
+ summary,
2413
+ target: {
2414
+ scope: "site",
2415
+ targetRefType: "widget_area",
2416
+ targetRefId: requestedChange.name,
2417
+ actionHash
2418
+ },
2419
+ requestedChange
2420
+ },
2421
+ actionHash
2422
+ };
2423
+ }
2424
+ async buildDeleteWidgetAreaRequest(input) {
2425
+ const current = normalizeWidgetAreaInput(input.area);
2426
+ const actionHash = await buildStableActionHash({
2427
+ actionType: "widget_area.delete",
2428
+ current
2429
+ });
2430
+ const title = `Approve deleting widget area ${input.area.name}`;
2431
+ const summary = input.area.widgets.length > 0 ? `Delete widget area ${input.area.name} and remove ${input.area.widgets.length} widgets.` : `Delete widget area ${input.area.name}.`;
2432
+ return {
2433
+ scope: "site",
2434
+ actionType: "widget_area.delete",
2435
+ title,
2436
+ summary,
2437
+ riskReason: "layout_structure_change",
2438
+ targetRefType: "widget_area",
2439
+ targetRefId: input.area.id,
2440
+ priority: "high",
2441
+ metadata: {
2442
+ actionHash,
2443
+ areaId: input.area.id,
2444
+ areaName: input.area.name,
2445
+ widgetCount: input.area.widgets.length
2446
+ },
2447
+ reviewPayload: {
2448
+ kind: "widget_area_delete",
2449
+ actionType: "widget_area.delete",
2450
+ title,
2451
+ summary,
2452
+ target: {
2453
+ scope: "site",
2454
+ targetRefType: "widget_area",
2455
+ targetRefId: input.area.id,
2456
+ actionHash
2457
+ },
2458
+ current
2459
+ },
2460
+ actionHash
2461
+ };
2462
+ }
2463
+ async buildCreateWidgetRequest(input) {
2464
+ const currentArea = normalizeWidgetAreaInput(input.area);
2465
+ const requestedChange = normalizeCreateWidgetInput(input);
2466
+ const actionHash = await buildStableActionHash({
2467
+ actionType: "widget.create",
2468
+ currentArea,
2469
+ requestedChange
2470
+ });
2471
+ const title = `Approve adding widget to ${input.area.name}`;
2472
+ const summary = `Add ${requestedChange.type} widget to area ${input.area.name}.`;
2473
+ return {
2474
+ scope: "site",
2475
+ actionType: "widget.create",
2476
+ title,
2477
+ summary,
2478
+ riskReason: "layout_structure_change",
2479
+ targetRefType: "widget_area",
2480
+ targetRefId: input.area.id,
2481
+ priority: "high",
2482
+ metadata: {
2483
+ actionHash,
2484
+ areaId: input.area.id,
2485
+ areaName: input.area.name,
2486
+ widgetType: requestedChange.type
2487
+ },
2488
+ reviewPayload: {
2489
+ kind: "widget_create",
2490
+ actionType: "widget.create",
2491
+ title,
2492
+ summary,
2493
+ target: {
2494
+ scope: "site",
2495
+ targetRefType: "widget_area",
2496
+ targetRefId: input.area.id,
2497
+ actionHash
2498
+ },
2499
+ currentArea,
2500
+ requestedChange
2501
+ },
2502
+ actionHash
2503
+ };
2504
+ }
2505
+ async buildUpdateWidgetRequest(input) {
2506
+ const current = normalizeWidgetInput(input.currentWidget);
2507
+ const requestedChange = normalizeUpdateWidgetInput(input);
2508
+ const changedKeys = Object.keys(requestedChange).toSorted();
2509
+ const actionHash = await buildStableActionHash({
2510
+ actionType: "widget.update",
2511
+ current,
2512
+ requestedChange
2513
+ });
2514
+ const title = `Approve updating widget ${input.currentWidget.id}`;
2515
+ const summary = `Update widget ${input.currentWidget.id} in area ${input.area.name}.`;
2516
+ return {
2517
+ scope: "site",
2518
+ actionType: "widget.update",
2519
+ title,
2520
+ summary,
2521
+ riskReason: "layout_structure_change",
2522
+ targetRefType: "widget",
2523
+ targetRefId: input.currentWidget.id,
2524
+ priority: "high",
2525
+ metadata: {
2526
+ actionHash,
2527
+ areaId: input.area.id,
2528
+ areaName: input.area.name,
2529
+ widgetId: input.currentWidget.id,
2530
+ changedKeys
2531
+ },
2532
+ reviewPayload: {
2533
+ kind: "widget_update",
2534
+ actionType: "widget.update",
2535
+ title,
2536
+ summary,
2537
+ target: {
2538
+ scope: "site",
2539
+ targetRefType: "widget",
2540
+ targetRefId: input.currentWidget.id,
2541
+ actionHash
2542
+ },
2543
+ changedKeys,
2544
+ current,
2545
+ requestedChange
2546
+ },
2547
+ actionHash
2548
+ };
2549
+ }
2550
+ async buildDeleteWidgetRequest(input) {
2551
+ const current = normalizeWidgetInput(input.currentWidget);
2552
+ const actionHash = await buildStableActionHash({
2553
+ actionType: "widget.delete",
2554
+ current
2555
+ });
2556
+ const title = `Approve deleting widget ${input.currentWidget.id}`;
2557
+ const summary = `Delete widget ${input.currentWidget.id} from area ${input.area.name}.`;
2558
+ return {
2559
+ scope: "site",
2560
+ actionType: "widget.delete",
2561
+ title,
2562
+ summary,
2563
+ riskReason: "layout_structure_change",
2564
+ targetRefType: "widget",
2565
+ targetRefId: input.currentWidget.id,
2566
+ priority: "high",
2567
+ metadata: {
2568
+ actionHash,
2569
+ areaId: input.area.id,
2570
+ areaName: input.area.name,
2571
+ widgetId: input.currentWidget.id
2572
+ },
2573
+ reviewPayload: {
2574
+ kind: "widget_delete",
2575
+ actionType: "widget.delete",
2576
+ title,
2577
+ summary,
2578
+ target: {
2579
+ scope: "site",
2580
+ targetRefType: "widget",
2581
+ targetRefId: input.currentWidget.id,
2582
+ actionHash
2583
+ },
2584
+ current
2585
+ },
2586
+ actionHash
2587
+ };
2588
+ }
2589
+ async buildReorderWidgetsRequest(input) {
2590
+ const currentArea = normalizeWidgetAreaInput(input.area);
2591
+ const requestedChange = normalizeReorderWidgetsInput(input.widgetIds);
2592
+ const actionHash = await buildStableActionHash({
2593
+ actionType: "widget.reorder",
2594
+ currentArea,
2595
+ requestedChange
2596
+ });
2597
+ const title = `Approve reordering widgets in ${input.area.name}`;
2598
+ const summary = `Reorder ${input.widgetIds.length} widgets in area ${input.area.name}.`;
2599
+ return {
2600
+ scope: "site",
2601
+ actionType: "widget.reorder",
2602
+ title,
2603
+ summary,
2604
+ riskReason: "layout_structure_change",
2605
+ targetRefType: "widget_area",
2606
+ targetRefId: input.area.id,
2607
+ priority: "high",
2608
+ metadata: {
2609
+ actionHash,
2610
+ areaId: input.area.id,
2611
+ areaName: input.area.name,
2612
+ widgetIds: [...input.widgetIds]
2613
+ },
2614
+ reviewPayload: {
2615
+ kind: "widget_reorder",
2616
+ actionType: "widget.reorder",
2617
+ title,
2618
+ summary,
2619
+ target: {
2620
+ scope: "site",
2621
+ targetRefType: "widget_area",
2622
+ targetRefId: input.area.id,
2623
+ actionHash
2624
+ },
2625
+ currentArea,
2626
+ requestedChange
2627
+ },
2628
+ actionHash
2629
+ };
2630
+ }
2631
+ };
2632
+ function normalizeWidgetArea(row) {
2633
+ return {
2634
+ id: row.id,
2635
+ name: row.name,
2636
+ label: row.label,
2637
+ description: row.description
2638
+ };
2639
+ }
2640
+ function normalizeWidget(row) {
2641
+ return {
2642
+ id: row.id,
2643
+ areaId: row.area_id,
2644
+ sortOrder: row.sort_order,
2645
+ type: row.type,
2646
+ title: row.title,
2647
+ content: parseUnknownArray(row.content),
2648
+ menuName: row.menu_name,
2649
+ componentId: row.component_id,
2650
+ componentProps: parseUnknownRecord(row.component_props)
2651
+ };
2652
+ }
2653
+ function normalizeWidgetAreaInput(area) {
2654
+ return {
2655
+ id: area.id,
2656
+ name: area.name,
2657
+ label: area.label,
2658
+ description: area.description,
2659
+ widgets: area.widgets.map(normalizeWidgetInput)
2660
+ };
2661
+ }
2662
+ function normalizeWidgetInput(widget) {
2663
+ return {
2664
+ id: widget.id,
2665
+ areaId: widget.areaId,
2666
+ sortOrder: widget.sortOrder,
2667
+ type: widget.type,
2668
+ title: widget.title,
2669
+ content: widget.content,
2670
+ menuName: widget.menuName,
2671
+ componentId: widget.componentId,
2672
+ componentProps: widget.componentProps
2673
+ };
2674
+ }
2675
+ function normalizeCreateWidgetAreaInput(input) {
2676
+ return {
2677
+ name: input.name,
2678
+ label: input.label,
2679
+ description: input.description ?? null
2680
+ };
2681
+ }
2682
+ function normalizeCreateWidgetInput(input) {
2683
+ return {
2684
+ type: input.type,
2685
+ title: input.title ?? null,
2686
+ content: input.content ?? null,
2687
+ menuName: input.menuName ?? null,
2688
+ componentId: input.componentId ?? null,
2689
+ componentProps: input.componentProps ?? null
2690
+ };
2691
+ }
2692
+ function normalizeUpdateWidgetInput(input) {
2693
+ const requestedChange = {};
2694
+ if (input.type !== void 0) requestedChange.type = input.type;
2695
+ if (input.title !== void 0) requestedChange.title = input.title || null;
2696
+ if (input.content !== void 0) requestedChange.content = input.content;
2697
+ if (input.menuName !== void 0) requestedChange.menuName = input.menuName || null;
2698
+ if (input.componentId !== void 0) requestedChange.componentId = input.componentId || null;
2699
+ if (input.componentProps !== void 0) requestedChange.componentProps = input.componentProps;
2700
+ return requestedChange;
2701
+ }
2702
+ function normalizeReorderWidgetsInput(widgetIds) {
2703
+ return widgetIds.map((id, index) => ({
2704
+ id,
2705
+ sortOrder: index
2706
+ }));
2707
+ }
2708
+ function parseUnknownArray(value) {
2709
+ if (!value) return null;
2710
+ try {
2711
+ const parsed = JSON.parse(value);
2712
+ return Array.isArray(parsed) ? parsed : null;
2713
+ } catch {
2714
+ return null;
2715
+ }
2716
+ }
2717
+ function parseUnknownRecord(value) {
2718
+ if (!value) return null;
2719
+ try {
2720
+ const parsed = JSON.parse(value);
2721
+ return isRecord$1(parsed) ? parsed : null;
2722
+ } catch {
2723
+ return null;
2724
+ }
2725
+ }
2726
+ function isRecord$1(value) {
2727
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2728
+ }
2729
+
2730
+ //#endregion
2731
+ //#region src/site-context/entity-resolve.ts
2732
+ const ULID_PATTERN = /^[0-9A-HJKMNP-TV-Z]{26}$/;
2733
+ const DISPLAY_FALLBACK_FIELDS = [
2734
+ "title",
2735
+ "name",
2736
+ "headline",
2737
+ "label",
2738
+ "question"
2739
+ ];
2740
+ const DISPLAY_FIELD_TYPES = new Set([
2741
+ "string",
2742
+ "text",
2743
+ "url",
2744
+ "slug",
2745
+ "select"
2746
+ ]);
2747
+ const ENTITY_TYPES = [
2748
+ "content",
2749
+ "collection",
2750
+ "plugin",
2751
+ "taxonomy",
2752
+ "menu"
2753
+ ];
2754
+ function isDisplayField(field) {
2755
+ return DISPLAY_FIELD_TYPES.has(field.type);
2756
+ }
2757
+ function uniqueValues(values) {
2758
+ return [...new Set(values)];
2759
+ }
2760
+ function compareOptionalIsoDesc(a, b) {
2761
+ if (a && b) return b.localeCompare(a);
2762
+ if (a) return -1;
2763
+ if (b) return 1;
2764
+ return 0;
2765
+ }
2766
+ function normalizeDisplayMatch(value) {
2767
+ return normalizeEntityAlias(value);
2768
+ }
2769
+ function candidateIdentity(candidate) {
2770
+ return candidate.collection ? `${candidate.entityType}:${candidate.collection}:${candidate.entityId}` : `${candidate.entityType}:${candidate.entityId}`;
2771
+ }
2772
+ function sortCandidates(candidates) {
2773
+ return candidates.toSorted((left, right) => {
2774
+ const reasonRank = matchReasonRank(left.matchReason) - matchReasonRank(right.matchReason);
2775
+ if (reasonRank !== 0) return reasonRank;
2776
+ const providerRank = (left.providerRank ?? Number.MAX_SAFE_INTEGER) - (right.providerRank ?? Number.MAX_SAFE_INTEGER);
2777
+ if (providerRank !== 0) return providerRank;
2778
+ const updatedAtRank = compareOptionalIsoDesc(left.updatedAt, right.updatedAt);
2779
+ if (updatedAtRank !== 0) return updatedAtRank;
2780
+ const createdAtRank = compareOptionalIsoDesc(left.createdAt, right.createdAt);
2781
+ if (createdAtRank !== 0) return createdAtRank;
2782
+ const labelRank = left.label.localeCompare(right.label);
2783
+ if (labelRank !== 0) return labelRank;
2784
+ const keyRank = left.entityKey.localeCompare(right.entityKey);
2785
+ if (keyRank !== 0) return keyRank;
2786
+ return left.entityId.localeCompare(right.entityId);
2787
+ });
2788
+ }
2789
+ function matchReasonRank(reason) {
2790
+ switch (reason) {
2791
+ case "exact_id": return 0;
2792
+ case "exact_key": return 1;
2793
+ case "exact_slug": return 2;
2794
+ case "alias": return 3;
2795
+ case "display_exact": return 4;
2796
+ case "display_partial": return 5;
2797
+ case "search_provider": return 6;
2798
+ }
2799
+ }
2800
+ function contentDisplayLabel(item, displayFields) {
2801
+ for (const field of displayFields) {
2802
+ const value = item.data[field];
2803
+ if (typeof value === "string" && value.trim().length > 0) return value;
2804
+ }
2805
+ if (typeof item.data.title === "string" && item.data.title.trim().length > 0) return item.data.title;
2806
+ if (typeof item.data.name === "string" && item.data.name.trim().length > 0) return item.data.name;
2807
+ if (item.slug) return item.slug;
2808
+ return item.id;
2809
+ }
2810
+ var EntityResolver = class {
2811
+ registry;
2812
+ contentRepository;
2813
+ aliasRepository;
2814
+ collectionContextCache = /* @__PURE__ */ new Map();
2815
+ constructor(options) {
2816
+ this.options = options;
2817
+ this.registry = new SchemaRegistry(options.db);
2818
+ this.contentRepository = new ContentRepository(options.db);
2819
+ this.aliasRepository = new EntityAliasRepository(options.db);
2820
+ }
2821
+ async resolve(input) {
2822
+ const query = input.query.trim();
2823
+ if (!query) return {
2824
+ status: "not_found",
2825
+ suggestion: "Provide a non-empty query."
2826
+ };
2827
+ const entityTypes = input.entityTypes?.length ? uniqueValues(input.entityTypes) : ENTITY_TYPES;
2828
+ const limit = Math.min(Math.max(input.limit ?? 5, 1), 20);
2829
+ const exactIdOrKey = await this.resolveExactIdOrKey(query, entityTypes, input.collection);
2830
+ const idOrKeyResult = this.finalizeTier(exactIdOrKey, query, limit, entityTypes);
2831
+ if (idOrKeyResult) return idOrKeyResult;
2832
+ const exactSlug = await this.resolveExactSlug(query, entityTypes, input.collection);
2833
+ const slugResult = this.finalizeTier(exactSlug, query, limit, entityTypes);
2834
+ if (slugResult) return slugResult;
2835
+ const alias = await this.resolveAlias(query, entityTypes, input.collection, limit);
2836
+ const aliasResult = this.finalizeTier(alias, query, limit, entityTypes);
2837
+ if (aliasResult) return aliasResult;
2838
+ const displayExact = await this.resolveDisplay(query, entityTypes, input.collection, true, limit);
2839
+ const displayExactResult = this.finalizeTier(displayExact, query, limit, entityTypes);
2840
+ if (displayExactResult) return displayExactResult;
2841
+ const displayPartial = await this.resolveDisplay(query, entityTypes, input.collection, false, limit);
2842
+ const displayPartialResult = this.finalizeTier(displayPartial, query, limit, entityTypes);
2843
+ if (displayPartialResult) return displayPartialResult;
2844
+ const searchMatches = await this.resolveSearchProvider(query, entityTypes, input.collection, limit);
2845
+ const searchResult = this.finalizeTier(searchMatches, query, limit, entityTypes);
2846
+ if (searchResult) return searchResult;
2847
+ return {
2848
+ status: "not_found",
2849
+ suggestion: `No ${describeEntityTypes(entityTypes)} found for "${query}". Check the ID or slug, add an alias, or use a more specific label.`
2850
+ };
2851
+ }
2852
+ finalizeTier(candidates, query, limit, entityTypes) {
2853
+ if (candidates.length === 0) return null;
2854
+ const sorted = dedupeCandidates(candidates).slice(0, limit);
2855
+ if (sorted.length === 1) return {
2856
+ status: "resolved",
2857
+ resolved: stripInternalCandidate(sorted[0])
2858
+ };
2859
+ return {
2860
+ status: "ambiguous",
2861
+ candidates: sorted.map(stripInternalCandidate),
2862
+ suggestion: `Found ${sorted.length} ${describeEntityTypes(entityTypes)} matches for "${query}". Narrow with entity_types or collection before proceeding.`
2863
+ };
2864
+ }
2865
+ async resolveExactIdOrKey(query, entityTypes, collectionHint) {
2866
+ const candidates = [];
2867
+ const [contentCollections, collectionContexts] = await Promise.all([entityTypes.includes("content") ? this.listContentCollections(collectionHint) : Promise.resolve([]), entityTypes.includes("collection") ? this.listAllCollectionContexts() : Promise.resolve([])]);
2868
+ if (entityTypes.includes("content")) for (const context of contentCollections) {
2869
+ const item = await this.contentRepository.findById(context.collection.slug, query);
2870
+ if (!item) continue;
2871
+ candidates.push(this.contentCandidate(item, context, 1, "exact_id"));
2872
+ }
2873
+ const [menus, taxonomies, plugins] = await Promise.all([
2874
+ entityTypes.includes("menu") ? this.listMenus() : Promise.resolve([]),
2875
+ entityTypes.includes("taxonomy") ? this.listTaxonomies() : Promise.resolve([]),
2876
+ entityTypes.includes("plugin") ? this.listPlugins() : Promise.resolve([])
2877
+ ]);
2878
+ if (entityTypes.includes("collection")) {
2879
+ for (const context of collectionContexts) if (ULID_PATTERN.test(query) && context.collection.id === query) {
2880
+ candidates.push(collectionCandidate(context.collection, 1, "exact_id"));
2881
+ continue;
2882
+ }
2883
+ }
2884
+ if (entityTypes.includes("menu")) for (const menu of menus) {
2885
+ if (ULID_PATTERN.test(query) && menu.id === query) {
2886
+ candidates.push(menuCandidate(menu, 1, "exact_id"));
2887
+ continue;
2888
+ }
2889
+ if (menu.name === query) candidates.push(menuCandidate(menu, 1, "exact_key"));
2890
+ }
2891
+ if (entityTypes.includes("taxonomy")) for (const taxonomy of taxonomies) {
2892
+ if (ULID_PATTERN.test(query) && taxonomy.id === query) {
2893
+ candidates.push(taxonomyCandidate(taxonomy, 1, "exact_id"));
2894
+ continue;
2895
+ }
2896
+ if (taxonomy.name === query) candidates.push(taxonomyCandidate(taxonomy, 1, "exact_key"));
2897
+ }
2898
+ if (entityTypes.includes("plugin")) {
2899
+ for (const plugin of plugins) if (plugin.id === query) candidates.push(pluginCandidate(plugin, 1, "exact_key"));
2900
+ }
2901
+ return candidates;
2902
+ }
2903
+ async resolveExactSlug(query, entityTypes, collectionHint) {
2904
+ const candidates = [];
2905
+ const [contentCollections, collectionContexts] = await Promise.all([entityTypes.includes("content") ? this.listContentCollections(collectionHint) : Promise.resolve([]), entityTypes.includes("collection") ? this.listAllCollectionContexts() : Promise.resolve([])]);
2906
+ if (entityTypes.includes("collection")) {
2907
+ for (const context of collectionContexts) if (context.collection.slug === query) candidates.push(collectionCandidate(context.collection, 2, "exact_slug"));
2908
+ }
2909
+ if (entityTypes.includes("content")) for (const context of contentCollections) {
2910
+ const item = await this.contentRepository.findBySlug(context.collection.slug, query);
2911
+ if (!item) continue;
2912
+ candidates.push(this.contentCandidate(item, context, 2, "exact_slug"));
2913
+ }
2914
+ return candidates;
2915
+ }
2916
+ async resolveAlias(query, entityTypes, collectionHint, limit) {
2917
+ const matches = await this.aliasRepository.findByNormalizedAlias({
2918
+ normalizedAlias: normalizeEntityAlias(query),
2919
+ entityTypes,
2920
+ collectionSlug: collectionHint,
2921
+ limit
2922
+ });
2923
+ return this.hydrateAliasMatches(matches);
2924
+ }
2925
+ async hydrateAliasMatches(matches) {
2926
+ const candidates = [];
2927
+ for (const match of matches) switch (match.entityType) {
2928
+ case "content": {
2929
+ if (!match.collectionSlug) continue;
2930
+ const context = await this.getCollectionContext(match.collectionSlug);
2931
+ if (!context) continue;
2932
+ const item = await this.contentRepository.findById(match.collectionSlug, match.entityId);
2933
+ if (!item) continue;
2934
+ candidates.push(this.contentCandidate(item, context, 3, "alias"));
2935
+ break;
2936
+ }
2937
+ case "collection": {
2938
+ const collection = (await this.listAllCollectionContexts()).find((item) => item.collection.id === match.entityId)?.collection;
2939
+ if (collection) candidates.push(collectionCandidate(collection, 3, "alias"));
2940
+ break;
2941
+ }
2942
+ case "menu": {
2943
+ const menu = await this.options.db.selectFrom("_dineway_menus").selectAll().where("id", "=", match.entityId).executeTakeFirst();
2944
+ if (menu) candidates.push(menuCandidate(menu, 3, "alias"));
2945
+ break;
2946
+ }
2947
+ case "taxonomy": {
2948
+ const taxonomy = await this.options.db.selectFrom("_dineway_taxonomy_defs").selectAll().where("id", "=", match.entityId).executeTakeFirst();
2949
+ if (taxonomy) candidates.push(taxonomyCandidate(taxonomy, 3, "alias"));
2950
+ break;
2951
+ }
2952
+ case "plugin": {
2953
+ const plugin = (await this.listPlugins()).find((item) => item.id === match.entityId);
2954
+ if (plugin) candidates.push(pluginCandidate(plugin, 3, "alias"));
2955
+ break;
2956
+ }
2957
+ }
2958
+ return candidates;
2959
+ }
2960
+ async resolveDisplay(query, entityTypes, collectionHint, exact, limit) {
2961
+ const candidates = [];
2962
+ const normalizedQuery = normalizeDisplayMatch(query);
2963
+ const [contentCollections, collectionContexts, menus, taxonomies, plugins] = await Promise.all([
2964
+ entityTypes.includes("content") ? this.listContentCollections(collectionHint) : Promise.resolve([]),
2965
+ entityTypes.includes("collection") ? this.listAllCollectionContexts() : Promise.resolve([]),
2966
+ entityTypes.includes("menu") ? this.listMenus() : Promise.resolve([]),
2967
+ entityTypes.includes("taxonomy") ? this.listTaxonomies() : Promise.resolve([]),
2968
+ entityTypes.includes("plugin") ? this.listPlugins() : Promise.resolve([])
2969
+ ]);
2970
+ if (entityTypes.includes("collection")) {
2971
+ for (const context of collectionContexts) if (matchesDisplayValues([context.collection.label, context.collection.labelSingular ?? ""], normalizedQuery, exact)) candidates.push(collectionCandidate(context.collection, 4, exact ? "display_exact" : "display_partial"));
2972
+ }
2973
+ if (entityTypes.includes("menu")) {
2974
+ for (const menu of menus) if (matchesDisplayValues([menu.label], normalizedQuery, exact)) candidates.push(menuCandidate(menu, 4, exact ? "display_exact" : "display_partial"));
2975
+ }
2976
+ if (entityTypes.includes("taxonomy")) {
2977
+ for (const taxonomy of taxonomies) if (matchesDisplayValues([taxonomy.label, taxonomy.label_singular ?? ""], normalizedQuery, exact)) candidates.push(taxonomyCandidate(taxonomy, 4, exact ? "display_exact" : "display_partial"));
2978
+ }
2979
+ if (entityTypes.includes("plugin")) {
2980
+ for (const plugin of plugins) if (matchesDisplayValues([plugin.name], normalizedQuery, exact)) candidates.push(pluginCandidate(plugin, 4, exact ? "display_exact" : "display_partial"));
2981
+ }
2982
+ if (entityTypes.includes("content")) for (const context of contentCollections) {
2983
+ const matches = await this.resolveContentDisplay(context, normalizedQuery, exact, limit);
2984
+ candidates.push(...matches);
2985
+ }
2986
+ return candidates;
2987
+ }
2988
+ async resolveContentDisplay(context, normalizedQuery, exact, limit) {
2989
+ const candidates = [];
2990
+ const tableName = `ec_${context.collection.slug}`;
2991
+ validateIdentifier(context.collection.slug, "content collection slug");
2992
+ validateIdentifier(tableName, "content table name");
2993
+ for (const fieldSlug of context.displayFields) {
2994
+ validateIdentifier(fieldSlug, "content display field");
2995
+ const fieldRef = sql.ref(fieldSlug);
2996
+ const likePattern = `%${normalizedQuery}%`;
2997
+ const result = await sql`
2998
+ SELECT
2999
+ id,
3000
+ slug,
3001
+ status,
3002
+ locale,
3003
+ created_at,
3004
+ updated_at
3005
+ FROM ${sql.ref(tableName)}
3006
+ WHERE deleted_at IS NULL
3007
+ AND ${exact ? sql`lower(${fieldRef}) = ${normalizedQuery}` : sql`lower(${fieldRef}) LIKE ${likePattern}`}
3008
+ ORDER BY updated_at DESC, created_at DESC, id ASC
3009
+ LIMIT ${limit}
3010
+ `.execute(this.options.db);
3011
+ for (const row of result.rows) {
3012
+ const item = await this.contentRepository.findById(context.collection.slug, row.id);
3013
+ if (!item) continue;
3014
+ candidates.push(this.contentCandidate(item, context, 4, exact ? "display_exact" : "display_partial"));
3015
+ }
3016
+ }
3017
+ return candidates;
3018
+ }
3019
+ async resolveSearchProvider(query, entityTypes, collectionHint, limit) {
3020
+ if (!entityTypes.includes("content")) return [];
3021
+ const candidates = [];
3022
+ const collections = await this.listContentCollections(collectionHint);
3023
+ for (const context of collections) {
3024
+ if (context.searchEnabled) {
3025
+ const results = await searchCollection(this.options.db, context.collection.slug, query, { limit });
3026
+ let providerRank = 0;
3027
+ for (const result of results.items) {
3028
+ providerRank += 1;
3029
+ const item = await this.contentRepository.findById(context.collection.slug, result.id);
3030
+ if (!item) continue;
3031
+ candidates.push({
3032
+ ...this.contentCandidate(item, context, 5, "search_provider"),
3033
+ providerRank
3034
+ });
3035
+ }
3036
+ continue;
3037
+ }
3038
+ candidates.push(...await this.resolveFallbackSearchProvider(context, query, limit));
3039
+ }
3040
+ return candidates;
3041
+ }
3042
+ async resolveFallbackSearchProvider(context, query, limit) {
3043
+ if (context.searchFields.length === 0) return [];
3044
+ const tableName = `ec_${context.collection.slug}`;
3045
+ validateIdentifier(context.collection.slug, "content collection slug");
3046
+ validateIdentifier(tableName, "content table name");
3047
+ const trimmedQuery = query.trim().toLowerCase();
3048
+ if (!trimmedQuery) return [];
3049
+ const likePattern = `%${trimmedQuery}%`;
3050
+ const searchConditions = context.searchFields.map((fieldSlug) => {
3051
+ validateIdentifier(fieldSlug, "content search field");
3052
+ return sql`lower(cast(${sql.ref(fieldSlug)} as text)) LIKE ${likePattern}`;
3053
+ });
3054
+ const result = await sql`
3055
+ SELECT
3056
+ id,
3057
+ slug,
3058
+ status,
3059
+ locale,
3060
+ created_at,
3061
+ updated_at
3062
+ FROM ${sql.ref(tableName)}
3063
+ WHERE deleted_at IS NULL
3064
+ AND (${sql.join(searchConditions, sql` OR `)})
3065
+ ORDER BY updated_at DESC, created_at DESC, id ASC
3066
+ LIMIT ${limit}
3067
+ `.execute(this.options.db);
3068
+ const candidates = [];
3069
+ for (const row of result.rows) {
3070
+ const item = await this.contentRepository.findById(context.collection.slug, row.id);
3071
+ if (!item) continue;
3072
+ candidates.push(this.contentCandidate(item, context, 5, "search_provider"));
3073
+ }
3074
+ return candidates;
3075
+ }
3076
+ async listAllCollectionContexts() {
3077
+ return (await Promise.all((await this.registry.listCollections()).map((collection) => this.getCollectionContext(collection.slug)))).filter((value) => value !== null);
3078
+ }
3079
+ async listContentCollections(collectionHint) {
3080
+ if (collectionHint) {
3081
+ const context = await this.getCollectionContext(collectionHint);
3082
+ return context ? [context] : [];
3083
+ }
3084
+ return this.listAllCollectionContexts();
3085
+ }
3086
+ async getCollectionContext(slug) {
3087
+ let promise = this.collectionContextCache.get(slug);
3088
+ if (!promise) {
3089
+ promise = this.buildCollectionContext(slug);
3090
+ this.collectionContextCache.set(slug, promise);
3091
+ }
3092
+ return promise;
3093
+ }
3094
+ async buildCollectionContext(slug) {
3095
+ const collection = await this.registry.getCollectionWithFields(slug);
3096
+ if (!collection) return null;
3097
+ const ftsManager = new FTSManager(this.options.db);
3098
+ const searchableFields = await ftsManager.getSearchableFields(slug);
3099
+ const searchConfig = await ftsManager.getSearchConfig(slug);
3100
+ return {
3101
+ collection,
3102
+ displayFields: resolveDisplayFields(collection, searchableFields, searchConfig?.weights),
3103
+ searchFields: searchableFields,
3104
+ searchEnabled: searchConfig?.enabled === true
3105
+ };
3106
+ }
3107
+ async listMenus() {
3108
+ return this.options.db.selectFrom("_dineway_menus").selectAll().execute();
3109
+ }
3110
+ async listTaxonomies() {
3111
+ return this.options.db.selectFrom("_dineway_taxonomy_defs").selectAll().execute();
3112
+ }
3113
+ async listPlugins() {
3114
+ const result = await handlePluginList(this.options.db, this.options.handlers.configuredPlugins, this.options.handlers.config.marketplace);
3115
+ return result.success ? result.data?.items ?? [] : [];
3116
+ }
3117
+ contentCandidate(item, context, matchTier, matchReason) {
3118
+ return {
3119
+ entityType: "content",
3120
+ entityId: item.id,
3121
+ entityKey: item.slug ?? item.id,
3122
+ label: contentDisplayLabel(item, context.displayFields),
3123
+ matchTier,
3124
+ matchReason,
3125
+ collection: context.collection.slug,
3126
+ slug: item.slug,
3127
+ status: item.status,
3128
+ locale: item.locale,
3129
+ updatedAt: item.updatedAt,
3130
+ createdAt: item.createdAt
3131
+ };
3132
+ }
3133
+ };
3134
+ function resolveDisplayFields(collection, searchableFields, weights) {
3135
+ const fieldsBySlug = new Map(collection.fields.map((field) => [field.slug, field]));
3136
+ const weightedFields = Object.entries(weights ?? {}).filter(([slug]) => {
3137
+ const field = fieldsBySlug.get(slug);
3138
+ return !!field && isDisplayField(field);
3139
+ }).toSorted((left, right) => right[1] - left[1]).map(([slug]) => slug);
3140
+ const configuredSearchFields = searchableFields.filter((slug) => {
3141
+ const field = fieldsBySlug.get(slug);
3142
+ return !!field && isDisplayField(field);
3143
+ });
3144
+ const fallbackFields = DISPLAY_FALLBACK_FIELDS.filter((slug) => {
3145
+ const field = fieldsBySlug.get(slug);
3146
+ return !!field && isDisplayField(field);
3147
+ });
3148
+ const remainingDisplayFields = collection.fields.filter((field) => isDisplayField(field)).map((field) => field.slug);
3149
+ return uniqueValues([
3150
+ ...weightedFields,
3151
+ ...configuredSearchFields,
3152
+ ...fallbackFields,
3153
+ ...remainingDisplayFields
3154
+ ]);
3155
+ }
3156
+ function dedupeCandidates(candidates) {
3157
+ const sorted = sortCandidates(candidates);
3158
+ const seen = /* @__PURE__ */ new Set();
3159
+ const deduped = [];
3160
+ for (const candidate of sorted) {
3161
+ const identity = candidateIdentity(candidate);
3162
+ if (seen.has(identity)) continue;
3163
+ seen.add(identity);
3164
+ deduped.push(candidate);
3165
+ }
3166
+ return deduped;
3167
+ }
3168
+ function stripInternalCandidate(candidate) {
3169
+ const { providerRank: _providerRank, ...publicCandidate } = candidate;
3170
+ return publicCandidate;
3171
+ }
3172
+ function collectionCandidate(collection, matchTier, matchReason) {
3173
+ return {
3174
+ entityType: "collection",
3175
+ entityId: collection.id,
3176
+ entityKey: collection.slug,
3177
+ label: collection.labelSingular ?? collection.label,
3178
+ matchTier,
3179
+ matchReason,
3180
+ slug: collection.slug,
3181
+ updatedAt: collection.updatedAt,
3182
+ createdAt: collection.createdAt
3183
+ };
3184
+ }
3185
+ function menuCandidate(menu, matchTier, matchReason) {
3186
+ return {
3187
+ entityType: "menu",
3188
+ entityId: menu.id,
3189
+ entityKey: menu.name,
3190
+ label: menu.label,
3191
+ matchTier,
3192
+ matchReason,
3193
+ updatedAt: menu.updated_at,
3194
+ createdAt: menu.created_at
3195
+ };
3196
+ }
3197
+ function taxonomyCandidate(taxonomy, matchTier, matchReason) {
3198
+ return {
3199
+ entityType: "taxonomy",
3200
+ entityId: taxonomy.id,
3201
+ entityKey: taxonomy.name,
3202
+ label: taxonomy.label_singular ?? taxonomy.label,
3203
+ matchTier,
3204
+ matchReason,
3205
+ createdAt: taxonomy.created_at
3206
+ };
3207
+ }
3208
+ function pluginCandidate(plugin, matchTier, matchReason) {
3209
+ const updatedAt = plugin.activatedAt ?? plugin.installedAt ?? plugin.deactivatedAt;
3210
+ return {
3211
+ entityType: "plugin",
3212
+ entityId: plugin.id,
3213
+ entityKey: plugin.id,
3214
+ label: plugin.name,
3215
+ matchTier,
3216
+ matchReason,
3217
+ status: plugin.status,
3218
+ updatedAt,
3219
+ createdAt: plugin.installedAt
3220
+ };
3221
+ }
3222
+ function matchesDisplayValues(values, normalizedQuery, exact) {
3223
+ return values.some((value) => {
3224
+ const normalizedValue = normalizeDisplayMatch(value);
3225
+ return exact ? normalizedValue === normalizedQuery : normalizedValue.includes(normalizedQuery);
3226
+ });
3227
+ }
3228
+ function describeEntityTypes(entityTypes) {
3229
+ if (entityTypes.length === 1) return entityTypes[0];
3230
+ if (entityTypes.length === ENTITY_TYPES.length) return "entities";
3231
+ return entityTypes.join(", ");
3232
+ }
3233
+
3234
+ //#endregion
3235
+ //#region src/site-context/expertise.ts
3236
+ var ActorExpertiseService = class {
3237
+ db;
3238
+ constructor(options) {
3239
+ this.db = options.db;
3240
+ }
3241
+ async findByScope(input) {
3242
+ assertExperimentalSiteContextWorkflowsEnabled();
3243
+ const parsed = parseSiteBriefingScope(input.scope);
3244
+ const includeInherited = input.includeInherited !== false;
3245
+ const scopes = includeInherited ? parsed.ancestors : [parsed.scope];
3246
+ const limit = clampLimit$1(input.limit);
3247
+ const contributions = await this.collectSignals({ scopes });
3248
+ const experts = Array.from(aggregateByActor(contributions).values(), (entry) => accumulatorToActorSummary(entry)).toSorted(compareActorSummaries).slice(0, limit);
3249
+ return {
3250
+ mode: "by_scope",
3251
+ scope: {
3252
+ requested: input.scope,
3253
+ resolved: parsed.scope,
3254
+ type: parsed.type,
3255
+ ancestors: parsed.ancestors,
3256
+ scopes,
3257
+ includeInherited,
3258
+ collection: parsed.collection,
3259
+ contentId: parsed.contentId,
3260
+ pluginId: parsed.pluginId
3261
+ },
3262
+ experts
3263
+ };
3264
+ }
3265
+ async findByActor(input) {
3266
+ assertExperimentalSiteContextWorkflowsEnabled();
3267
+ const contributions = await this.collectSignals({
3268
+ actorType: input.actorType,
3269
+ actorId: input.actorId
3270
+ });
3271
+ const scopes = Array.from(aggregateByScope(contributions).values(), (entry) => accumulatorToScopeSummary(entry)).toSorted(compareScopeSummaries);
3272
+ const limitedScopes = input.limit === void 0 ? scopes : scopes.slice(0, clampLimit$1(input.limit));
3273
+ return {
3274
+ mode: "by_actor",
3275
+ actor: {
3276
+ actorType: input.actorType,
3277
+ actorId: input.actorId
3278
+ },
3279
+ counts: sumCounts(limitedScopes.map((item) => item.counts)),
3280
+ scopes: limitedScopes
3281
+ };
3282
+ }
3283
+ async collectSignals(query) {
3284
+ if (query.scopes && query.scopes.length === 0) return [];
3285
+ const [activitySignals, contextSignals, requestedReviewSignals, resolvedReviewSignals] = await Promise.all([
3286
+ this.listActivitySignals(query),
3287
+ this.listContextSignals(query),
3288
+ this.listRequestedReviewSignals(query),
3289
+ this.listResolvedReviewSignals(query)
3290
+ ]);
3291
+ return [
3292
+ ...activitySignals,
3293
+ ...contextSignals,
3294
+ ...requestedReviewSignals,
3295
+ ...resolvedReviewSignals
3296
+ ];
3297
+ }
3298
+ async listActivitySignals(query) {
3299
+ let q = this.db.selectFrom("_dineway_activity_log").select([
3300
+ "actor_type as actorType",
3301
+ "actor_id as actorId",
3302
+ "scope",
3303
+ "action_type as actionType",
3304
+ "created_at as contributedAt"
3305
+ ]);
3306
+ if (query.scopes) q = q.where("scope", "in", query.scopes);
3307
+ if (query.actorType) q = q.where("actor_type", "=", query.actorType);
3308
+ if (query.actorId) q = q.where("actor_id", "=", query.actorId);
3309
+ return (await q.execute()).map((row) => ({
3310
+ actorType: row.actorType,
3311
+ actorId: row.actorId,
3312
+ scope: row.scope,
3313
+ type: "activity",
3314
+ actionType: row.actionType,
3315
+ contributedAt: row.contributedAt
3316
+ }));
3317
+ }
3318
+ async listContextSignals(query) {
3319
+ let q = this.db.selectFrom("_dineway_context_entries").select([
3320
+ "created_by_actor_type as actorType",
3321
+ "created_by_actor_id as actorId",
3322
+ "scope",
3323
+ "context_type as contextType",
3324
+ "created_at as contributedAt"
3325
+ ]).where("is_current", "=", 1);
3326
+ if (query.scopes) q = q.where("scope", "in", query.scopes);
3327
+ if (query.actorType) q = q.where("created_by_actor_type", "=", query.actorType);
3328
+ if (query.actorId) q = q.where("created_by_actor_id", "=", query.actorId);
3329
+ return (await q.execute()).map((row) => ({
3330
+ actorType: row.actorType,
3331
+ actorId: row.actorId,
3332
+ scope: row.scope,
3333
+ type: "context",
3334
+ contextType: row.contextType,
3335
+ contributedAt: row.contributedAt
3336
+ }));
3337
+ }
3338
+ async listRequestedReviewSignals(query) {
3339
+ let q = this.db.selectFrom("_dineway_review_requests").select([
3340
+ "requested_by_actor_type as actorType",
3341
+ "requested_by_actor_id as actorId",
3342
+ "scope",
3343
+ "action_type as actionType",
3344
+ "created_at as contributedAt"
3345
+ ]);
3346
+ if (query.scopes) q = q.where("scope", "in", query.scopes);
3347
+ if (query.actorType) q = q.where("requested_by_actor_type", "=", query.actorType);
3348
+ if (query.actorId) q = q.where("requested_by_actor_id", "=", query.actorId);
3349
+ return (await q.execute()).map((row) => ({
3350
+ actorType: row.actorType,
3351
+ actorId: row.actorId,
3352
+ scope: row.scope,
3353
+ type: "review",
3354
+ actionType: row.actionType,
3355
+ contributedAt: row.contributedAt
3356
+ }));
3357
+ }
3358
+ async listResolvedReviewSignals(query) {
3359
+ let q = this.db.selectFrom("_dineway_review_requests").select([
3360
+ "resolved_by_actor_type as actorType",
3361
+ "resolved_by_actor_id as actorId",
3362
+ "scope",
3363
+ "action_type as actionType",
3364
+ "resolved_at as contributedAt"
3365
+ ]).where("resolved_by_actor_type", "is not", null).where("resolved_by_actor_id", "is not", null).where("resolved_at", "is not", null);
3366
+ if (query.scopes) q = q.where("scope", "in", query.scopes);
3367
+ if (query.actorType) q = q.where("resolved_by_actor_type", "=", query.actorType);
3368
+ if (query.actorId) q = q.where("resolved_by_actor_id", "=", query.actorId);
3369
+ return (await q.execute()).map((row) => ({
3370
+ actorType: row.actorType,
3371
+ actorId: row.actorId,
3372
+ scope: row.scope,
3373
+ type: "review",
3374
+ actionType: row.actionType,
3375
+ contributedAt: row.contributedAt
3376
+ }));
3377
+ }
3378
+ };
3379
+ function aggregateByActor(signals) {
3380
+ const result = /* @__PURE__ */ new Map();
3381
+ for (const signal of signals) {
3382
+ const key = `${signal.actorType}:${signal.actorId}`;
3383
+ const accumulator = result.get(key) ?? createAccumulator({
3384
+ actorType: signal.actorType,
3385
+ actorId: signal.actorId,
3386
+ scope: signal.scope,
3387
+ contributedAt: signal.contributedAt
3388
+ });
3389
+ applySignal(accumulator, signal);
3390
+ result.set(key, accumulator);
3391
+ }
3392
+ return result;
3393
+ }
3394
+ function aggregateByScope(signals) {
3395
+ const result = /* @__PURE__ */ new Map();
3396
+ for (const signal of signals) {
3397
+ const key = signal.scope;
3398
+ const accumulator = result.get(key) ?? createAccumulator({
3399
+ actorType: signal.actorType,
3400
+ actorId: signal.actorId,
3401
+ scope: signal.scope,
3402
+ contributedAt: signal.contributedAt
3403
+ });
3404
+ applySignal(accumulator, signal);
3405
+ result.set(key, accumulator);
3406
+ }
3407
+ return result;
3408
+ }
3409
+ function createAccumulator(input) {
3410
+ return {
3411
+ actorType: input.actorType,
3412
+ actorId: input.actorId,
3413
+ scope: input.scope,
3414
+ lastContributedAt: input.contributedAt,
3415
+ contextEntryCount: 0,
3416
+ reviewRequestCount: 0,
3417
+ activityCount: 0,
3418
+ contextTypes: /* @__PURE__ */ new Set(),
3419
+ actionTypes: /* @__PURE__ */ new Set(),
3420
+ reviewActionTypes: /* @__PURE__ */ new Set(),
3421
+ matchedScopes: new Set([input.scope])
3422
+ };
3423
+ }
3424
+ function applySignal(accumulator, signal) {
3425
+ accumulator.lastContributedAt = maxIsoTimestamp(accumulator.lastContributedAt, signal.contributedAt);
3426
+ accumulator.matchedScopes.add(signal.scope);
3427
+ switch (signal.type) {
3428
+ case "activity":
3429
+ accumulator.activityCount += 1;
3430
+ if (signal.actionType) accumulator.actionTypes.add(signal.actionType);
3431
+ return;
3432
+ case "context":
3433
+ accumulator.contextEntryCount += 1;
3434
+ if (signal.contextType) accumulator.contextTypes.add(signal.contextType);
3435
+ return;
3436
+ case "review":
3437
+ accumulator.reviewRequestCount += 1;
3438
+ if (signal.actionType) accumulator.reviewActionTypes.add(signal.actionType);
3439
+ return;
3440
+ }
3441
+ }
3442
+ function accumulatorToActorSummary(entry) {
3443
+ return {
3444
+ actorType: entry.actorType,
3445
+ actorId: entry.actorId,
3446
+ lastContributedAt: entry.lastContributedAt,
3447
+ counts: toCounts(entry),
3448
+ contextTypes: [...entry.contextTypes].toSorted(),
3449
+ actionTypes: [...entry.actionTypes].toSorted(),
3450
+ reviewActionTypes: [...entry.reviewActionTypes].toSorted(),
3451
+ scopes: [...entry.matchedScopes].toSorted()
3452
+ };
3453
+ }
3454
+ function accumulatorToScopeSummary(entry) {
3455
+ const parsed = parseSiteBriefingScope(entry.scope);
3456
+ return {
3457
+ scope: entry.scope,
3458
+ scopeInfo: {
3459
+ scope: parsed.scope,
3460
+ type: parsed.type,
3461
+ collection: parsed.collection,
3462
+ contentId: parsed.contentId,
3463
+ pluginId: parsed.pluginId
3464
+ },
3465
+ lastContributedAt: entry.lastContributedAt,
3466
+ counts: toCounts(entry),
3467
+ contextTypes: [...entry.contextTypes].toSorted(),
3468
+ actionTypes: [...entry.actionTypes].toSorted(),
3469
+ reviewActionTypes: [...entry.reviewActionTypes].toSorted()
3470
+ };
3471
+ }
3472
+ function toCounts(entry) {
3473
+ const total = entry.contextEntryCount + entry.reviewRequestCount + entry.activityCount;
3474
+ return {
3475
+ contextEntries: entry.contextEntryCount,
3476
+ reviewRequests: entry.reviewRequestCount,
3477
+ activities: entry.activityCount,
3478
+ total
3479
+ };
3480
+ }
3481
+ function compareActorSummaries(left, right) {
3482
+ return compareCounts(left.counts, right.counts) || compareIsoDesc(left.lastContributedAt, right.lastContributedAt) || left.actorType.localeCompare(right.actorType) || left.actorId.localeCompare(right.actorId);
3483
+ }
3484
+ function compareScopeSummaries(left, right) {
3485
+ return compareCounts(left.counts, right.counts) || compareIsoDesc(left.lastContributedAt, right.lastContributedAt) || left.scope.localeCompare(right.scope);
3486
+ }
3487
+ function compareCounts(left, right) {
3488
+ return right.contextEntries - left.contextEntries || right.reviewRequests - left.reviewRequests || right.activities - left.activities || right.total - left.total;
3489
+ }
3490
+ function compareIsoDesc(left, right) {
3491
+ return right.localeCompare(left);
3492
+ }
3493
+ function sumCounts(values) {
3494
+ return values.reduce((accumulator, value) => ({
3495
+ contextEntries: accumulator.contextEntries + value.contextEntries,
3496
+ reviewRequests: accumulator.reviewRequests + value.reviewRequests,
3497
+ activities: accumulator.activities + value.activities,
3498
+ total: accumulator.total + value.total
3499
+ }), {
3500
+ contextEntries: 0,
3501
+ reviewRequests: 0,
3502
+ activities: 0,
3503
+ total: 0
3504
+ });
3505
+ }
3506
+ function maxIsoTimestamp(left, right) {
3507
+ return left.localeCompare(right) >= 0 ? left : right;
3508
+ }
3509
+ function clampLimit$1(value) {
3510
+ return Math.min(Math.max(1, value ?? 10), 100);
3511
+ }
3512
+
3513
+ //#endregion
3514
+ //#region src/database/repositories/handoff-snapshots.ts
3515
+ var HandoffSnapshotRepository = class {
3516
+ constructor(db) {
3517
+ this.db = db;
3518
+ }
3519
+ async create(input) {
3520
+ const id = ulid();
3521
+ await this.db.insertInto("_dineway_handoff_snapshots").values(toInsertableHandoffSnapshot(id, input)).execute();
3522
+ return this.findById(id).then((snapshot) => {
3523
+ if (!snapshot) throw new Error("Failed to create handoff snapshot");
3524
+ return snapshot;
3525
+ });
3526
+ }
3527
+ async findById(id) {
3528
+ const row = await this.db.selectFrom("_dineway_handoff_snapshots").selectAll().where("id", "=", id).executeTakeFirst();
3529
+ return row ? rowToHandoffSnapshot(row) : null;
3530
+ }
3531
+ async markResumed(id, resumedAt) {
3532
+ const value = resumedAt ?? (/* @__PURE__ */ new Date()).toISOString();
3533
+ await this.db.updateTable("_dineway_handoff_snapshots").set({ resumed_at: value }).where("id", "=", id).execute();
3534
+ return this.findById(id);
3535
+ }
3536
+ };
3537
+ function toInsertableHandoffSnapshot(id, input) {
3538
+ return {
3539
+ id,
3540
+ scope: input.scope,
3541
+ actor_type: input.actorType,
3542
+ actor_id: input.actorId,
3543
+ auth_metadata: jsonOrNull(input.authMetadata),
3544
+ objective: input.objective,
3545
+ reasoning: input.reasoning,
3546
+ key_findings: JSON.stringify(input.keyFindings ?? []),
3547
+ touched_objects: JSON.stringify(input.touchedObjects ?? []),
3548
+ pending_actions: JSON.stringify(input.pendingActions ?? []),
3549
+ tool_evidence: JSON.stringify(input.toolEvidence ?? []),
3550
+ confidence: input.confidence ?? null,
3551
+ handoff_kind: input.handoffKind ?? "pause",
3552
+ reference_type: input.referenceType ?? null,
3553
+ reference_id: input.referenceId ?? null,
3554
+ created_at: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
3555
+ resumed_at: null
3556
+ };
3557
+ }
3558
+ function rowToHandoffSnapshot(row) {
3559
+ return {
3560
+ id: row.id,
3561
+ scope: row.scope,
3562
+ actorType: row.actor_type,
3563
+ actorId: row.actor_id,
3564
+ authMetadata: parseRecord(row.auth_metadata),
3565
+ objective: row.objective,
3566
+ reasoning: row.reasoning,
3567
+ keyFindings: parseArray(row.key_findings),
3568
+ touchedObjects: parseArray(row.touched_objects),
3569
+ pendingActions: parseArray(row.pending_actions),
3570
+ toolEvidence: parseArray(row.tool_evidence),
3571
+ confidence: row.confidence,
3572
+ handoffKind: row.handoff_kind,
3573
+ referenceType: row.reference_type,
3574
+ referenceId: row.reference_id,
3575
+ createdAt: row.created_at,
3576
+ resumedAt: row.resumed_at
3577
+ };
3578
+ }
3579
+ function jsonOrNull(value) {
3580
+ return value ? JSON.stringify(value) : null;
3581
+ }
3582
+ function parseRecord(value) {
3583
+ if (!value) return null;
3584
+ try {
3585
+ const parsed = JSON.parse(value);
3586
+ return isRecord(parsed) ? parsed : null;
3587
+ } catch {
3588
+ return null;
3589
+ }
3590
+ }
3591
+ function parseArray(value) {
3592
+ if (!value) return [];
3593
+ try {
3594
+ const parsed = JSON.parse(value);
3595
+ return Array.isArray(parsed) ? parsed.filter((_item) => true) : [];
3596
+ } catch {
3597
+ return [];
3598
+ }
3599
+ }
3600
+ function isRecord(value) {
3601
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3602
+ }
3603
+
3604
+ //#endregion
3605
+ //#region src/site-context/handoff.ts
3606
+ const DEFAULT_ACTIVITY_LIMIT = 25;
3607
+ const DEFAULT_REVIEW_LIMIT = 25;
3608
+ const MAX_DIFF_LIMIT = 100;
3609
+ var HandoffSnapshotStore = class {
3610
+ db;
3611
+ now;
3612
+ constructor(options) {
3613
+ this.db = options.db;
3614
+ this.now = options.now ?? /* @__PURE__ */ new Date();
3615
+ }
3616
+ async capture(input) {
3617
+ assertExperimentalSiteContextWorkflowsEnabled();
3618
+ parseSiteBriefingScope(input.scope);
3619
+ return new HandoffSnapshotRepository(this.db).create(input);
3620
+ }
3621
+ async get(id) {
3622
+ assertExperimentalSiteContextWorkflowsEnabled();
3623
+ return new HandoffSnapshotRepository(this.db).findById(id);
3624
+ }
3625
+ async resume(input) {
3626
+ assertExperimentalSiteContextWorkflowsEnabled();
3627
+ const repository = new HandoffSnapshotRepository(this.db);
3628
+ const snapshot = await repository.findById(input.id);
3629
+ if (!snapshot) return null;
3630
+ const resumedAt = this.now.toISOString();
3631
+ const resumed = await repository.markResumed(snapshot.id, resumedAt);
3632
+ if (!resumed) return null;
3633
+ const scope = parseSiteBriefingScope(resumed.scope);
3634
+ const permissions = {
3635
+ canReadContent: false,
3636
+ ...input.permissions
3637
+ };
3638
+ const activityLimit = clampLimit(input.activityLimit ?? DEFAULT_ACTIVITY_LIMIT);
3639
+ const reviewLimit = clampLimit(input.reviewLimit ?? DEFAULT_REVIEW_LIMIT);
3640
+ const [activity, context, reviewRequests] = permissions.canReadContent ? await Promise.all([
3641
+ new SiteActivityRepository(this.db).findTimeline({
3642
+ scopes: scope.ancestors,
3643
+ since: resumed.createdAt,
3644
+ limit: activityLimit
3645
+ }),
3646
+ new ContextRepository(this.db).diff({
3647
+ scopes: scope.ancestors,
3648
+ since: resumed.createdAt,
3649
+ now: resumedAt
3650
+ }),
3651
+ new ReviewRequestRepository(this.db).list({
3652
+ scopes: scope.ancestors,
3653
+ since: resumed.createdAt,
3654
+ limit: reviewLimit
3655
+ })
3656
+ ]) : [
3657
+ null,
3658
+ null,
3659
+ null
3660
+ ];
3661
+ return {
3662
+ snapshot: resumed,
3663
+ resumedAt,
3664
+ diff: {
3665
+ scope: summarizeScope(scope),
3666
+ since: resumed.createdAt,
3667
+ activity: permissions.canReadContent ? includedSection({
3668
+ scopes: scope.ancestors,
3669
+ items: activity.items
3670
+ }) : omittedSection({
3671
+ scopes: scope.ancestors,
3672
+ items: []
3673
+ }, "missing content:read permission"),
3674
+ context: permissions.canReadContent ? includedSection({
3675
+ scopes: scope.ancestors,
3676
+ diff: context
3677
+ }) : omittedSection({
3678
+ scopes: scope.ancestors,
3679
+ diff: {
3680
+ newEntries: [],
3681
+ supersededEntries: [],
3682
+ staleEntries: [],
3683
+ reviewedEntries: []
3684
+ }
3685
+ }, "missing content:read permission"),
3686
+ reviewRequests: permissions.canReadContent ? includedSection({
3687
+ scopes: scope.ancestors,
3688
+ items: reviewRequests.items
3689
+ }) : omittedSection({
3690
+ scopes: scope.ancestors,
3691
+ items: []
3692
+ }, "missing content:read permission")
3693
+ }
3694
+ };
3695
+ }
3696
+ };
3697
+ function summarizeScope(scope) {
3698
+ return {
3699
+ requested: scope.scope,
3700
+ resolved: scope.scope,
3701
+ type: scope.type,
3702
+ ancestors: scope.ancestors,
3703
+ collection: scope.collection,
3704
+ contentId: scope.contentId,
3705
+ pluginId: scope.pluginId
3706
+ };
3707
+ }
3708
+ function includedSection(data) {
3709
+ return {
3710
+ status: "included",
3711
+ data
3712
+ };
3713
+ }
3714
+ function omittedSection(data, reason) {
3715
+ return {
3716
+ status: "omitted",
3717
+ reason,
3718
+ data
3719
+ };
3720
+ }
3721
+ function clampLimit(value) {
3722
+ return Math.min(Math.max(1, Math.floor(value)), MAX_DIFF_LIMIT);
3723
+ }
3724
+
3725
+ //#endregion
3726
+ //#region src/site-context/assignments.ts
3727
+ const ASSIGNMENT_VALID_FROM = {
3728
+ accept: ["pending"],
3729
+ start: ["accepted", "blocked"],
3730
+ block: ["accepted", "in_progress"],
3731
+ complete: [
3732
+ "pending",
3733
+ "accepted",
3734
+ "in_progress"
3735
+ ],
3736
+ decline: ["pending", "accepted"],
3737
+ cancel: [
3738
+ "pending",
3739
+ "accepted",
3740
+ "in_progress",
3741
+ "blocked"
3742
+ ]
3743
+ };
3744
+ var AssignmentService = class {
3745
+ repository;
3746
+ constructor(db) {
3747
+ this.db = db;
3748
+ this.repository = new AssignmentRepository(db);
3749
+ }
3750
+ async create(actor, input) {
3751
+ assertExperimentalSiteContextWorkflowsEnabled();
3752
+ if (input.relatedHandoffSnapshotId) {
3753
+ const snapshot = await new HandoffSnapshotRepository(this.db).findById(input.relatedHandoffSnapshotId);
3754
+ if (!snapshot) throw new Error(`Handoff snapshot not found: ${input.relatedHandoffSnapshotId}`);
3755
+ if (snapshot.scope !== input.scope) throw new Error("Related handoff snapshot scope must match the assignment scope.");
3756
+ }
3757
+ return this.repository.create({
3758
+ scope: input.scope,
3759
+ assignmentType: input.assignmentType,
3760
+ title: input.title,
3761
+ summary: input.summary,
3762
+ details: input.details,
3763
+ priority: input.priority,
3764
+ assignedByActorType: actor.actorType,
3765
+ assignedByActorId: actor.actorId,
3766
+ assignedToActorType: input.assignedToActorType,
3767
+ assignedToActorId: input.assignedToActorId,
3768
+ metadata: input.metadata,
3769
+ relatedHandoffSnapshotId: input.relatedHandoffSnapshotId,
3770
+ dueAt: input.dueAt,
3771
+ createdAt: input.createdAt
3772
+ });
3773
+ }
3774
+ async get(id, actor) {
3775
+ assertExperimentalSiteContextWorkflowsEnabled();
3776
+ const assignment = await this.repository.findById(id);
3777
+ if (!assignment) return null;
3778
+ this.assertReadable(assignment, actor);
3779
+ return assignment;
3780
+ }
3781
+ async list(actor, input = {}) {
3782
+ assertExperimentalSiteContextWorkflowsEnabled();
3783
+ return this.repository.list(this.buildListQuery(actor, input));
3784
+ }
3785
+ async accept(input) {
3786
+ assertExperimentalSiteContextWorkflowsEnabled();
3787
+ const assignment = await this.loadExisting(input.id);
3788
+ this.assertAssigneeAction("accept", assignment, input.actor);
3789
+ this.assertValidAction("accept", assignment.status);
3790
+ const accepted = await this.repository.accept(assignment.id, {
3791
+ assignedToActorType: assignment.assignedToActorType ?? input.actor.actorType,
3792
+ assignedToActorId: assignment.assignedToActorId ?? input.actor.actorId,
3793
+ acceptedAt: input.at,
3794
+ metadata: assignment.metadata
3795
+ });
3796
+ if (!accepted) throw new Error(`Failed to accept assignment ${assignment.id}.`);
3797
+ return accepted;
3798
+ }
3799
+ async start(input) {
3800
+ assertExperimentalSiteContextWorkflowsEnabled();
3801
+ const assignment = await this.loadExisting(input.id);
3802
+ this.assertAssigneeAction("start", assignment, input.actor);
3803
+ this.assertValidAction("start", assignment.status);
3804
+ const started = await this.repository.start(assignment.id, {
3805
+ at: input.at ?? assignment.startedAt ?? void 0,
3806
+ metadata: assignment.metadata
3807
+ });
3808
+ if (!started) throw new Error(`Failed to start assignment ${assignment.id}.`);
3809
+ return started;
3810
+ }
3811
+ async block(input) {
3812
+ assertExperimentalSiteContextWorkflowsEnabled();
3813
+ const assignment = await this.loadExisting(input.id);
3814
+ this.assertAssigneeAction("block", assignment, input.actor);
3815
+ this.assertValidAction("block", assignment.status);
3816
+ const blocked = await this.repository.block(assignment.id, {
3817
+ at: input.at,
3818
+ metadata: mergeReasonMetadata(assignment.metadata, "block_reason", input.reason)
3819
+ });
3820
+ if (!blocked) throw new Error(`Failed to block assignment ${assignment.id}.`);
3821
+ return blocked;
3822
+ }
3823
+ async complete(input) {
3824
+ assertExperimentalSiteContextWorkflowsEnabled();
3825
+ const assignment = await this.loadExisting(input.id);
3826
+ this.assertAssigneeAction("complete", assignment, input.actor);
3827
+ this.assertValidAction("complete", assignment.status);
3828
+ const completed = await this.repository.complete(assignment.id, {
3829
+ at: input.at,
3830
+ metadata: mergeReasonMetadata(assignment.metadata, "completion_note", input.reason)
3831
+ });
3832
+ if (!completed) throw new Error(`Failed to complete assignment ${assignment.id}.`);
3833
+ return completed;
3834
+ }
3835
+ async decline(input) {
3836
+ assertExperimentalSiteContextWorkflowsEnabled();
3837
+ const assignment = await this.loadExisting(input.id);
3838
+ this.assertAssigneeAction("decline", assignment, input.actor);
3839
+ this.assertValidAction("decline", assignment.status);
3840
+ const declined = await this.repository.decline(assignment.id, {
3841
+ at: input.at,
3842
+ metadata: mergeReasonMetadata(assignment.metadata, "decline_reason", input.reason)
3843
+ });
3844
+ if (!declined) throw new Error(`Failed to decline assignment ${assignment.id}.`);
3845
+ return declined;
3846
+ }
3847
+ async cancel(input) {
3848
+ assertExperimentalSiteContextWorkflowsEnabled();
3849
+ const assignment = await this.loadExisting(input.id);
3850
+ this.assertCanceller(assignment, input.actor);
3851
+ this.assertValidAction("cancel", assignment.status);
3852
+ const cancelled = await this.repository.cancel(assignment.id, {
3853
+ at: input.at,
3854
+ metadata: mergeReasonMetadata(assignment.metadata, "cancel_reason", input.reason)
3855
+ });
3856
+ if (!cancelled) throw new Error(`Failed to cancel assignment ${assignment.id}.`);
3857
+ return cancelled;
3858
+ }
3859
+ buildListQuery(actor, input) {
3860
+ const query = {
3861
+ scope: input.scope,
3862
+ scopes: input.scopes,
3863
+ statuses: input.statuses,
3864
+ priority: input.priority,
3865
+ assignmentType: input.assignmentType,
3866
+ since: input.since,
3867
+ limit: input.limit,
3868
+ cursor: input.cursor
3869
+ };
3870
+ if (isWorkflowSupervisor(actor.userRole)) {
3871
+ if (input.assignedToMe && !input.assignedByMe) {
3872
+ query.assignedToActorType = actor.actorType;
3873
+ query.assignedToActorId = actor.actorId;
3874
+ } else if (input.assignedByMe && !input.assignedToMe) {
3875
+ query.assignedByActorType = actor.actorType;
3876
+ query.assignedByActorId = actor.actorId;
3877
+ }
3878
+ return query;
3879
+ }
3880
+ if (input.assignedToMe && !input.assignedByMe) {
3881
+ query.assignedToActorType = actor.actorType;
3882
+ query.assignedToActorId = actor.actorId;
3883
+ return query;
3884
+ }
3885
+ if (input.assignedByMe && !input.assignedToMe) {
3886
+ query.assignedByActorType = actor.actorType;
3887
+ query.assignedByActorId = actor.actorId;
3888
+ return query;
3889
+ }
3890
+ query.participantActor = {
3891
+ actorType: actor.actorType,
3892
+ actorId: actor.actorId
3893
+ };
3894
+ return query;
3895
+ }
3896
+ async loadExisting(id) {
3897
+ const assignment = await this.repository.findById(id);
3898
+ if (!assignment) throw new Error(`Assignment not found: ${id}`);
3899
+ return assignment;
3900
+ }
3901
+ assertReadable(assignment, actor) {
3902
+ if (isWorkflowSupervisor(actor.userRole)) return;
3903
+ if (matchesActor$1(assignment.assignedByActorType, assignment.assignedByActorId, actor) || matchesActor$1(assignment.assignedToActorType, assignment.assignedToActorId, actor)) return;
3904
+ throw new Error("Insufficient permissions to access this assignment.");
3905
+ }
3906
+ assertAssigneeAction(action, assignment, actor) {
3907
+ if (isWorkflowSupervisor(actor.userRole)) return;
3908
+ if (!assignment.assignedToActorType || !assignment.assignedToActorId) {
3909
+ if (action === "accept") return;
3910
+ throw new Error(`Only an assigned actor can ${action} this assignment.`);
3911
+ }
3912
+ if (matchesActor$1(assignment.assignedToActorType, assignment.assignedToActorId, actor)) return;
3913
+ throw new Error(`Only the assignee can ${action} this assignment.`);
3914
+ }
3915
+ assertCanceller(assignment, actor) {
3916
+ if (isWorkflowSupervisor(actor.userRole)) return;
3917
+ if (matchesActor$1(assignment.assignedByActorType, assignment.assignedByActorId, actor)) return;
3918
+ throw new Error("Only the assigner or an editor can cancel this assignment.");
3919
+ }
3920
+ assertValidAction(action, currentStatus) {
3921
+ const blocker = validateAssignmentAction(action, currentStatus);
3922
+ if (blocker) throw new Error(blocker);
3923
+ }
3924
+ };
3925
+ function validateAssignmentAction(action, currentStatus) {
3926
+ const validFrom = ASSIGNMENT_VALID_FROM[action];
3927
+ if (validFrom.includes(currentStatus)) return null;
3928
+ return `Cannot ${action} an assignment that is currently '${currentStatus}'. Must be: ${validFrom.join(" or ")}`;
3929
+ }
3930
+ function matchesActor$1(actorType, actorId, actor) {
3931
+ return actorType === actor.actorType && actorId === actor.actorId;
3932
+ }
3933
+ function isWorkflowSupervisor(userRole) {
3934
+ return userRole >= Role.EDITOR;
3935
+ }
3936
+ function mergeReasonMetadata(metadata, key, reason) {
3937
+ if (!reason) return metadata;
3938
+ return {
3939
+ ...metadata,
3940
+ [key]: reason
3941
+ };
3942
+ }
3943
+
3944
+ //#endregion
3945
+ //#region src/site-context/hitl.ts
3946
+ const HITL_REQUEST_VALID_FROM = { resolve: ["pending"] };
3947
+ var HitlRequestService = class {
3948
+ repository;
3949
+ assignments;
3950
+ constructor(db) {
3951
+ this.db = db;
3952
+ this.repository = new HitlRequestRepository(db);
3953
+ this.assignments = new AssignmentRepository(db);
3954
+ }
3955
+ async create(actor, input) {
3956
+ assertExperimentalSiteContextWorkflowsEnabled();
3957
+ parseSiteBriefingScope(input.scope);
3958
+ const assignment = input.relatedAssignmentId ? await this.assignments.findById(input.relatedAssignmentId) : null;
3959
+ if (input.relatedAssignmentId && !assignment) throw new Error(`Assignment not found: ${input.relatedAssignmentId}`);
3960
+ if (assignment) {
3961
+ this.assertRelatedAssignmentReadable(assignment, actor);
3962
+ if (assignment.scope !== input.scope) throw new Error("Related assignment scope must match the HITL request scope.");
3963
+ if (assignment.relatedHitlRequestId) throw new Error(`Assignment ${assignment.id} is already linked to HITL request ${assignment.relatedHitlRequestId}.`);
3964
+ }
3965
+ if (input.relatedHandoffSnapshotId) {
3966
+ const snapshot = await new HandoffSnapshotRepository(this.db).findById(input.relatedHandoffSnapshotId);
3967
+ if (!snapshot) throw new Error(`Handoff snapshot not found: ${input.relatedHandoffSnapshotId}`);
3968
+ this.assertRelatedHandoffSnapshotReadable(snapshot, actor);
3969
+ if (snapshot.scope !== input.scope) throw new Error("Related handoff snapshot scope must match the HITL request scope.");
3970
+ }
3971
+ const request = await this.repository.create({
3972
+ scope: input.scope,
3973
+ actionType: input.actionType,
3974
+ title: input.title,
3975
+ summary: input.summary,
3976
+ riskReason: input.riskReason,
3977
+ reviewPayload: input.reviewPayload,
3978
+ targetRefType: input.targetRefType,
3979
+ targetRefId: input.targetRefId,
3980
+ requestedByActorType: actor.actorType,
3981
+ requestedByActorId: actor.actorId,
3982
+ requestedAuthMetadata: actor.authMetadata,
3983
+ priority: input.priority,
3984
+ metadata: input.metadata,
3985
+ relatedAssignmentId: input.relatedAssignmentId,
3986
+ relatedHandoffSnapshotId: input.relatedHandoffSnapshotId,
3987
+ slaDueAt: input.slaDueAt,
3988
+ createdAt: input.createdAt
3989
+ });
3990
+ if (assignment) {
3991
+ if (!await this.assignments.linkHitlRequest(assignment.id, request.id, request.createdAt)) throw new Error(`Failed to link assignment ${assignment.id} to HITL request ${request.id}.`);
3992
+ }
3993
+ return request;
3994
+ }
3995
+ async get(id, actor) {
3996
+ assertExperimentalSiteContextWorkflowsEnabled();
3997
+ const request = await this.repository.findById(id);
3998
+ if (!request) return null;
3999
+ this.assertReadable(request, actor);
4000
+ return request;
4001
+ }
4002
+ async list(actor, input = {}) {
4003
+ assertExperimentalSiteContextWorkflowsEnabled();
4004
+ return this.repository.list(this.buildListQuery(actor, input));
4005
+ }
4006
+ async resolve(input) {
4007
+ assertExperimentalSiteContextWorkflowsEnabled();
4008
+ const request = await this.loadExisting(input.id);
4009
+ this.assertResolver(input.actor);
4010
+ this.assertReadable(request, input.actor);
4011
+ this.assertValidAction("resolve", request.status);
4012
+ const resolved = await this.repository.resolve(request.id, {
4013
+ decision: input.decision,
4014
+ resolvedByActorType: input.actor.actorType,
4015
+ resolvedByActorId: input.actor.actorId,
4016
+ resolvedAuthMetadata: input.actor.authMetadata,
4017
+ reviewNote: input.reviewNote,
4018
+ resolvedAt: input.at
4019
+ });
4020
+ if (!resolved) throw new Error(`Failed to resolve HITL request ${request.id}.`);
4021
+ return resolved;
4022
+ }
4023
+ buildListQuery(actor, input) {
4024
+ const query = {
4025
+ scope: input.scope,
4026
+ scopes: input.scopes,
4027
+ statuses: input.statuses,
4028
+ priority: input.priority,
4029
+ actionType: input.actionType,
4030
+ targetRefType: input.targetRefType,
4031
+ targetRefId: input.targetRefId,
4032
+ relatedAssignmentId: input.relatedAssignmentId,
4033
+ since: input.since,
4034
+ limit: input.limit,
4035
+ cursor: input.cursor
4036
+ };
4037
+ if (isHitlSupervisor(actor.userRole)) return query;
4038
+ return {
4039
+ ...query,
4040
+ requestedByActorType: actor.actorType,
4041
+ requestedByActorId: actor.actorId
4042
+ };
4043
+ }
4044
+ async loadExisting(id) {
4045
+ const request = await this.repository.findById(id);
4046
+ if (!request) throw new Error(`HITL request not found: ${id}`);
4047
+ return request;
4048
+ }
4049
+ assertReadable(request, actor) {
4050
+ if (isHitlSupervisor(actor.userRole)) return;
4051
+ if (request.requestedByActorType === actor.actorType && request.requestedByActorId === actor.actorId) return;
4052
+ throw new Error("Insufficient permissions to read this HITL request.");
4053
+ }
4054
+ assertResolver(actor) {
4055
+ if (isHitlSupervisor(actor.userRole)) return;
4056
+ throw new Error("HITL requests may only be resolved by an editor or admin.");
4057
+ }
4058
+ assertRelatedAssignmentReadable(assignment, actor) {
4059
+ if (isHitlSupervisor(actor.userRole)) return;
4060
+ if (matchesActor(assignment.assignedByActorType, assignment.assignedByActorId, actor) || matchesActor(assignment.assignedToActorType, assignment.assignedToActorId, actor)) return;
4061
+ throw new Error("Insufficient permissions to link this assignment to a HITL request.");
4062
+ }
4063
+ assertRelatedHandoffSnapshotReadable(snapshot, actor) {
4064
+ if (isHitlSupervisor(actor.userRole)) return;
4065
+ if (matchesActor(snapshot.actorType, snapshot.actorId, actor)) return;
4066
+ throw new Error("Insufficient permissions to link this handoff snapshot to a HITL request.");
4067
+ }
4068
+ assertValidAction(action, status) {
4069
+ const validFrom = HITL_REQUEST_VALID_FROM[action];
4070
+ if (!validFrom.includes(status)) throw new Error(`Cannot ${action} a HITL request in status "${status}". Valid statuses: ${validFrom.join(", ")}.`);
4071
+ }
4072
+ };
4073
+ function isHitlSupervisor(role) {
4074
+ return role >= Role.EDITOR;
4075
+ }
4076
+ function matchesActor(actorType, actorId, actor) {
4077
+ return actorType === actor.actorType && actorId === actor.actorId;
4078
+ }
4079
+
4080
+ //#endregion
4081
+ //#region src/site-context/workflow-hitl.ts
4082
+ var WorkflowHitlCoordinator = class {
4083
+ constructor(db) {
4084
+ this.db = db;
4085
+ }
4086
+ async ensureRequest(input) {
4087
+ assertExperimentalSiteContextWorkflowsEnabled();
4088
+ const matching = (await new HitlRequestRepository(this.db).list({
4089
+ scope: input.action.scope,
4090
+ statuses: ["pending", "approved"],
4091
+ actionType: input.action.actionType,
4092
+ targetRefType: input.action.targetRefType,
4093
+ targetRefId: input.action.targetRefId,
4094
+ limit: 50
4095
+ })).items.find((item) => {
4096
+ const actionHash = item.metadata.actionHash;
4097
+ return typeof actionHash === "string" && actionHash === input.action.actionHash;
4098
+ });
4099
+ if (matching) return {
4100
+ created: false,
4101
+ request: matching
4102
+ };
4103
+ return {
4104
+ created: true,
4105
+ request: await new HitlRequestService(this.db).create(input.actor, {
4106
+ scope: input.action.scope,
4107
+ actionType: input.action.actionType,
4108
+ title: input.action.title,
4109
+ summary: input.action.summary,
4110
+ riskReason: input.action.riskReason,
4111
+ reviewPayload: input.action.reviewPayload,
4112
+ targetRefType: input.action.targetRefType,
4113
+ targetRefId: input.action.targetRefId,
4114
+ priority: input.action.priority,
4115
+ metadata: input.action.metadata
4116
+ })
4117
+ };
4118
+ }
4119
+ };
4120
+
4121
+ //#endregion
4122
+ export { HITL_REQUEST_STATUSES as C, ASSIGNMENT_STATUSES as E, HITL_REQUEST_PRIORITIES as S, ASSIGNMENT_PRIORITIES as T, RiskPolicyEvaluator as _, ActorExpertiseService as a, toPublicContextEntry as b, SectionHitlPayloadBuilder as c, RedirectHitlPayloadBuilder as d, SettingsHitlPayloadBuilder as f, SchemaHitlPayloadBuilder as g, PluginHitlPayloadBuilder as h, HandoffSnapshotStore as i, TaxonomyHitlPayloadBuilder as l, ExclusiveHookHitlPayloadBuilder as m, HitlRequestService as n, EntityResolver as o, WordPressImportHitlPayloadBuilder as p, AssignmentService as r, WidgetHitlPayloadBuilder as s, WorkflowHitlCoordinator as t, MenuHitlPayloadBuilder as u, ReviewPayloadBuilder as v, ASSIGNMENT_ACTOR_TYPES as w, toPublicContextEntryPage as x, toPublicContextDiff as y };