emdash 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1436) hide show
  1. package/dist/action-token-SK8zyN7w.mjs +26 -0
  2. package/dist/action-token-SK8zyN7w.mjs.map +1 -0
  3. package/dist/activation-Dim4YMM7.mjs +387 -0
  4. package/dist/activation-Dim4YMM7.mjs.map +1 -0
  5. package/dist/adapters-F_xorvWv.d.mts +173 -0
  6. package/dist/adapters-F_xorvWv.d.mts.map +1 -0
  7. package/dist/allowed-origins-CEug-p0t.mjs +116 -0
  8. package/dist/allowed-origins-CEug-p0t.mjs.map +1 -0
  9. package/dist/api/route-utils.d.mts +4 -4
  10. package/dist/api/route-utils.mjs +47 -45
  11. package/dist/api/route-utils.mjs.map +1 -1
  12. package/dist/api/schemas/index.d.mts +1 -1
  13. package/dist/api/schemas/index.mjs +9 -9
  14. package/dist/api-D-7BNHoz.mjs +5025 -0
  15. package/dist/api-D-7BNHoz.mjs.map +1 -0
  16. package/dist/api-tokens-Bx38ZCQp.mjs +173 -0
  17. package/dist/api-tokens-Bx38ZCQp.mjs.map +1 -0
  18. package/dist/apply-T7ATgzCh.mjs +1702 -0
  19. package/dist/apply-T7ATgzCh.mjs.map +1 -0
  20. package/dist/approvals-D-m6wvGl.mjs +460 -0
  21. package/dist/approvals-D-m6wvGl.mjs.map +1 -0
  22. package/dist/artifact-fetch-DIh7iyOV.mjs +659 -0
  23. package/dist/artifact-fetch-DIh7iyOV.mjs.map +1 -0
  24. package/dist/artifacts-htGyfCSt.mjs +307 -0
  25. package/dist/artifacts-htGyfCSt.mjs.map +1 -0
  26. package/dist/astro/index.d.mts +14 -14
  27. package/dist/astro/index.d.mts.map +1 -1
  28. package/dist/astro/index.mjs +109 -18
  29. package/dist/astro/index.mjs.map +1 -1
  30. package/dist/astro/middleware/auth.d.mts +12 -12
  31. package/dist/astro/middleware/auth.d.mts.map +1 -1
  32. package/dist/astro/middleware/auth.mjs +12 -11
  33. package/dist/astro/middleware/auth.mjs.map +1 -1
  34. package/dist/astro/middleware/media-usage-write-fence.mjs +5 -5
  35. package/dist/astro/middleware/redirect.d.mts.map +1 -1
  36. package/dist/astro/middleware/redirect.mjs +60 -40
  37. package/dist/astro/middleware/redirect.mjs.map +1 -1
  38. package/dist/astro/middleware/request-context.mjs +49 -15
  39. package/dist/astro/middleware/request-context.mjs.map +1 -1
  40. package/dist/astro/middleware/setup.mjs +1 -1
  41. package/dist/astro/middleware.d.mts +12 -12
  42. package/dist/astro/middleware.d.mts.map +1 -1
  43. package/dist/astro/middleware.mjs +116 -408
  44. package/dist/astro/middleware.mjs.map +1 -1
  45. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +14 -14
  46. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +14 -14
  47. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +6 -6
  48. package/dist/astro/routes/api/admin/api-tokens/index.mjs +7 -7
  49. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +6 -6
  50. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +16 -16
  51. package/dist/astro/routes/api/admin/byline-fields/index.mjs +16 -16
  52. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +16 -16
  53. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +22 -21
  54. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
  55. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +22 -21
  56. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -1
  57. package/dist/astro/routes/api/admin/bylines/index.mjs +22 -21
  58. package/dist/astro/routes/api/admin/bylines/index.mjs.map +1 -1
  59. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +18 -18
  60. package/dist/astro/routes/api/admin/comments/_id_.mjs +7 -7
  61. package/dist/astro/routes/api/admin/comments/bulk.mjs +17 -17
  62. package/dist/astro/routes/api/admin/comments/counts.mjs +7 -7
  63. package/dist/astro/routes/api/admin/comments/index.mjs +17 -17
  64. package/dist/astro/routes/api/admin/core-update.mjs +7 -7
  65. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +6 -6
  66. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +5 -5
  67. package/dist/astro/routes/api/admin/media-usage/activation.mjs +20 -20
  68. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +21 -21
  69. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +21 -21
  70. package/dist/astro/routes/api/admin/media-usage/progress.mjs +23 -22
  71. package/dist/astro/routes/api/admin/media-usage/progress.mjs.map +1 -1
  72. package/dist/astro/routes/api/admin/media-usage/repair.mjs +29 -28
  73. package/dist/astro/routes/api/admin/media-usage/repair.mjs.map +1 -1
  74. package/dist/astro/routes/api/admin/media-usage/work/index.mjs +21 -21
  75. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +21 -21
  76. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +6 -6
  77. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +6 -6
  78. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +8 -8
  79. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +8 -8
  80. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +71 -69
  81. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  82. package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +7 -7
  83. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +70 -68
  84. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
  85. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +70 -69
  86. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  87. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +79 -78
  88. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  89. package/dist/astro/routes/api/admin/plugins/index.mjs +71 -69
  90. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  91. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +7 -7
  92. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +70 -68
  93. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  94. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +78 -77
  95. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  96. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +70 -68
  97. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  98. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +70 -69
  99. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  100. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +80 -79
  101. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  102. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +10 -10
  103. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  104. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +72 -71
  105. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  106. package/dist/astro/routes/api/admin/plugins/registry/publisher-handle.mjs +7 -7
  107. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs +71 -69
  108. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs.map +1 -1
  109. package/dist/astro/routes/api/admin/plugins/updates.mjs +70 -68
  110. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  111. package/dist/astro/routes/api/admin/scheduled-policy-rejections/_collection_/_id_.mjs +5 -5
  112. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +70 -68
  113. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  114. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +7 -7
  115. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +70 -68
  116. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  117. package/dist/astro/routes/api/admin/transfer/_...path_.mjs +4 -4
  118. package/dist/astro/routes/api/admin/transfer/approvals/_id_/approve.mjs +38 -37
  119. package/dist/astro/routes/api/admin/transfer/approvals/_id_/approve.mjs.map +1 -1
  120. package/dist/astro/routes/api/admin/transfer/approvals/_id_/deny.mjs +38 -37
  121. package/dist/astro/routes/api/admin/transfer/approvals/_id_/deny.mjs.map +1 -1
  122. package/dist/astro/routes/api/admin/transfer/approvals/index.mjs +40 -39
  123. package/dist/astro/routes/api/admin/transfer/approvals/index.mjs.map +1 -1
  124. package/dist/astro/routes/api/admin/transfer/capabilities.mjs +40 -39
  125. package/dist/astro/routes/api/admin/transfer/capabilities.mjs.map +1 -1
  126. package/dist/astro/routes/api/admin/transfer/exports/_id_/advance.mjs +40 -39
  127. package/dist/astro/routes/api/admin/transfer/exports/_id_/advance.mjs.map +1 -1
  128. package/dist/astro/routes/api/admin/transfer/exports/_id_/archive.mjs +41 -40
  129. package/dist/astro/routes/api/admin/transfer/exports/_id_/archive.mjs.map +1 -1
  130. package/dist/astro/routes/api/admin/transfer/exports/_id_/files/_...path_.mjs +41 -40
  131. package/dist/astro/routes/api/admin/transfer/exports/_id_/files/_...path_.mjs.map +1 -1
  132. package/dist/astro/routes/api/admin/transfer/exports/_id_/index.mjs +40 -39
  133. package/dist/astro/routes/api/admin/transfer/exports/_id_/index.mjs.map +1 -1
  134. package/dist/astro/routes/api/admin/transfer/exports/_id_/manifest.mjs +41 -40
  135. package/dist/astro/routes/api/admin/transfer/exports/_id_/manifest.mjs.map +1 -1
  136. package/dist/astro/routes/api/admin/transfer/exports/index.mjs +42 -41
  137. package/dist/astro/routes/api/admin/transfer/exports/index.mjs.map +1 -1
  138. package/dist/astro/routes/api/admin/transfer/imports/_id_/abandon.mjs +40 -39
  139. package/dist/astro/routes/api/admin/transfer/imports/_id_/abandon.mjs.map +1 -1
  140. package/dist/astro/routes/api/admin/transfer/imports/_id_/advance.mjs +40 -39
  141. package/dist/astro/routes/api/admin/transfer/imports/_id_/advance.mjs.map +1 -1
  142. package/dist/astro/routes/api/admin/transfer/imports/_id_/analyze.mjs +42 -41
  143. package/dist/astro/routes/api/admin/transfer/imports/_id_/analyze.mjs.map +1 -1
  144. package/dist/astro/routes/api/admin/transfer/imports/_id_/cancel.mjs +40 -39
  145. package/dist/astro/routes/api/admin/transfer/imports/_id_/cancel.mjs.map +1 -1
  146. package/dist/astro/routes/api/admin/transfer/imports/_id_/execute.mjs +42 -41
  147. package/dist/astro/routes/api/admin/transfer/imports/_id_/execute.mjs.map +1 -1
  148. package/dist/astro/routes/api/admin/transfer/imports/_id_/files/_...path_.mjs +40 -39
  149. package/dist/astro/routes/api/admin/transfer/imports/_id_/files/_...path_.mjs.map +1 -1
  150. package/dist/astro/routes/api/admin/transfer/imports/_id_/index.mjs +40 -39
  151. package/dist/astro/routes/api/admin/transfer/imports/_id_/index.mjs.map +1 -1
  152. package/dist/astro/routes/api/admin/transfer/imports/_id_/missing.mjs +42 -41
  153. package/dist/astro/routes/api/admin/transfer/imports/_id_/missing.mjs.map +1 -1
  154. package/dist/astro/routes/api/admin/transfer/imports/_id_/plan.mjs +40 -39
  155. package/dist/astro/routes/api/admin/transfer/imports/_id_/plan.mjs.map +1 -1
  156. package/dist/astro/routes/api/admin/transfer/imports/_id_/receipt.mjs +40 -39
  157. package/dist/astro/routes/api/admin/transfer/imports/_id_/receipt.mjs.map +1 -1
  158. package/dist/astro/routes/api/admin/transfer/imports/index.mjs +42 -41
  159. package/dist/astro/routes/api/admin/transfer/imports/index.mjs.map +1 -1
  160. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +4 -4
  161. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +4 -4
  162. package/dist/astro/routes/api/admin/users/_id_/index.mjs +14 -14
  163. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +6 -6
  164. package/dist/astro/routes/api/admin/users/index.mjs +14 -14
  165. package/dist/astro/routes/api/auth/dev-bypass.mjs +6 -6
  166. package/dist/astro/routes/api/auth/handover.mjs +6 -6
  167. package/dist/astro/routes/api/auth/invite/accept.mjs +4 -4
  168. package/dist/astro/routes/api/auth/invite/complete.mjs +19 -19
  169. package/dist/astro/routes/api/auth/invite/index.mjs +16 -16
  170. package/dist/astro/routes/api/auth/invite/register-options.mjs +17 -17
  171. package/dist/astro/routes/api/auth/logout.mjs +5 -5
  172. package/dist/astro/routes/api/auth/magic-link/send.mjs +18 -18
  173. package/dist/astro/routes/api/auth/magic-link/verify.mjs +15 -15
  174. package/dist/astro/routes/api/auth/me.mjs +15 -15
  175. package/dist/astro/routes/api/auth/mode.mjs +5 -5
  176. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +8 -8
  177. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  178. package/dist/astro/routes/api/auth/passkey/_id_.mjs +14 -14
  179. package/dist/astro/routes/api/auth/passkey/index.mjs +4 -4
  180. package/dist/astro/routes/api/auth/passkey/options.mjs +19 -19
  181. package/dist/astro/routes/api/auth/passkey/register/options.mjs +17 -17
  182. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +18 -18
  183. package/dist/astro/routes/api/auth/passkey/verify.mjs +19 -19
  184. package/dist/astro/routes/api/auth/signup/complete.mjs +19 -19
  185. package/dist/astro/routes/api/auth/signup/request.mjs +17 -17
  186. package/dist/astro/routes/api/auth/signup/verify.mjs +4 -4
  187. package/dist/astro/routes/api/calendar.mjs +15 -15
  188. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +12 -12
  189. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +18 -18
  190. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +5 -5
  191. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.d.mts.map +1 -1
  192. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +18 -17
  193. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs.map +1 -1
  194. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +7 -10
  195. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs.map +1 -1
  196. package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs +20 -17
  197. package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs.map +1 -1
  198. package/dist/astro/routes/api/content/_collection_/_id_/permanent.d.mts.map +1 -1
  199. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +7 -6
  200. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs.map +1 -1
  201. package/dist/astro/routes/api/content/_collection_/_id_/plugin-extensions/_pluginId_/_kind_/_extensionId_.mjs +11 -11
  202. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +30 -29
  203. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs.map +1 -1
  204. package/dist/astro/routes/api/content/_collection_/_id_/publish.d.mts.map +1 -1
  205. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +18 -17
  206. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
  207. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +34 -33
  208. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
  209. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +34 -33
  210. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
  211. package/dist/astro/routes/api/content/_collection_/_id_/restore.d.mts.map +1 -1
  212. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +7 -6
  213. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs.map +1 -1
  214. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +5 -5
  215. package/dist/astro/routes/api/content/_collection_/_id_/schedule.d.mts.map +1 -1
  216. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +19 -18
  217. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
  218. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.d.mts.map +1 -1
  219. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +30 -25
  220. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  221. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +5 -5
  222. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.d.mts.map +1 -1
  223. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +18 -17
  224. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs.map +1 -1
  225. package/dist/astro/routes/api/content/_collection_/_id_.d.mts.map +1 -1
  226. package/dist/astro/routes/api/content/_collection_/_id_.mjs +27 -20
  227. package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
  228. package/dist/astro/routes/api/content/_collection_/authors.mjs +5 -5
  229. package/dist/astro/routes/api/content/_collection_/index.mjs +18 -21
  230. package/dist/astro/routes/api/content/_collection_/index.mjs.map +1 -1
  231. package/dist/astro/routes/api/content/_collection_/trash.mjs +15 -15
  232. package/dist/astro/routes/api/dashboard.d.mts.map +1 -1
  233. package/dist/astro/routes/api/dashboard.mjs +17 -11
  234. package/dist/astro/routes/api/dashboard.mjs.map +1 -1
  235. package/dist/astro/routes/api/dev/emails.mjs +5 -5
  236. package/dist/astro/routes/api/dev/scheduled-tasks.d.mts +12 -0
  237. package/dist/astro/routes/api/dev/scheduled-tasks.d.mts.map +1 -0
  238. package/dist/astro/routes/api/dev/scheduled-tasks.mjs +140 -0
  239. package/dist/astro/routes/api/dev/scheduled-tasks.mjs.map +1 -0
  240. package/dist/astro/routes/api/health.mjs +6 -6
  241. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  242. package/dist/astro/routes/api/import/probe.mjs +24 -22
  243. package/dist/astro/routes/api/import/probe.mjs.map +1 -1
  244. package/dist/astro/routes/api/import/wordpress/analyze.d.mts.map +1 -1
  245. package/dist/astro/routes/api/import/wordpress/analyze.mjs +7 -20
  246. package/dist/astro/routes/api/import/wordpress/analyze.mjs.map +1 -1
  247. package/dist/astro/routes/api/import/wordpress/execute.d.mts +15 -14
  248. package/dist/astro/routes/api/import/wordpress/execute.d.mts.map +1 -1
  249. package/dist/astro/routes/api/import/wordpress/execute.mjs +28 -29
  250. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  251. package/dist/astro/routes/api/import/wordpress/media.d.mts +12 -12
  252. package/dist/astro/routes/api/import/wordpress/media.mjs +17 -17
  253. package/dist/astro/routes/api/import/wordpress/prepare.mjs +19 -17
  254. package/dist/astro/routes/api/import/wordpress/prepare.mjs.map +1 -1
  255. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +13 -13
  256. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +27 -26
  257. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
  258. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  259. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +25 -22
  260. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs.map +1 -1
  261. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +13 -13
  262. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts.map +1 -1
  263. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +55 -34
  264. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  265. package/dist/astro/routes/api/manifest.mjs +6 -6
  266. package/dist/astro/routes/api/mcp.mjs +135 -101
  267. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  268. package/dist/astro/routes/api/media/_id_/confirm.mjs +17 -17
  269. package/dist/astro/routes/api/media/_id_/replace.mjs +15 -15
  270. package/dist/astro/routes/api/media/_id_/upload.mjs +8 -8
  271. package/dist/astro/routes/api/media/_id_/usage.mjs +31 -30
  272. package/dist/astro/routes/api/media/_id_/usage.mjs.map +1 -1
  273. package/dist/astro/routes/api/media/_id_.mjs +29 -28
  274. package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
  275. package/dist/astro/routes/api/media/asset/_id_/_filename_.mjs +6 -6
  276. package/dist/astro/routes/api/media/file/_...key_.mjs +10 -10
  277. package/dist/astro/routes/api/media/folders/_id_.mjs +16 -16
  278. package/dist/astro/routes/api/media/folders/index.mjs +16 -16
  279. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +5 -5
  280. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +5 -5
  281. package/dist/astro/routes/api/media/providers/index.mjs +5 -5
  282. package/dist/astro/routes/api/media/upload-url.mjs +17 -17
  283. package/dist/astro/routes/api/media.mjs +30 -29
  284. package/dist/astro/routes/api/media.mjs.map +1 -1
  285. package/dist/astro/routes/api/menus/_name_/items/_id_.d.mts.map +1 -1
  286. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +19 -18
  287. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
  288. package/dist/astro/routes/api/menus/_name_/items.d.mts.map +1 -1
  289. package/dist/astro/routes/api/menus/_name_/items.mjs +18 -17
  290. package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
  291. package/dist/astro/routes/api/menus/_name_/reorder.d.mts.map +1 -1
  292. package/dist/astro/routes/api/menus/_name_/reorder.mjs +18 -17
  293. package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
  294. package/dist/astro/routes/api/menus/_name_/translations.d.mts.map +1 -1
  295. package/dist/astro/routes/api/menus/_name_/translations.mjs +18 -17
  296. package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
  297. package/dist/astro/routes/api/menus/_name_.d.mts.map +1 -1
  298. package/dist/astro/routes/api/menus/_name_.mjs +19 -18
  299. package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
  300. package/dist/astro/routes/api/menus/index.d.mts.map +1 -1
  301. package/dist/astro/routes/api/menus/index.mjs +18 -17
  302. package/dist/astro/routes/api/menus/index.mjs.map +1 -1
  303. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  304. package/dist/astro/routes/api/oauth/device/authorize.mjs +8 -8
  305. package/dist/astro/routes/api/oauth/device/code.mjs +11 -11
  306. package/dist/astro/routes/api/oauth/device/token.mjs +10 -10
  307. package/dist/astro/routes/api/oauth/register.mjs +7 -7
  308. package/dist/astro/routes/api/oauth/token/refresh.mjs +8 -8
  309. package/dist/astro/routes/api/oauth/token/revoke.mjs +8 -8
  310. package/dist/astro/routes/api/oauth/token.mjs +8 -8
  311. package/dist/astro/routes/api/openapi.json.mjs +20 -20
  312. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +11 -11
  313. package/dist/astro/routes/api/redirects/404s/index.mjs +19 -19
  314. package/dist/astro/routes/api/redirects/404s/summary.mjs +19 -19
  315. package/dist/astro/routes/api/redirects/_id_.d.mts.map +1 -1
  316. package/dist/astro/routes/api/redirects/_id_.mjs +32 -23
  317. package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
  318. package/dist/astro/routes/api/redirects/index.d.mts.map +1 -1
  319. package/dist/astro/routes/api/redirects/index.mjs +24 -21
  320. package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
  321. package/dist/astro/routes/api/relations/_id_/index.mjs +34 -33
  322. package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
  323. package/dist/astro/routes/api/relations/index.mjs +34 -33
  324. package/dist/astro/routes/api/relations/index.mjs.map +1 -1
  325. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +5 -5
  326. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +16 -16
  327. package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs +70 -68
  328. package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs.map +1 -1
  329. package/dist/astro/routes/api/schema/block-types/_slug_/versions/_version_/activate.mjs +70 -68
  330. package/dist/astro/routes/api/schema/block-types/_slug_/versions/_version_/activate.mjs.map +1 -1
  331. package/dist/astro/routes/api/schema/block-types/index.mjs +70 -68
  332. package/dist/astro/routes/api/schema/block-types/index.mjs.map +1 -1
  333. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +70 -68
  334. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  335. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +70 -68
  336. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  337. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +70 -68
  338. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  339. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +70 -68
  340. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  341. package/dist/astro/routes/api/schema/collections/index.mjs +70 -68
  342. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  343. package/dist/astro/routes/api/schema/collections/reorder.mjs +70 -68
  344. package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
  345. package/dist/astro/routes/api/schema/index.mjs +16 -15
  346. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  347. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +70 -68
  348. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  349. package/dist/astro/routes/api/schema/orphans/index.mjs +70 -68
  350. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  351. package/dist/astro/routes/api/search/enable.mjs +19 -18
  352. package/dist/astro/routes/api/search/enable.mjs.map +1 -1
  353. package/dist/astro/routes/api/search/index.mjs +18 -17
  354. package/dist/astro/routes/api/search/index.mjs.map +1 -1
  355. package/dist/astro/routes/api/search/rebuild.mjs +19 -18
  356. package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
  357. package/dist/astro/routes/api/search/stats.mjs +9 -8
  358. package/dist/astro/routes/api/search/stats.mjs.map +1 -1
  359. package/dist/astro/routes/api/search/suggest.mjs +18 -17
  360. package/dist/astro/routes/api/search/suggest.mjs.map +1 -1
  361. package/dist/astro/routes/api/sections/_slug_.mjs +18 -17
  362. package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
  363. package/dist/astro/routes/api/sections/index.mjs +18 -17
  364. package/dist/astro/routes/api/sections/index.mjs.map +1 -1
  365. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +7 -7
  366. package/dist/astro/routes/api/settings/backups/archives/index.mjs +7 -7
  367. package/dist/astro/routes/api/settings/backups/export.mjs +7 -7
  368. package/dist/astro/routes/api/settings/backups/index.mjs +8 -8
  369. package/dist/astro/routes/api/settings/domain-notify.mjs +9 -9
  370. package/dist/astro/routes/api/settings/domain.d.mts.map +1 -1
  371. package/dist/astro/routes/api/settings/domain.mjs +17 -14
  372. package/dist/astro/routes/api/settings/domain.mjs.map +1 -1
  373. package/dist/astro/routes/api/settings/email.mjs +6 -6
  374. package/dist/astro/routes/api/settings.d.mts.map +1 -1
  375. package/dist/astro/routes/api/settings.mjs +23 -20
  376. package/dist/astro/routes/api/settings.mjs.map +1 -1
  377. package/dist/astro/routes/api/setup/admin-verify.d.mts.map +1 -1
  378. package/dist/astro/routes/api/setup/admin-verify.mjs +25 -21
  379. package/dist/astro/routes/api/setup/admin-verify.mjs.map +1 -1
  380. package/dist/astro/routes/api/setup/admin.mjs +18 -18
  381. package/dist/astro/routes/api/setup/dev-bypass.mjs +42 -40
  382. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  383. package/dist/astro/routes/api/setup/dev-reset.mjs +4 -4
  384. package/dist/astro/routes/api/setup/index.mjs +48 -46
  385. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  386. package/dist/astro/routes/api/setup/status.mjs +6 -6
  387. package/dist/astro/routes/api/site/domain-proof.mjs +11 -9
  388. package/dist/astro/routes/api/site/domain-proof.mjs.map +1 -1
  389. package/dist/astro/routes/api/snapshot.mjs +8 -8
  390. package/dist/astro/routes/api/taxonomies/_name_/reorder.d.mts.map +1 -1
  391. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +23 -21
  392. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs.map +1 -1
  393. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.d.mts.map +1 -1
  394. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +23 -21
  395. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
  396. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.d.mts.map +1 -1
  397. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +24 -22
  398. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
  399. package/dist/astro/routes/api/taxonomies/_name_/terms/index.d.mts.map +1 -1
  400. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +23 -21
  401. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
  402. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +21 -20
  403. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs.map +1 -1
  404. package/dist/astro/routes/api/taxonomies/_name_.d.mts.map +1 -1
  405. package/dist/astro/routes/api/taxonomies/_name_.mjs +24 -22
  406. package/dist/astro/routes/api/taxonomies/_name_.mjs.map +1 -1
  407. package/dist/astro/routes/api/taxonomies/bulk-tag.mjs +34 -33
  408. package/dist/astro/routes/api/taxonomies/bulk-tag.mjs.map +1 -1
  409. package/dist/astro/routes/api/taxonomies/index.d.mts.map +1 -1
  410. package/dist/astro/routes/api/taxonomies/index.mjs +23 -21
  411. package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
  412. package/dist/astro/routes/api/themes/preview.mjs +6 -6
  413. package/dist/astro/routes/api/typegen.mjs +6 -6
  414. package/dist/astro/routes/api/visual-editing/action-token.mjs +6 -6
  415. package/dist/astro/routes/api/visual-editing/content/_collection_/_id_/publish.mjs +18 -18
  416. package/dist/astro/routes/api/visual-editing/toolbar-labels.mjs +4 -4
  417. package/dist/astro/routes/api/well-known/auth.mjs +1 -1
  418. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  419. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  420. package/dist/astro/routes/api/widget-areas/_name_/reorder.d.mts.map +1 -1
  421. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +17 -16
  422. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs.map +1 -1
  423. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.d.mts.map +1 -1
  424. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +21 -19
  425. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs.map +1 -1
  426. package/dist/astro/routes/api/widget-areas/_name_/widgets.d.mts.map +1 -1
  427. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +20 -18
  428. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs.map +1 -1
  429. package/dist/astro/routes/api/widget-areas/_name_.d.mts.map +1 -1
  430. package/dist/astro/routes/api/widget-areas/_name_.mjs +10 -8
  431. package/dist/astro/routes/api/widget-areas/_name_.mjs.map +1 -1
  432. package/dist/astro/routes/api/widget-areas/index.d.mts.map +1 -1
  433. package/dist/astro/routes/api/widget-areas/index.mjs +20 -18
  434. package/dist/astro/routes/api/widget-areas/index.mjs.map +1 -1
  435. package/dist/astro/routes/api/widget-components.mjs +5 -5
  436. package/dist/astro/routes/robots.txt.d.mts.map +1 -1
  437. package/dist/astro/routes/robots.txt.mjs +38 -5
  438. package/dist/astro/routes/robots.txt.mjs.map +1 -1
  439. package/dist/astro/routes/sitemap-_collection_.xml.mjs +13 -8
  440. package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
  441. package/dist/astro/routes/sitemap.xml.mjs +11 -6
  442. package/dist/astro/routes/sitemap.xml.mjs.map +1 -1
  443. package/dist/astro/types.d.mts +19 -17
  444. package/dist/astro/types.d.mts.map +1 -1
  445. package/dist/audit-_gieLVGU.mjs +127 -0
  446. package/dist/audit-_gieLVGU.mjs.map +1 -0
  447. package/dist/auth/providers/github.d.mts +1 -1
  448. package/dist/auth/providers/google.d.mts +1 -1
  449. package/dist/auth/providers/microsoft.d.mts +1 -1
  450. package/dist/authoritative-records-CQlB3JzE.mjs +5183 -0
  451. package/dist/authoritative-records-CQlB3JzE.mjs.map +1 -0
  452. package/dist/authorize-DPFBGbE6.mjs +74 -0
  453. package/dist/authorize-DPFBGbE6.mjs.map +1 -0
  454. package/dist/backup-3FgVxiDJ.mjs +246 -0
  455. package/dist/backup-3FgVxiDJ.mjs.map +1 -0
  456. package/dist/block-types-CYcG56JB.mjs +132 -0
  457. package/dist/block-types-CYcG56JB.mjs.map +1 -0
  458. package/dist/block-values-gCX4HBSl.mjs +215 -0
  459. package/dist/block-values-gCX4HBSl.mjs.map +1 -0
  460. package/dist/byline-BR1qhyiw.mjs +909 -0
  461. package/dist/byline-BR1qhyiw.mjs.map +1 -0
  462. package/dist/byline-fields-4ClDC88c.mjs +123 -0
  463. package/dist/byline-fields-4ClDC88c.mjs.map +1 -0
  464. package/dist/byline-fields-BLXZnX7N.mjs +280 -0
  465. package/dist/byline-fields-BLXZnX7N.mjs.map +1 -0
  466. package/dist/bylines-CVOvRUL7.mjs +234 -0
  467. package/dist/bylines-CVOvRUL7.mjs.map +1 -0
  468. package/dist/bylines-DxOs9B7z.mjs +150 -0
  469. package/dist/bylines-DxOs9B7z.mjs.map +1 -0
  470. package/dist/cache-CEU9wo_h.mjs +151 -0
  471. package/dist/cache-CEU9wo_h.mjs.map +1 -0
  472. package/dist/canonical-BudtH-Fx.mjs +174 -0
  473. package/dist/canonical-BudtH-Fx.mjs.map +1 -0
  474. package/dist/capture-triggers-CT6dK9zd.mjs +362 -0
  475. package/dist/capture-triggers-CT6dK9zd.mjs.map +1 -0
  476. package/dist/challenge-store-C17BYx2-.mjs +51 -0
  477. package/dist/challenge-store-C17BYx2-.mjs.map +1 -0
  478. package/dist/checksum-CEqvfxGX.mjs +162 -0
  479. package/dist/checksum-CEqvfxGX.mjs.map +1 -0
  480. package/dist/chunks-xC4UD5-S.mjs +25 -0
  481. package/dist/chunks-xC4UD5-S.mjs.map +1 -0
  482. package/dist/cli/index.mjs +127 -113
  483. package/dist/cli/index.mjs.map +1 -1
  484. package/dist/client/cf-access.d.mts +1 -1
  485. package/dist/client/index.d.mts +47 -47
  486. package/dist/client/index.d.mts.map +1 -1
  487. package/dist/client/index.mjs +12 -10
  488. package/dist/client/index.mjs.map +1 -1
  489. package/dist/collection-slugs-cache-e09QeJQt.mjs +85 -0
  490. package/dist/collection-slugs-cache-e09QeJQt.mjs.map +1 -0
  491. package/dist/comment-UvIWDKcW.mjs +325 -0
  492. package/dist/comment-UvIWDKcW.mjs.map +1 -0
  493. package/dist/comment-reaction-dGp6_FRo.mjs +85 -0
  494. package/dist/comment-reaction-dGp6_FRo.mjs.map +1 -0
  495. package/dist/comments-pej-_BUO.mjs +195 -0
  496. package/dist/comments-pej-_BUO.mjs.map +1 -0
  497. package/dist/comments-yiRFx3w5.mjs +99 -0
  498. package/dist/comments-yiRFx3w5.mjs.map +1 -0
  499. package/dist/components-Brp__9xo.mjs +112 -0
  500. package/dist/components-Brp__9xo.mjs.map +1 -0
  501. package/dist/config-Bsm_u_oE.d.mts +6799 -0
  502. package/dist/config-Bsm_u_oE.d.mts.map +1 -0
  503. package/dist/config-CFMojMFK.d.mts +39 -0
  504. package/dist/config-CFMojMFK.d.mts.map +1 -0
  505. package/dist/config-DBU6iUQB.mjs +228 -0
  506. package/dist/config-DBU6iUQB.mjs.map +1 -0
  507. package/dist/connection-BtEN_lP9.mjs +36 -0
  508. package/dist/connection-BtEN_lP9.mjs.map +1 -0
  509. package/dist/content-DQSRZTVw.mjs +2075 -0
  510. package/dist/content-DQSRZTVw.mjs.map +1 -0
  511. package/dist/content-list-query-CYKcY6Vi.d.mts +26 -0
  512. package/dist/content-list-query-CYKcY6Vi.d.mts.map +1 -0
  513. package/dist/content-repair-DNh5--x5.mjs +442 -0
  514. package/dist/content-repair-DNh5--x5.mjs.map +1 -0
  515. package/dist/context-BYptmCN0.mjs +2090 -0
  516. package/dist/context-BYptmCN0.mjs.map +1 -0
  517. package/dist/credits-B9iORdWB.mjs +110 -0
  518. package/dist/credits-B9iORdWB.mjs.map +1 -0
  519. package/dist/cron-D7obTIfk.mjs +306 -0
  520. package/dist/cron-D7obTIfk.mjs.map +1 -0
  521. package/dist/dashboard-D0jcgBD7.mjs +167 -0
  522. package/dist/dashboard-D0jcgBD7.mjs.map +1 -0
  523. package/dist/database/migration-lock.d.mts +17 -4
  524. package/dist/database/migration-lock.d.mts.map +1 -1
  525. package/dist/database/migration-lock.mjs +32 -5
  526. package/dist/database/migration-lock.mjs.map +1 -1
  527. package/dist/db/index.d.mts +3 -3
  528. package/dist/db/index.mjs +1 -1
  529. package/dist/db/libsql-migrations.d.mts +1 -1
  530. package/dist/db/libsql-migrations.mjs +4 -4
  531. package/dist/db/libsql.d.mts +1 -1
  532. package/dist/db/postgres-migrations.d.mts +1 -1
  533. package/dist/db/postgres-migrations.mjs +4 -4
  534. package/dist/db/postgres.d.mts +1 -1
  535. package/dist/db/sqlite-migrations.d.mts +1 -1
  536. package/dist/db/sqlite-migrations.mjs +4 -4
  537. package/dist/db/sqlite.d.mts +1 -1
  538. package/dist/db/sqlite.mjs +1 -1
  539. package/dist/default-C0W-PhAp.mjs +81 -0
  540. package/dist/default-C0W-PhAp.mjs.map +1 -0
  541. package/dist/deferred-tasks-ZvUECSzI.d.mts +9 -0
  542. package/dist/deferred-tasks-ZvUECSzI.d.mts.map +1 -0
  543. package/dist/dev-typegen-EBni_pOQ.mjs +29 -0
  544. package/dist/dev-typegen-EBni_pOQ.mjs.map +1 -0
  545. package/dist/device-flow-BkFKBoAn.mjs +521 -0
  546. package/dist/device-flow-BkFKBoAn.mjs.map +1 -0
  547. package/dist/digest-DJ1tHCgy.mjs +194 -0
  548. package/dist/digest-DJ1tHCgy.mjs.map +1 -0
  549. package/dist/direct-executor-Cbxzg4qe.mjs +117 -0
  550. package/dist/direct-executor-Cbxzg4qe.mjs.map +1 -0
  551. package/dist/email-console-FFVJWb9N.mjs +50 -0
  552. package/dist/email-console-FFVJWb9N.mjs.map +1 -0
  553. package/dist/email-locale-BJ8DjTzZ.mjs +25 -0
  554. package/dist/email-locale-BJ8DjTzZ.mjs.map +1 -0
  555. package/dist/emdash-runtime-DVi7vtXC.mjs +4379 -0
  556. package/dist/emdash-runtime-DVi7vtXC.mjs.map +1 -0
  557. package/dist/entry-lock-C7VX0NGK.d.mts +4568 -0
  558. package/dist/entry-lock-C7VX0NGK.d.mts.map +1 -0
  559. package/dist/entry-lock-DLxCffFW.mjs +163 -0
  560. package/dist/entry-lock-DLxCffFW.mjs.map +1 -0
  561. package/dist/entry-lock-Df6-XhIu.mjs +1211 -0
  562. package/dist/entry-lock-Df6-XhIu.mjs.map +1 -0
  563. package/dist/env-types-C3FCVBWe.mjs +38 -0
  564. package/dist/env-types-C3FCVBWe.mjs.map +1 -0
  565. package/dist/error-CVWeIOku.mjs +90 -0
  566. package/dist/error-CVWeIOku.mjs.map +1 -0
  567. package/dist/errors-B4f4It-2.mjs +120 -0
  568. package/dist/errors-B4f4It-2.mjs.map +1 -0
  569. package/dist/errors-BOYNdIo3.mjs +479 -0
  570. package/dist/errors-BOYNdIo3.mjs.map +1 -0
  571. package/dist/escape-lsNq38PP.mjs +9 -0
  572. package/dist/escape-lsNq38PP.mjs.map +1 -0
  573. package/dist/fence-C3MUitUN.mjs +162 -0
  574. package/dist/fence-C3MUitUN.mjs.map +1 -0
  575. package/dist/field-defs-cache-Dez5iWJJ.mjs +77 -0
  576. package/dist/field-defs-cache-Dez5iWJJ.mjs.map +1 -0
  577. package/dist/field-map-Bft9LKak.mjs +83 -0
  578. package/dist/field-map-Bft9LKak.mjs.map +1 -0
  579. package/dist/fts-manager-Beg3e4bI.mjs +443 -0
  580. package/dist/fts-manager-Beg3e4bI.mjs.map +1 -0
  581. package/dist/gc-ByyAYiYE.mjs +75 -0
  582. package/dist/gc-ByyAYiYE.mjs.map +1 -0
  583. package/dist/hash-BJaeek87.mjs +37 -0
  584. package/dist/hash-BJaeek87.mjs.map +1 -0
  585. package/dist/hook-result-BrdLyOdI.d.mts +31 -0
  586. package/dist/hook-result-BrdLyOdI.d.mts.map +1 -0
  587. package/dist/hreflang-C8Jb-hrf.mjs +105 -0
  588. package/dist/hreflang-C8Jb-hrf.mjs.map +1 -0
  589. package/dist/hreflang-CY_F5OjF.d.mts +50 -0
  590. package/dist/hreflang-CY_F5OjF.d.mts.map +1 -0
  591. package/dist/http-route-dispatch-CyeW6iPv.mjs +342 -0
  592. package/dist/http-route-dispatch-CyeW6iPv.mjs.map +1 -0
  593. package/dist/identity-Cael5uTT.mjs +35 -0
  594. package/dist/identity-Cael5uTT.mjs.map +1 -0
  595. package/dist/import-BUXjdZUn.mjs +2126 -0
  596. package/dist/import-BUXjdZUn.mjs.map +1 -0
  597. package/dist/index-BB9sVisO.d.mts +623 -0
  598. package/dist/index-BB9sVisO.d.mts.map +1 -0
  599. package/dist/index.d.mts +23 -23
  600. package/dist/index.mjs +96 -94
  601. package/dist/install-finalization-3JX5qQEA.mjs +58 -0
  602. package/dist/install-finalization-3JX5qQEA.mjs.map +1 -0
  603. package/dist/json-recordset-BUjxhr77.mjs +12 -0
  604. package/dist/json-recordset-BUjxhr77.mjs.map +1 -0
  605. package/dist/json-schema-v_D_pPNG.mjs +15 -0
  606. package/dist/json-schema-v_D_pPNG.mjs.map +1 -0
  607. package/dist/keys-CifIkT0N.mjs +61 -0
  608. package/dist/keys-CifIkT0N.mjs.map +1 -0
  609. package/dist/kinds-B_Qcl5pz.mjs +974 -0
  610. package/dist/kinds-B_Qcl5pz.mjs.map +1 -0
  611. package/dist/lifecycle-7vUJeFRe.mjs +25 -0
  612. package/dist/lifecycle-7vUJeFRe.mjs.map +1 -0
  613. package/dist/load-CdAG9wz-.mjs +28 -0
  614. package/dist/load-CdAG9wz-.mjs.map +1 -0
  615. package/dist/loader-CswroUbe.mjs +1380 -0
  616. package/dist/loader-CswroUbe.mjs.map +1 -0
  617. package/dist/loops-uA4iTOzd.mjs +205 -0
  618. package/dist/loops-uA4iTOzd.mjs.map +1 -0
  619. package/dist/manifest-builder-B8zjuH3f.mjs +189 -0
  620. package/dist/manifest-builder-B8zjuH3f.mjs.map +1 -0
  621. package/dist/manifest-schema-DNb4XmTS.mjs +497 -0
  622. package/dist/manifest-schema-DNb4XmTS.mjs.map +1 -0
  623. package/dist/marketplace-CqbgeIa7.mjs +257 -0
  624. package/dist/marketplace-CqbgeIa7.mjs.map +1 -0
  625. package/dist/media/index.d.mts +1 -1
  626. package/dist/media/local-runtime.d.mts +14 -14
  627. package/dist/media/local-runtime.mjs +10 -5
  628. package/dist/media/local-runtime.mjs.map +1 -1
  629. package/dist/media--dJRU6i2.mjs +294 -0
  630. package/dist/media--dJRU6i2.mjs.map +1 -0
  631. package/dist/media-1WC65OCB.mjs +416 -0
  632. package/dist/media-1WC65OCB.mjs.map +1 -0
  633. package/dist/media-Bws9f18T.mjs +373 -0
  634. package/dist/media-Bws9f18T.mjs.map +1 -0
  635. package/dist/media-allowlist-BJB7MFx6.mjs +45 -0
  636. package/dist/media-allowlist-BJB7MFx6.mjs.map +1 -0
  637. package/dist/media-folders-Dn3C16B8.mjs +210 -0
  638. package/dist/media-folders-Dn3C16B8.mjs.map +1 -0
  639. package/dist/media-url-BQgKvpQ5.mjs +43 -0
  640. package/dist/media-url-BQgKvpQ5.mjs.map +1 -0
  641. package/dist/media-usage-CF0WVcLO.mjs +282 -0
  642. package/dist/media-usage-CF0WVcLO.mjs.map +1 -0
  643. package/dist/media-usage-activation-C9HwVw5w.mjs +78 -0
  644. package/dist/media-usage-activation-C9HwVw5w.mjs.map +1 -0
  645. package/dist/media-usage-work-CkLa5-nc.mjs +1036 -0
  646. package/dist/media-usage-work-CkLa5-nc.mjs.map +1 -0
  647. package/dist/media-usage-work-m3AWTmmC.mjs +151 -0
  648. package/dist/media-usage-work-m3AWTmmC.mjs.map +1 -0
  649. package/dist/menus-BCVSSp1z.mjs +753 -0
  650. package/dist/menus-BCVSSp1z.mjs.map +1 -0
  651. package/dist/menus-BSzwObhV.mjs +92 -0
  652. package/dist/menus-BSzwObhV.mjs.map +1 -0
  653. package/dist/menus-Cl4kwdt7.mjs +3721 -0
  654. package/dist/menus-Cl4kwdt7.mjs.map +1 -0
  655. package/dist/migrations/index.d.mts +1 -1
  656. package/dist/migrations/index.d.mts.map +1 -1
  657. package/dist/migrations/index.mjs +3 -3
  658. package/dist/mode-C-D3qICy.mjs +23 -0
  659. package/dist/mode-C-D3qICy.mjs.map +1 -0
  660. package/dist/node-sqlite-compat-CrKzRr0J.mjs +63 -0
  661. package/dist/node-sqlite-compat-CrKzRr0J.mjs.map +1 -0
  662. package/dist/oauth-authorization-TpEJrYB7.mjs +274 -0
  663. package/dist/oauth-authorization-TpEJrYB7.mjs.map +1 -0
  664. package/dist/oauth-clients-BT0Pg-MO.mjs +266 -0
  665. package/dist/oauth-clients-BT0Pg-MO.mjs.map +1 -0
  666. package/dist/oauth-state-store-CHMn_mwc.mjs +50 -0
  667. package/dist/oauth-state-store-CHMn_mwc.mjs.map +1 -0
  668. package/dist/oauth-user-lookup-BDgF6IVG.mjs +26 -0
  669. package/dist/oauth-user-lookup-BDgF6IVG.mjs.map +1 -0
  670. package/dist/object-cache/memory.d.mts +1 -1
  671. package/dist/options-DJWaq3Ie.d.mts +81 -0
  672. package/dist/options-DJWaq3Ie.d.mts.map +1 -0
  673. package/dist/ownership-MiyA7qKO.mjs +12 -0
  674. package/dist/ownership-MiyA7qKO.mjs.map +1 -0
  675. package/dist/page/index.d.mts +2 -2
  676. package/dist/page/index.mjs +9 -4
  677. package/dist/page/index.mjs.map +1 -1
  678. package/dist/parse-CWHOFc6z.d.mts +176 -0
  679. package/dist/parse-CWHOFc6z.d.mts.map +1 -0
  680. package/dist/parse-DgQ2NABT.mjs +81 -0
  681. package/dist/parse-DgQ2NABT.mjs.map +1 -0
  682. package/dist/passkey-config-D0kdzEao.mjs +46 -0
  683. package/dist/passkey-config-D0kdzEao.mjs.map +1 -0
  684. package/dist/paths-biDzFTY2.mjs +77 -0
  685. package/dist/paths-biDzFTY2.mjs.map +1 -0
  686. package/dist/placeholder-D41vk11_.d.mts +306 -0
  687. package/dist/placeholder-D41vk11_.d.mts.map +1 -0
  688. package/dist/plan-CCoqxNoU.mjs +135 -0
  689. package/dist/plan-CCoqxNoU.mjs.map +1 -0
  690. package/dist/plugin-test-runtime.d.mts +14 -14
  691. package/dist/plugin-test-runtime.mjs +109 -107
  692. package/dist/plugin-tool-name-DDUgN_0p.mjs +27 -0
  693. package/dist/plugin-tool-name-DDUgN_0p.mjs.map +1 -0
  694. package/dist/plugin-types.d.mts +2 -2
  695. package/dist/plugin-utils.d.mts +12 -12
  696. package/dist/plugins/adapt-sandbox-entry.d.mts +12 -12
  697. package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
  698. package/dist/plugins/adapt-sandbox-entry.mjs +9 -8
  699. package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
  700. package/dist/plugins/host.d.mts +5 -5
  701. package/dist/plugins/host.mjs +45 -41
  702. package/dist/plugins-COJ2L49n.mjs +261 -0
  703. package/dist/plugins-COJ2L49n.mjs.map +1 -0
  704. package/dist/policy-DLQ--Hnm.mjs +45 -0
  705. package/dist/policy-DLQ--Hnm.mjs.map +1 -0
  706. package/dist/portable-text-BH4zgkSm.mjs +311 -0
  707. package/dist/portable-text-BH4zgkSm.mjs.map +1 -0
  708. package/dist/preview-DLexxwp3.mjs +107 -0
  709. package/dist/preview-DLexxwp3.mjs.map +1 -0
  710. package/dist/protocol-79kUO7jP.d.mts +65 -0
  711. package/dist/protocol-79kUO7jP.d.mts.map +1 -0
  712. package/dist/public-plugin-api-routes-BuAMJ8nN.mjs +316 -0
  713. package/dist/public-plugin-api-routes-BuAMJ8nN.mjs.map +1 -0
  714. package/dist/public-submission-Di3TsgzX.mjs +251 -0
  715. package/dist/public-submission-Di3TsgzX.mjs.map +1 -0
  716. package/dist/public-url-Bt98vysr.mjs +101 -0
  717. package/dist/public-url-Bt98vysr.mjs.map +1 -0
  718. package/dist/query-CpnRlBh8.mjs +1156 -0
  719. package/dist/query-CpnRlBh8.mjs.map +1 -0
  720. package/dist/query-haKvLAWl.mjs +41 -0
  721. package/dist/query-haKvLAWl.mjs.map +1 -0
  722. package/dist/range-CYfeXgGK.mjs +51 -0
  723. package/dist/range-CYfeXgGK.mjs.map +1 -0
  724. package/dist/rate-limit-Xp4d0NBY.mjs +127 -0
  725. package/dist/rate-limit-Xp4d0NBY.mjs.map +1 -0
  726. package/dist/receipt-BUsQCOeM.mjs +43 -0
  727. package/dist/receipt-BUsQCOeM.mjs.map +1 -0
  728. package/dist/redirect-CQAV7mCo.mjs +19 -0
  729. package/dist/redirect-CQAV7mCo.mjs.map +1 -0
  730. package/dist/redirect-DiS_3mA4.mjs +423 -0
  731. package/dist/redirect-DiS_3mA4.mjs.map +1 -0
  732. package/dist/redirect-paths-CNYq7w80.mjs +36 -0
  733. package/dist/redirect-paths-CNYq7w80.mjs.map +1 -0
  734. package/dist/redirects-BEVSRMa2.mjs +148 -0
  735. package/dist/redirects-BEVSRMa2.mjs.map +1 -0
  736. package/dist/redirects-BHpy-VsZ.mjs +446 -0
  737. package/dist/redirects-BHpy-VsZ.mjs.map +1 -0
  738. package/dist/registry/testing.mjs +3 -3
  739. package/dist/registry-TUVaid9Z.mjs +8369 -0
  740. package/dist/registry-TUVaid9Z.mjs.map +1 -0
  741. package/dist/relations-CA_QuMTU.mjs +776 -0
  742. package/dist/relations-CA_QuMTU.mjs.map +1 -0
  743. package/dist/request-context.d.mts +1 -1
  744. package/dist/request-meta-bwZ_NsvU.mjs +141 -0
  745. package/dist/request-meta-bwZ_NsvU.mjs.map +1 -0
  746. package/dist/resolve-DwNM-CXl.mjs +101 -0
  747. package/dist/resolve-DwNM-CXl.mjs.map +1 -0
  748. package/dist/revision-BVp8S0e_.mjs +374 -0
  749. package/dist/revision-BVp8S0e_.mjs.map +1 -0
  750. package/dist/route-cache-QSOyDEw0.mjs +20 -0
  751. package/dist/route-cache-QSOyDEw0.mjs.map +1 -0
  752. package/dist/route-wire-Ca_HWCZ5.mjs +197 -0
  753. package/dist/route-wire-Ca_HWCZ5.mjs.map +1 -0
  754. package/dist/routes-BerZFrvV.mjs +272 -0
  755. package/dist/routes-BerZFrvV.mjs.map +1 -0
  756. package/dist/runner-BObHz5FC.d.mts +68 -0
  757. package/dist/runner-BObHz5FC.d.mts.map +1 -0
  758. package/dist/runner-C5NeAkBQ.mjs +6595 -0
  759. package/dist/runner-C5NeAkBQ.mjs.map +1 -0
  760. package/dist/runtime.d.mts +13 -13
  761. package/dist/runtime.mjs +3 -2
  762. package/dist/runtime.mjs.map +1 -1
  763. package/dist/schema/project-env-types.mjs +39 -35
  764. package/dist/schema/project-env-types.mjs.map +1 -1
  765. package/dist/schema-C4OBuv6Z.mjs +13 -0
  766. package/dist/schema-C4OBuv6Z.mjs.map +1 -0
  767. package/dist/schema-DJRfvM_o.mjs +815 -0
  768. package/dist/schema-DJRfvM_o.mjs.map +1 -0
  769. package/dist/scopes-BU03K7Uo.mjs +34 -0
  770. package/dist/scopes-BU03K7Uo.mjs.map +1 -0
  771. package/dist/search-DfVzks89.mjs +450 -0
  772. package/dist/search-DfVzks89.mjs.map +1 -0
  773. package/dist/sections-BMy4JVUz.mjs +346 -0
  774. package/dist/sections-BMy4JVUz.mjs.map +1 -0
  775. package/dist/seed/index.d.mts +2 -2
  776. package/dist/seed/index.mjs +37 -33
  777. package/dist/seo/index.d.mts +3 -3
  778. package/dist/seo/index.mjs +24 -20
  779. package/dist/seo/index.mjs.map +1 -1
  780. package/dist/seo-ClB-dw9w.mjs +188 -0
  781. package/dist/seo-ClB-dw9w.mjs.map +1 -0
  782. package/dist/seo-VZYOEy8f.mjs +133 -0
  783. package/dist/seo-VZYOEy8f.mjs.map +1 -0
  784. package/dist/service-Bo_usgSk.mjs +150 -0
  785. package/dist/service-Bo_usgSk.mjs.map +1 -0
  786. package/dist/session-user-DlpPdf8L.mjs +61 -0
  787. package/dist/session-user-DlpPdf8L.mjs.map +1 -0
  788. package/dist/settings-CWb84sDm.mjs +452 -0
  789. package/dist/settings-CWb84sDm.mjs.map +1 -0
  790. package/dist/settings-DS914jjE.mjs +66 -0
  791. package/dist/settings-DS914jjE.mjs.map +1 -0
  792. package/dist/settings-Dd1uivmQ.mjs +73 -0
  793. package/dist/settings-Dd1uivmQ.mjs.map +1 -0
  794. package/dist/setup-complete-BuNxAUiN.mjs +65 -0
  795. package/dist/setup-complete-BuNxAUiN.mjs.map +1 -0
  796. package/dist/setup-nonce-BnEAX0iy.mjs +25 -0
  797. package/dist/setup-nonce-BnEAX0iy.mjs.map +1 -0
  798. package/dist/site-domain-Bq5j5bVg.mjs +131 -0
  799. package/dist/site-domain-Bq5j5bVg.mjs.map +1 -0
  800. package/dist/site-settings-DRHfX7bq.mjs +50 -0
  801. package/dist/site-settings-DRHfX7bq.mjs.map +1 -0
  802. package/dist/site-url-MB685I5X.mjs +45 -0
  803. package/dist/site-url-MB685I5X.mjs.map +1 -0
  804. package/dist/sitemap-name-BTg2NJJv.mjs +26 -0
  805. package/dist/sitemap-name-BTg2NJJv.mjs.map +1 -0
  806. package/dist/slug-aVnUV4SL.mjs +16 -0
  807. package/dist/slug-aVnUV4SL.mjs.map +1 -0
  808. package/dist/snapshot-DYsG4uOq.mjs +414 -0
  809. package/dist/snapshot-DYsG4uOq.mjs.map +1 -0
  810. package/dist/ssrf-BcYjyM4M.mjs +406 -0
  811. package/dist/ssrf-BcYjyM4M.mjs.map +1 -0
  812. package/dist/stage-D8DWgPcO.mjs +662 -0
  813. package/dist/stage-D8DWgPcO.mjs.map +1 -0
  814. package/dist/staged-CD_imitH.mjs +686 -0
  815. package/dist/staged-CD_imitH.mjs.map +1 -0
  816. package/dist/state-CFbGZziM.mjs +178 -0
  817. package/dist/state-CFbGZziM.mjs.map +1 -0
  818. package/dist/status-BFNdxzKc.mjs +30 -0
  819. package/dist/status-BFNdxzKc.mjs.map +1 -0
  820. package/dist/storage/local.d.mts +1 -1
  821. package/dist/storage/local.mjs +3 -3
  822. package/dist/storage/s3.d.mts +1 -1
  823. package/dist/storage/s3.mjs +1 -1
  824. package/dist/storage-query-DRyu3bSU.d.mts +1615 -0
  825. package/dist/storage-query-DRyu3bSU.d.mts.map +1 -0
  826. package/dist/tar-DFjExb9X.mjs +449 -0
  827. package/dist/tar-DFjExb9X.mjs.map +1 -0
  828. package/dist/target-CWZs2-o6.mjs +27 -0
  829. package/dist/target-CWZs2-o6.mjs.map +1 -0
  830. package/dist/taxonomies-ChnU7Mc8.mjs +697 -0
  831. package/dist/taxonomies-ChnU7Mc8.mjs.map +1 -0
  832. package/dist/taxonomies-Dd9JJv_a.mjs +939 -0
  833. package/dist/taxonomies-Dd9JJv_a.mjs.map +1 -0
  834. package/dist/taxonomy-C_C_LBAU.mjs +550 -0
  835. package/dist/taxonomy-C_C_LBAU.mjs.map +1 -0
  836. package/dist/tokens-BnhSnGwJ.mjs +171 -0
  837. package/dist/tokens-BnhSnGwJ.mjs.map +1 -0
  838. package/dist/transfer-ClH6w6BV.mjs +8873 -0
  839. package/dist/transfer-ClH6w6BV.mjs.map +1 -0
  840. package/dist/transfer-WmWiR3xf.mjs +166 -0
  841. package/dist/transfer-WmWiR3xf.mjs.map +1 -0
  842. package/dist/transfer-download--ofRj9Cw.mjs +33 -0
  843. package/dist/transfer-download--ofRj9Cw.mjs.map +1 -0
  844. package/dist/transformations-Bx4lYY0Y.mjs +196 -0
  845. package/dist/transformations-Bx4lYY0Y.mjs.map +1 -0
  846. package/dist/transport-BjbqNiPI.mjs +136 -0
  847. package/dist/transport-BjbqNiPI.mjs.map +1 -0
  848. package/dist/transport-DxiXnbXk.d.mts +42 -0
  849. package/dist/transport-DxiXnbXk.d.mts.map +1 -0
  850. package/dist/trusted-proxy-BU3Nx9g1.mjs +51 -0
  851. package/dist/trusted-proxy-BU3Nx9g1.mjs.map +1 -0
  852. package/dist/turnstile-CJwvsOqw.mjs +58 -0
  853. package/dist/turnstile-CJwvsOqw.mjs.map +1 -0
  854. package/dist/types-BA3ey2QH.d.mts +87 -0
  855. package/dist/types-BA3ey2QH.d.mts.map +1 -0
  856. package/dist/types-Bwpzb5o6.d.mts +227 -0
  857. package/dist/types-Bwpzb5o6.d.mts.map +1 -0
  858. package/dist/types-CNB-dj6F.d.mts +289 -0
  859. package/dist/types-CNB-dj6F.d.mts.map +1 -0
  860. package/dist/types-CgfFGfO5.mjs +16 -0
  861. package/dist/types-CgfFGfO5.mjs.map +1 -0
  862. package/dist/types-D2NEXtgB.mjs +127 -0
  863. package/dist/types-D2NEXtgB.mjs.map +1 -0
  864. package/dist/types-DCFavOii.d.mts +916 -0
  865. package/dist/types-DCFavOii.d.mts.map +1 -0
  866. package/dist/types-DHO7Pd25.d.mts +366 -0
  867. package/dist/types-DHO7Pd25.d.mts.map +1 -0
  868. package/dist/types-DvqVxZXa.d.mts +125 -0
  869. package/dist/types-DvqVxZXa.d.mts.map +1 -0
  870. package/dist/types-QoPHm-2w.d.mts +1741 -0
  871. package/dist/types-QoPHm-2w.d.mts.map +1 -0
  872. package/dist/types-RLgeIpnF.d.mts +374 -0
  873. package/dist/types-RLgeIpnF.d.mts.map +1 -0
  874. package/dist/types-qHVygneX.mjs +77 -0
  875. package/dist/types-qHVygneX.mjs.map +1 -0
  876. package/dist/types-sUHaH7lC.mjs +37 -0
  877. package/dist/types-sUHaH7lC.mjs.map +1 -0
  878. package/dist/types-slSqujQL.d.mts +204 -0
  879. package/dist/types-slSqujQL.d.mts.map +1 -0
  880. package/dist/update-check-BxNg9T6N.mjs +161 -0
  881. package/dist/update-check-BxNg9T6N.mjs.map +1 -0
  882. package/dist/upload-attempts-DPFC4COv.mjs +32 -0
  883. package/dist/upload-attempts-DPFC4COv.mjs.map +1 -0
  884. package/dist/url-pattern-QATUE_rv.mjs +41 -0
  885. package/dist/url-pattern-QATUE_rv.mjs.map +1 -0
  886. package/dist/user-BlCTKVAm.mjs +171 -0
  887. package/dist/user-BlCTKVAm.mjs.map +1 -0
  888. package/dist/utils-TPt7w2cS.mjs +442 -0
  889. package/dist/utils-TPt7w2cS.mjs.map +1 -0
  890. package/dist/validate-DxYhJQA-.mjs +524 -0
  891. package/dist/validate-DxYhJQA-.mjs.map +1 -0
  892. package/dist/validate-emKxGC5F.d.mts +468 -0
  893. package/dist/validate-emKxGC5F.d.mts.map +1 -0
  894. package/dist/validation-Ckq4vsVg.mjs +220 -0
  895. package/dist/validation-Ckq4vsVg.mjs.map +1 -0
  896. package/dist/version-BZj18Q7G.mjs +9 -0
  897. package/dist/version-BZj18Q7G.mjs.map +1 -0
  898. package/dist/version-DHmGpcch.mjs +7 -0
  899. package/dist/version-DHmGpcch.mjs.map +1 -0
  900. package/dist/video-DytCnw3L.mjs +54 -0
  901. package/dist/video-DytCnw3L.mjs.map +1 -0
  902. package/dist/virtual-modules-DO954n7P.mjs +515 -0
  903. package/dist/virtual-modules-DO954n7P.mjs.map +1 -0
  904. package/dist/widgets-DA5XmvVC.mjs +121 -0
  905. package/dist/widgets-DA5XmvVC.mjs.map +1 -0
  906. package/dist/wxr-taxonomies-CrMonejI.d.mts +34 -0
  907. package/dist/wxr-taxonomies-CrMonejI.d.mts.map +1 -0
  908. package/dist/wxr-taxonomies-RgRG0d5e.mjs +453 -0
  909. package/dist/wxr-taxonomies-RgRG0d5e.mjs.map +1 -0
  910. package/dist/zod-generator-D0JKy94C.mjs +424 -0
  911. package/dist/zod-generator-D0JKy94C.mjs.map +1 -0
  912. package/package.json +7 -6
  913. package/src/api/authorize.ts +42 -0
  914. package/src/api/handlers/dashboard.ts +33 -10
  915. package/src/api/handlers/manifest.ts +1 -0
  916. package/src/api/handlers/plugins.ts +1 -0
  917. package/src/api/handlers/revision.ts +6 -2
  918. package/src/api/handlers/site-domain.ts +26 -10
  919. package/src/api/schemas/settings.ts +2 -0
  920. package/src/api/types.ts +2 -0
  921. package/src/astro/integration/dev-scheduler-bridge.ts +91 -0
  922. package/src/astro/integration/index.ts +48 -1
  923. package/src/astro/integration/routes.ts +8 -0
  924. package/src/astro/integration/runtime.ts +2 -1
  925. package/src/astro/integration/virtual-modules.ts +9 -16
  926. package/src/astro/integration/vite-config.ts +4 -15
  927. package/src/astro/middleware/auth.ts +3 -1
  928. package/src/astro/middleware/redirect.ts +71 -42
  929. package/src/astro/middleware.ts +18 -3
  930. package/src/astro/prefetch.ts +7 -5
  931. package/src/astro/public-plugin-api-routes.ts +10 -2
  932. package/src/astro/routes/api/admin/plugins/registry/artifact.ts +1 -1
  933. package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +2 -1
  934. package/src/astro/routes/api/content/[collection]/[id]/duplicate.ts +1 -5
  935. package/src/astro/routes/api/content/[collection]/[id]/lock.ts +2 -2
  936. package/src/astro/routes/api/content/[collection]/[id]/permanent.ts +2 -1
  937. package/src/astro/routes/api/content/[collection]/[id]/publish.ts +2 -1
  938. package/src/astro/routes/api/content/[collection]/[id]/restore.ts +2 -1
  939. package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +3 -2
  940. package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +5 -4
  941. package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +2 -1
  942. package/src/astro/routes/api/content/[collection]/[id].ts +18 -6
  943. package/src/astro/routes/api/content/[collection]/index.ts +1 -5
  944. package/src/astro/routes/api/dashboard.ts +4 -1
  945. package/src/astro/routes/api/dev/scheduled-tasks.ts +20 -0
  946. package/src/astro/routes/api/import/wordpress/analyze.ts +1 -16
  947. package/src/astro/routes/api/import/wordpress/execute.ts +8 -3
  948. package/src/astro/routes/api/import/wordpress-plugin/analyze.ts +4 -1
  949. package/src/astro/routes/api/import/wordpress-plugin/execute.ts +34 -5
  950. package/src/astro/routes/api/menus/[name]/items/[id].ts +3 -2
  951. package/src/astro/routes/api/menus/[name]/items.ts +2 -1
  952. package/src/astro/routes/api/menus/[name]/reorder.ts +2 -1
  953. package/src/astro/routes/api/menus/[name]/translations.ts +2 -1
  954. package/src/astro/routes/api/menus/[name].ts +3 -2
  955. package/src/astro/routes/api/menus/index.ts +2 -1
  956. package/src/astro/routes/api/redirects/[id].ts +15 -2
  957. package/src/astro/routes/api/redirects/index.ts +5 -1
  958. package/src/astro/routes/api/settings/domain.ts +2 -1
  959. package/src/astro/routes/api/settings.ts +2 -1
  960. package/src/astro/routes/api/setup/admin-verify.ts +7 -1
  961. package/src/astro/routes/api/taxonomies/[name]/reorder.ts +2 -1
  962. package/src/astro/routes/api/taxonomies/[name]/terms/[slug]/translations.ts +2 -1
  963. package/src/astro/routes/api/taxonomies/[name]/terms/[slug].ts +3 -2
  964. package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +2 -1
  965. package/src/astro/routes/api/taxonomies/[name].ts +3 -2
  966. package/src/astro/routes/api/taxonomies/index.ts +2 -1
  967. package/src/astro/routes/api/widget-areas/[name]/reorder.ts +2 -1
  968. package/src/astro/routes/api/widget-areas/[name]/widgets/[id].ts +3 -2
  969. package/src/astro/routes/api/widget-areas/[name]/widgets.ts +2 -1
  970. package/src/astro/routes/api/widget-areas/[name].ts +2 -1
  971. package/src/astro/routes/api/widget-areas/index.ts +2 -1
  972. package/src/astro/routes/robots.txt.ts +33 -2
  973. package/src/astro/types.ts +10 -1
  974. package/src/auth/types.ts +4 -4
  975. package/src/cache/redirect-paths.ts +56 -0
  976. package/src/cache/route-cache.ts +22 -0
  977. package/src/cli/commands/import/wordpress.ts +3 -27
  978. package/src/cli/commands/login.ts +35 -43
  979. package/src/cli/commands/migrate.ts +36 -4
  980. package/src/cli/commands/seed.ts +18 -8
  981. package/src/cli/wxr/parser.ts +2 -2
  982. package/src/client/index.ts +12 -2
  983. package/src/client/portable-text.ts +21 -7
  984. package/src/comments/query.ts +8 -2
  985. package/src/components/CommentForm.astro +2 -2
  986. package/src/components/Comments.astro +1 -1
  987. package/src/components/InlinePortableTextEditor.tsx +152 -1325
  988. package/src/components/inline-block-types.ts +278 -0
  989. package/src/components/inline-bubble-menu.tsx +696 -0
  990. package/src/components/inline-editor-ui.tsx +1192 -0
  991. package/src/components/inline-image.tsx +722 -0
  992. package/src/components/inline-media-picker.tsx +1221 -0
  993. package/src/components/inline-slash-menu.tsx +556 -0
  994. package/src/database/collection-cleanup.ts +30 -0
  995. package/src/database/datetime-storage.ts +337 -60
  996. package/src/database/migration-lock.ts +43 -7
  997. package/src/database/repositories/content.ts +3 -1
  998. package/src/database/repositories/plugin-storage.ts +109 -8
  999. package/src/database/repositories/revision.ts +24 -6
  1000. package/src/database/repositories/types.ts +65 -7
  1001. package/src/emdash-runtime.ts +176 -160
  1002. package/src/import/index.ts +1 -0
  1003. package/src/import/registry.ts +17 -0
  1004. package/src/import/sources/wordpress-plugin.ts +151 -9
  1005. package/src/import/types.ts +3 -0
  1006. package/src/import/utils.ts +5 -0
  1007. package/src/loader.ts +36 -2
  1008. package/src/mcp/json-schema.ts +14 -0
  1009. package/src/mcp/plugin-tool-name.ts +36 -0
  1010. package/src/mcp/server.ts +74 -15
  1011. package/src/media/usage/collection-deletion.ts +4 -0
  1012. package/src/migrations/direct-executor.ts +42 -12
  1013. package/src/migrations/protocol.ts +6 -2
  1014. package/src/plugins/adapt-sandbox-entry.ts +16 -6
  1015. package/src/plugins/state.ts +5 -8
  1016. package/src/query.ts +51 -10
  1017. package/src/redirects/cache.ts +34 -2
  1018. package/src/schema/block-values.ts +80 -17
  1019. package/src/schema/registry.ts +9 -1
  1020. package/src/search/query.ts +3 -1
  1021. package/src/seed/apply.ts +32 -8
  1022. package/src/settings/index.ts +20 -0
  1023. package/src/settings/types.ts +2 -0
  1024. package/src/visual-editing/toolbar.ts +46 -12
  1025. package/dist/action-token-BdWad2YG.mjs +0 -26
  1026. package/dist/action-token-BdWad2YG.mjs.map +0 -1
  1027. package/dist/activation-xomsCMJg.mjs +0 -387
  1028. package/dist/activation-xomsCMJg.mjs.map +0 -1
  1029. package/dist/adapters-B4-nbElt.d.mts +0 -173
  1030. package/dist/adapters-B4-nbElt.d.mts.map +0 -1
  1031. package/dist/allowed-origins-CLpHGGlc.mjs +0 -116
  1032. package/dist/allowed-origins-CLpHGGlc.mjs.map +0 -1
  1033. package/dist/api-DBw_IWoi.mjs +0 -5024
  1034. package/dist/api-DBw_IWoi.mjs.map +0 -1
  1035. package/dist/api-tokens-B0ZipcZ-.mjs +0 -173
  1036. package/dist/api-tokens-B0ZipcZ-.mjs.map +0 -1
  1037. package/dist/apply-Cx48saFC.mjs +0 -1680
  1038. package/dist/apply-Cx48saFC.mjs.map +0 -1
  1039. package/dist/approvals-BXgtXA2s.mjs +0 -460
  1040. package/dist/approvals-BXgtXA2s.mjs.map +0 -1
  1041. package/dist/artifact-fetch-DsRczRGG.mjs +0 -659
  1042. package/dist/artifact-fetch-DsRczRGG.mjs.map +0 -1
  1043. package/dist/artifacts-D-O-qj9C.mjs +0 -307
  1044. package/dist/artifacts-D-O-qj9C.mjs.map +0 -1
  1045. package/dist/audit-CCH3MA4Y.mjs +0 -127
  1046. package/dist/audit-CCH3MA4Y.mjs.map +0 -1
  1047. package/dist/authoritative-records-Dcs7l2H5.mjs +0 -5183
  1048. package/dist/authoritative-records-Dcs7l2H5.mjs.map +0 -1
  1049. package/dist/authorize-TdIGpRSE.mjs +0 -49
  1050. package/dist/authorize-TdIGpRSE.mjs.map +0 -1
  1051. package/dist/backup-CZt5Mzwx.mjs +0 -246
  1052. package/dist/backup-CZt5Mzwx.mjs.map +0 -1
  1053. package/dist/block-types-DHnkzE6u.mjs +0 -132
  1054. package/dist/block-types-DHnkzE6u.mjs.map +0 -1
  1055. package/dist/block-values-C4N_F2-G.mjs +0 -175
  1056. package/dist/block-values-C4N_F2-G.mjs.map +0 -1
  1057. package/dist/byline-BmVKOQ8l.mjs +0 -909
  1058. package/dist/byline-BmVKOQ8l.mjs.map +0 -1
  1059. package/dist/byline-fields-B8SDs3M_.mjs +0 -123
  1060. package/dist/byline-fields-B8SDs3M_.mjs.map +0 -1
  1061. package/dist/byline-fields-Bze3ZdAw.mjs +0 -280
  1062. package/dist/byline-fields-Bze3ZdAw.mjs.map +0 -1
  1063. package/dist/bylines-CHhR28r9.mjs +0 -150
  1064. package/dist/bylines-CHhR28r9.mjs.map +0 -1
  1065. package/dist/bylines-DZS4OflA.mjs +0 -234
  1066. package/dist/bylines-DZS4OflA.mjs.map +0 -1
  1067. package/dist/cache-x0z8t_m9.mjs +0 -133
  1068. package/dist/cache-x0z8t_m9.mjs.map +0 -1
  1069. package/dist/canonical-BUcKRYpG.mjs +0 -174
  1070. package/dist/canonical-BUcKRYpG.mjs.map +0 -1
  1071. package/dist/capture-triggers-C9JKoIdT.mjs +0 -362
  1072. package/dist/capture-triggers-C9JKoIdT.mjs.map +0 -1
  1073. package/dist/challenge-store-BHgdPVze.mjs +0 -51
  1074. package/dist/challenge-store-BHgdPVze.mjs.map +0 -1
  1075. package/dist/checksum-BYR5i7qe.mjs +0 -162
  1076. package/dist/checksum-BYR5i7qe.mjs.map +0 -1
  1077. package/dist/chunks-Dr5Vr0zA.mjs +0 -25
  1078. package/dist/chunks-Dr5Vr0zA.mjs.map +0 -1
  1079. package/dist/collection-slugs-cache-B2Gs9Jwx.mjs +0 -85
  1080. package/dist/collection-slugs-cache-B2Gs9Jwx.mjs.map +0 -1
  1081. package/dist/comment-CWla6OHV.mjs +0 -325
  1082. package/dist/comment-CWla6OHV.mjs.map +0 -1
  1083. package/dist/comment-reaction-RZrcs5cW.mjs +0 -85
  1084. package/dist/comment-reaction-RZrcs5cW.mjs.map +0 -1
  1085. package/dist/comments-BzmIKVb2.mjs +0 -99
  1086. package/dist/comments-BzmIKVb2.mjs.map +0 -1
  1087. package/dist/comments-Da_dI2O1.mjs +0 -195
  1088. package/dist/comments-Da_dI2O1.mjs.map +0 -1
  1089. package/dist/components-oFXumpf5.mjs +0 -112
  1090. package/dist/components-oFXumpf5.mjs.map +0 -1
  1091. package/dist/config--wamYxBW.d.mts +0 -39
  1092. package/dist/config--wamYxBW.d.mts.map +0 -1
  1093. package/dist/config-Bo4eOOdV.mjs +0 -228
  1094. package/dist/config-Bo4eOOdV.mjs.map +0 -1
  1095. package/dist/config-C4-UxIk7.d.mts +0 -6790
  1096. package/dist/config-C4-UxIk7.d.mts.map +0 -1
  1097. package/dist/connection-UpzYxtE2.mjs +0 -36
  1098. package/dist/connection-UpzYxtE2.mjs.map +0 -1
  1099. package/dist/content-CcHrqkgp.mjs +0 -2072
  1100. package/dist/content-CcHrqkgp.mjs.map +0 -1
  1101. package/dist/content-list-query-Bxxdd9fv.d.mts +0 -26
  1102. package/dist/content-list-query-Bxxdd9fv.d.mts.map +0 -1
  1103. package/dist/content-repair-havk1F0-.mjs +0 -442
  1104. package/dist/content-repair-havk1F0-.mjs.map +0 -1
  1105. package/dist/context-CvhgHgSH.mjs +0 -2043
  1106. package/dist/context-CvhgHgSH.mjs.map +0 -1
  1107. package/dist/credits-CygUrPOi.mjs +0 -110
  1108. package/dist/credits-CygUrPOi.mjs.map +0 -1
  1109. package/dist/cron-C6ytTOLw.mjs +0 -306
  1110. package/dist/cron-C6ytTOLw.mjs.map +0 -1
  1111. package/dist/dashboard-7_FYfafc.mjs +0 -151
  1112. package/dist/dashboard-7_FYfafc.mjs.map +0 -1
  1113. package/dist/default-CHCUkV4Z.mjs +0 -81
  1114. package/dist/default-CHCUkV4Z.mjs.map +0 -1
  1115. package/dist/deferred-tasks-G0xhcJTl.d.mts +0 -9
  1116. package/dist/deferred-tasks-G0xhcJTl.d.mts.map +0 -1
  1117. package/dist/dev-typegen-Dtl8AfS6.mjs +0 -29
  1118. package/dist/dev-typegen-Dtl8AfS6.mjs.map +0 -1
  1119. package/dist/device-flow-CzDJmQ1q.mjs +0 -521
  1120. package/dist/device-flow-CzDJmQ1q.mjs.map +0 -1
  1121. package/dist/digest-xJmyPv2r.mjs +0 -194
  1122. package/dist/digest-xJmyPv2r.mjs.map +0 -1
  1123. package/dist/direct-executor-BXiYIVJ9.mjs +0 -104
  1124. package/dist/direct-executor-BXiYIVJ9.mjs.map +0 -1
  1125. package/dist/email-console-7ZPApLlm.mjs +0 -50
  1126. package/dist/email-console-7ZPApLlm.mjs.map +0 -1
  1127. package/dist/email-locale-DFdUA6UF.mjs +0 -25
  1128. package/dist/email-locale-DFdUA6UF.mjs.map +0 -1
  1129. package/dist/emdash-runtime-C4oFeVpN.mjs +0 -4363
  1130. package/dist/emdash-runtime-C4oFeVpN.mjs.map +0 -1
  1131. package/dist/entry-lock-B4n0HdQ_.mjs +0 -163
  1132. package/dist/entry-lock-B4n0HdQ_.mjs.map +0 -1
  1133. package/dist/entry-lock-BAAlKYrz.d.mts +0 -4566
  1134. package/dist/entry-lock-BAAlKYrz.d.mts.map +0 -1
  1135. package/dist/entry-lock-Cjz0h45X.mjs +0 -1209
  1136. package/dist/entry-lock-Cjz0h45X.mjs.map +0 -1
  1137. package/dist/env-types-4bkF6Bqg.mjs +0 -38
  1138. package/dist/env-types-4bkF6Bqg.mjs.map +0 -1
  1139. package/dist/error-DxgQdaZ_.mjs +0 -90
  1140. package/dist/error-DxgQdaZ_.mjs.map +0 -1
  1141. package/dist/errors-CjtE5aWF.mjs +0 -120
  1142. package/dist/errors-CjtE5aWF.mjs.map +0 -1
  1143. package/dist/errors-hskQ0C8G.mjs +0 -479
  1144. package/dist/errors-hskQ0C8G.mjs.map +0 -1
  1145. package/dist/escape-ESFhYzwG.mjs +0 -9
  1146. package/dist/escape-ESFhYzwG.mjs.map +0 -1
  1147. package/dist/fence-vc3aHgRA.mjs +0 -162
  1148. package/dist/fence-vc3aHgRA.mjs.map +0 -1
  1149. package/dist/field-defs-cache-zoow36nz.mjs +0 -77
  1150. package/dist/field-defs-cache-zoow36nz.mjs.map +0 -1
  1151. package/dist/field-map-JD1wG0Tq.mjs +0 -83
  1152. package/dist/field-map-JD1wG0Tq.mjs.map +0 -1
  1153. package/dist/fts-manager-WJCN8uU6.mjs +0 -443
  1154. package/dist/fts-manager-WJCN8uU6.mjs.map +0 -1
  1155. package/dist/gc-CsGZiKdH.mjs +0 -75
  1156. package/dist/gc-CsGZiKdH.mjs.map +0 -1
  1157. package/dist/hash-C4DFoJ7Z.mjs +0 -37
  1158. package/dist/hash-C4DFoJ7Z.mjs.map +0 -1
  1159. package/dist/hook-result-CXjtMk7Q.d.mts +0 -31
  1160. package/dist/hook-result-CXjtMk7Q.d.mts.map +0 -1
  1161. package/dist/hreflang-BAma7iRr.mjs +0 -105
  1162. package/dist/hreflang-BAma7iRr.mjs.map +0 -1
  1163. package/dist/hreflang-BsYo4x_M.d.mts +0 -50
  1164. package/dist/hreflang-BsYo4x_M.d.mts.map +0 -1
  1165. package/dist/http-route-dispatch-C8G7hAK6.mjs +0 -342
  1166. package/dist/http-route-dispatch-C8G7hAK6.mjs.map +0 -1
  1167. package/dist/identity-BwBKM1fH.mjs +0 -35
  1168. package/dist/identity-BwBKM1fH.mjs.map +0 -1
  1169. package/dist/import-DJ3Z2wxE.mjs +0 -2021
  1170. package/dist/import-DJ3Z2wxE.mjs.map +0 -1
  1171. package/dist/index-DYsn97dY.d.mts +0 -623
  1172. package/dist/index-DYsn97dY.d.mts.map +0 -1
  1173. package/dist/install-finalization-DCFnFSHv.mjs +0 -58
  1174. package/dist/install-finalization-DCFnFSHv.mjs.map +0 -1
  1175. package/dist/keys-CGvAndSp.mjs +0 -61
  1176. package/dist/keys-CGvAndSp.mjs.map +0 -1
  1177. package/dist/kinds-DT1W4T4Y.mjs +0 -974
  1178. package/dist/kinds-DT1W4T4Y.mjs.map +0 -1
  1179. package/dist/lifecycle-BzglCSY0.mjs +0 -25
  1180. package/dist/lifecycle-BzglCSY0.mjs.map +0 -1
  1181. package/dist/load-DjUqmf3s.mjs +0 -28
  1182. package/dist/load-DjUqmf3s.mjs.map +0 -1
  1183. package/dist/loader-CetY659y.mjs +0 -1355
  1184. package/dist/loader-CetY659y.mjs.map +0 -1
  1185. package/dist/loops-DkT1zkPH.mjs +0 -205
  1186. package/dist/loops-DkT1zkPH.mjs.map +0 -1
  1187. package/dist/manifest-builder-BOFCd9rX.mjs +0 -189
  1188. package/dist/manifest-builder-BOFCd9rX.mjs.map +0 -1
  1189. package/dist/manifest-schema-BiFBPEsp.mjs +0 -497
  1190. package/dist/manifest-schema-BiFBPEsp.mjs.map +0 -1
  1191. package/dist/marketplace-CUlenvZm.mjs +0 -257
  1192. package/dist/marketplace-CUlenvZm.mjs.map +0 -1
  1193. package/dist/media-CRKsKlfK.mjs +0 -416
  1194. package/dist/media-CRKsKlfK.mjs.map +0 -1
  1195. package/dist/media-C_z7sRuC.mjs +0 -294
  1196. package/dist/media-C_z7sRuC.mjs.map +0 -1
  1197. package/dist/media-IT8hQleU.mjs +0 -373
  1198. package/dist/media-IT8hQleU.mjs.map +0 -1
  1199. package/dist/media-allowlist-Ct6wvnT2.mjs +0 -45
  1200. package/dist/media-allowlist-Ct6wvnT2.mjs.map +0 -1
  1201. package/dist/media-folders-DtMt-vAA.mjs +0 -210
  1202. package/dist/media-folders-DtMt-vAA.mjs.map +0 -1
  1203. package/dist/media-url-BpXLqCmf.mjs +0 -43
  1204. package/dist/media-url-BpXLqCmf.mjs.map +0 -1
  1205. package/dist/media-usage-DEPHZZ9X.mjs +0 -282
  1206. package/dist/media-usage-DEPHZZ9X.mjs.map +0 -1
  1207. package/dist/media-usage-activation-V2Siabtw.mjs +0 -78
  1208. package/dist/media-usage-activation-V2Siabtw.mjs.map +0 -1
  1209. package/dist/media-usage-work-Cv1OE59F.mjs +0 -151
  1210. package/dist/media-usage-work-Cv1OE59F.mjs.map +0 -1
  1211. package/dist/media-usage-work-cgDYGvrt.mjs +0 -1015
  1212. package/dist/media-usage-work-cgDYGvrt.mjs.map +0 -1
  1213. package/dist/menus-CvVYfsuk.mjs +0 -753
  1214. package/dist/menus-CvVYfsuk.mjs.map +0 -1
  1215. package/dist/menus-D1HC8npj.mjs +0 -92
  1216. package/dist/menus-D1HC8npj.mjs.map +0 -1
  1217. package/dist/menus-DL8IPIcm.mjs +0 -3721
  1218. package/dist/menus-DL8IPIcm.mjs.map +0 -1
  1219. package/dist/mode-eieqAWLe.mjs +0 -23
  1220. package/dist/mode-eieqAWLe.mjs.map +0 -1
  1221. package/dist/node-sqlite-compat-VuyzJw1b.mjs +0 -63
  1222. package/dist/node-sqlite-compat-VuyzJw1b.mjs.map +0 -1
  1223. package/dist/oauth-authorization-B6ZJbMd2.mjs +0 -274
  1224. package/dist/oauth-authorization-B6ZJbMd2.mjs.map +0 -1
  1225. package/dist/oauth-clients-DVjRc9v3.mjs +0 -266
  1226. package/dist/oauth-clients-DVjRc9v3.mjs.map +0 -1
  1227. package/dist/oauth-state-store-CnmYYsVQ.mjs +0 -50
  1228. package/dist/oauth-state-store-CnmYYsVQ.mjs.map +0 -1
  1229. package/dist/oauth-user-lookup-Dz1_R5vT.mjs +0 -26
  1230. package/dist/oauth-user-lookup-Dz1_R5vT.mjs.map +0 -1
  1231. package/dist/options-BR9XZl7h.d.mts +0 -81
  1232. package/dist/options-BR9XZl7h.d.mts.map +0 -1
  1233. package/dist/ownership-COPyVysP.mjs +0 -12
  1234. package/dist/ownership-COPyVysP.mjs.map +0 -1
  1235. package/dist/parse-BOGhrwSq.d.mts +0 -174
  1236. package/dist/parse-BOGhrwSq.d.mts.map +0 -1
  1237. package/dist/parse-Cn5aSk1N.mjs +0 -81
  1238. package/dist/parse-Cn5aSk1N.mjs.map +0 -1
  1239. package/dist/passkey-config-mMFRQUCj.mjs +0 -46
  1240. package/dist/passkey-config-mMFRQUCj.mjs.map +0 -1
  1241. package/dist/paths-BmcAdBo9.mjs +0 -77
  1242. package/dist/paths-BmcAdBo9.mjs.map +0 -1
  1243. package/dist/placeholder-nOep3_Gn.d.mts +0 -306
  1244. package/dist/placeholder-nOep3_Gn.d.mts.map +0 -1
  1245. package/dist/plan-CDY4K8CH.mjs +0 -135
  1246. package/dist/plan-CDY4K8CH.mjs.map +0 -1
  1247. package/dist/plugins-DFBpfbO3.mjs +0 -261
  1248. package/dist/plugins-DFBpfbO3.mjs.map +0 -1
  1249. package/dist/policy-B_2qnHSy.mjs +0 -45
  1250. package/dist/policy-B_2qnHSy.mjs.map +0 -1
  1251. package/dist/portable-text-Dc2YAusw.mjs +0 -307
  1252. package/dist/portable-text-Dc2YAusw.mjs.map +0 -1
  1253. package/dist/preview-BtzikJ9O.mjs +0 -107
  1254. package/dist/preview-BtzikJ9O.mjs.map +0 -1
  1255. package/dist/protocol-M268ox8L.d.mts +0 -61
  1256. package/dist/protocol-M268ox8L.d.mts.map +0 -1
  1257. package/dist/public-submission-BQZavgZU.mjs +0 -251
  1258. package/dist/public-submission-BQZavgZU.mjs.map +0 -1
  1259. package/dist/public-url-uT1Ok2Tu.mjs +0 -101
  1260. package/dist/public-url-uT1Ok2Tu.mjs.map +0 -1
  1261. package/dist/query-BGG3sDEd.mjs +0 -1127
  1262. package/dist/query-BGG3sDEd.mjs.map +0 -1
  1263. package/dist/query-C_CWlifp.mjs +0 -41
  1264. package/dist/query-C_CWlifp.mjs.map +0 -1
  1265. package/dist/range-CXK_kDbI.mjs +0 -51
  1266. package/dist/range-CXK_kDbI.mjs.map +0 -1
  1267. package/dist/rate-limit-Dvamvay-.mjs +0 -127
  1268. package/dist/rate-limit-Dvamvay-.mjs.map +0 -1
  1269. package/dist/receipt-BmQGzquP.mjs +0 -43
  1270. package/dist/receipt-BmQGzquP.mjs.map +0 -1
  1271. package/dist/redirect-B39kTQ_0.mjs +0 -423
  1272. package/dist/redirect-B39kTQ_0.mjs.map +0 -1
  1273. package/dist/redirect-BguJ00Pv.mjs +0 -19
  1274. package/dist/redirect-BguJ00Pv.mjs.map +0 -1
  1275. package/dist/redirects-C8G4BsfP.mjs +0 -446
  1276. package/dist/redirects-C8G4BsfP.mjs.map +0 -1
  1277. package/dist/redirects-DFT7Wr-e.mjs +0 -148
  1278. package/dist/redirects-DFT7Wr-e.mjs.map +0 -1
  1279. package/dist/registry-DeZ27gVi.mjs +0 -8374
  1280. package/dist/registry-DeZ27gVi.mjs.map +0 -1
  1281. package/dist/relations-DBB1bRJW.mjs +0 -776
  1282. package/dist/relations-DBB1bRJW.mjs.map +0 -1
  1283. package/dist/request-meta-BSvkhIBX.mjs +0 -141
  1284. package/dist/request-meta-BSvkhIBX.mjs.map +0 -1
  1285. package/dist/resolve-BxH64HN9.mjs +0 -100
  1286. package/dist/resolve-BxH64HN9.mjs.map +0 -1
  1287. package/dist/revision-BWEH2qQB.mjs +0 -368
  1288. package/dist/revision-BWEH2qQB.mjs.map +0 -1
  1289. package/dist/route-wire-CwbWB_6O.mjs +0 -197
  1290. package/dist/route-wire-CwbWB_6O.mjs.map +0 -1
  1291. package/dist/routes-BfIxc7ft.mjs +0 -272
  1292. package/dist/routes-BfIxc7ft.mjs.map +0 -1
  1293. package/dist/runner-DkeafPBA.d.mts +0 -68
  1294. package/dist/runner-DkeafPBA.d.mts.map +0 -1
  1295. package/dist/runner-wqt4BrIW.mjs +0 -6383
  1296. package/dist/runner-wqt4BrIW.mjs.map +0 -1
  1297. package/dist/schema-BXIW-JHi.mjs +0 -815
  1298. package/dist/schema-BXIW-JHi.mjs.map +0 -1
  1299. package/dist/schema-I74JwYte.mjs +0 -13
  1300. package/dist/schema-I74JwYte.mjs.map +0 -1
  1301. package/dist/scopes-RWZ5ft_Z.mjs +0 -34
  1302. package/dist/scopes-RWZ5ft_Z.mjs.map +0 -1
  1303. package/dist/search-DxwagyWS.mjs +0 -450
  1304. package/dist/search-DxwagyWS.mjs.map +0 -1
  1305. package/dist/sections-Ccq9ZgyD.mjs +0 -346
  1306. package/dist/sections-Ccq9ZgyD.mjs.map +0 -1
  1307. package/dist/seo-CCnfPWAQ.mjs +0 -133
  1308. package/dist/seo-CCnfPWAQ.mjs.map +0 -1
  1309. package/dist/seo-QCtJ1jjV.mjs +0 -188
  1310. package/dist/seo-QCtJ1jjV.mjs.map +0 -1
  1311. package/dist/service-DX84s2rw.mjs +0 -150
  1312. package/dist/service-DX84s2rw.mjs.map +0 -1
  1313. package/dist/session-user-1dtJc2zv.mjs +0 -61
  1314. package/dist/session-user-1dtJc2zv.mjs.map +0 -1
  1315. package/dist/settings-B1jOxAIl.mjs +0 -443
  1316. package/dist/settings-B1jOxAIl.mjs.map +0 -1
  1317. package/dist/settings-Bc1IBl1t.mjs +0 -66
  1318. package/dist/settings-Bc1IBl1t.mjs.map +0 -1
  1319. package/dist/settings-GaZ5sVgg.mjs +0 -73
  1320. package/dist/settings-GaZ5sVgg.mjs.map +0 -1
  1321. package/dist/setup-complete-DidMAWJS.mjs +0 -65
  1322. package/dist/setup-complete-DidMAWJS.mjs.map +0 -1
  1323. package/dist/setup-nonce-DKl4S4c6.mjs +0 -25
  1324. package/dist/setup-nonce-DKl4S4c6.mjs.map +0 -1
  1325. package/dist/site-domain-CbI51Pc2.mjs +0 -113
  1326. package/dist/site-domain-CbI51Pc2.mjs.map +0 -1
  1327. package/dist/site-settings-CDdT4mVm.mjs +0 -50
  1328. package/dist/site-settings-CDdT4mVm.mjs.map +0 -1
  1329. package/dist/site-url-CrDZaAvo.mjs +0 -45
  1330. package/dist/site-url-CrDZaAvo.mjs.map +0 -1
  1331. package/dist/sitemap-name-W3BTor6X.mjs +0 -26
  1332. package/dist/sitemap-name-W3BTor6X.mjs.map +0 -1
  1333. package/dist/slug-BJhHKoOH.mjs +0 -16
  1334. package/dist/slug-BJhHKoOH.mjs.map +0 -1
  1335. package/dist/snapshot-BuI_2uDe.mjs +0 -414
  1336. package/dist/snapshot-BuI_2uDe.mjs.map +0 -1
  1337. package/dist/ssrf-LM_0wpGA.mjs +0 -406
  1338. package/dist/ssrf-LM_0wpGA.mjs.map +0 -1
  1339. package/dist/stage-DhzZuYaT.mjs +0 -662
  1340. package/dist/stage-DhzZuYaT.mjs.map +0 -1
  1341. package/dist/staged-DboEaWsV.mjs +0 -686
  1342. package/dist/staged-DboEaWsV.mjs.map +0 -1
  1343. package/dist/state-DCXDzjHq.mjs +0 -178
  1344. package/dist/state-DCXDzjHq.mjs.map +0 -1
  1345. package/dist/status-Dl85BK39.mjs +0 -30
  1346. package/dist/status-Dl85BK39.mjs.map +0 -1
  1347. package/dist/storage-query-BOBmeDMD.d.mts +0 -1615
  1348. package/dist/storage-query-BOBmeDMD.d.mts.map +0 -1
  1349. package/dist/tar-K40edFMt.mjs +0 -449
  1350. package/dist/tar-K40edFMt.mjs.map +0 -1
  1351. package/dist/target-BOighEY1.mjs +0 -27
  1352. package/dist/target-BOighEY1.mjs.map +0 -1
  1353. package/dist/taxonomies-DQSywBvX.mjs +0 -697
  1354. package/dist/taxonomies-DQSywBvX.mjs.map +0 -1
  1355. package/dist/taxonomies-Dj5eaobC.mjs +0 -939
  1356. package/dist/taxonomies-Dj5eaobC.mjs.map +0 -1
  1357. package/dist/taxonomy-QrNmTfIZ.mjs +0 -550
  1358. package/dist/taxonomy-QrNmTfIZ.mjs.map +0 -1
  1359. package/dist/tokens-j5L0as2H.mjs +0 -171
  1360. package/dist/tokens-j5L0as2H.mjs.map +0 -1
  1361. package/dist/transfer-CYEw8Tu4.mjs +0 -8873
  1362. package/dist/transfer-CYEw8Tu4.mjs.map +0 -1
  1363. package/dist/transfer-DDX10hkD.mjs +0 -166
  1364. package/dist/transfer-DDX10hkD.mjs.map +0 -1
  1365. package/dist/transfer-download-BAqq6GJv.mjs +0 -33
  1366. package/dist/transfer-download-BAqq6GJv.mjs.map +0 -1
  1367. package/dist/transformations-De44wqV_.mjs +0 -196
  1368. package/dist/transformations-De44wqV_.mjs.map +0 -1
  1369. package/dist/transport-1QjUhCRO.d.mts +0 -42
  1370. package/dist/transport-1QjUhCRO.d.mts.map +0 -1
  1371. package/dist/transport-Ds5pVX7p.mjs +0 -136
  1372. package/dist/transport-Ds5pVX7p.mjs.map +0 -1
  1373. package/dist/trusted-proxy-d4Tk6biT.mjs +0 -51
  1374. package/dist/trusted-proxy-d4Tk6biT.mjs.map +0 -1
  1375. package/dist/turnstile-DaFLtyrs.mjs +0 -58
  1376. package/dist/turnstile-DaFLtyrs.mjs.map +0 -1
  1377. package/dist/types-B4-1P2DK.d.mts +0 -227
  1378. package/dist/types-B4-1P2DK.d.mts.map +0 -1
  1379. package/dist/types-BKXA0f-c.mjs +0 -16
  1380. package/dist/types-BKXA0f-c.mjs.map +0 -1
  1381. package/dist/types-BiHcpUoO.d.mts +0 -374
  1382. package/dist/types-BiHcpUoO.d.mts.map +0 -1
  1383. package/dist/types-BihhvkyN.d.mts +0 -85
  1384. package/dist/types-BihhvkyN.d.mts.map +0 -1
  1385. package/dist/types-Bq9Wohd7.d.mts +0 -363
  1386. package/dist/types-Bq9Wohd7.d.mts.map +0 -1
  1387. package/dist/types-C-Xp0CcN.mjs +0 -103
  1388. package/dist/types-C-Xp0CcN.mjs.map +0 -1
  1389. package/dist/types-C4P7F1Vq.d.mts +0 -1741
  1390. package/dist/types-C4P7F1Vq.d.mts.map +0 -1
  1391. package/dist/types-CGaqwHw4.mjs +0 -37
  1392. package/dist/types-CGaqwHw4.mjs.map +0 -1
  1393. package/dist/types-D4ECCE4X.mjs +0 -77
  1394. package/dist/types-D4ECCE4X.mjs.map +0 -1
  1395. package/dist/types-DcRJp0vS.d.mts +0 -125
  1396. package/dist/types-DcRJp0vS.d.mts.map +0 -1
  1397. package/dist/types-Ff85fTzU.d.mts +0 -289
  1398. package/dist/types-Ff85fTzU.d.mts.map +0 -1
  1399. package/dist/types-UKr5Sf4y.d.mts +0 -916
  1400. package/dist/types-UKr5Sf4y.d.mts.map +0 -1
  1401. package/dist/types-YpN8hZW7.d.mts +0 -204
  1402. package/dist/types-YpN8hZW7.d.mts.map +0 -1
  1403. package/dist/update-check-DrlsK-tt.mjs +0 -161
  1404. package/dist/update-check-DrlsK-tt.mjs.map +0 -1
  1405. package/dist/upload-attempts-D8CPPvRU.mjs +0 -32
  1406. package/dist/upload-attempts-D8CPPvRU.mjs.map +0 -1
  1407. package/dist/url-pattern-Di4Nn3vP.mjs +0 -41
  1408. package/dist/url-pattern-Di4Nn3vP.mjs.map +0 -1
  1409. package/dist/user-B-ZdGjhI.mjs +0 -171
  1410. package/dist/user-B-ZdGjhI.mjs.map +0 -1
  1411. package/dist/utils-D7wL3r6-.mjs +0 -437
  1412. package/dist/utils-D7wL3r6-.mjs.map +0 -1
  1413. package/dist/validate-BSZbSUDk.mjs +0 -524
  1414. package/dist/validate-BSZbSUDk.mjs.map +0 -1
  1415. package/dist/validate-Dfv0DpZi.d.mts +0 -468
  1416. package/dist/validate-Dfv0DpZi.d.mts.map +0 -1
  1417. package/dist/validation-DRyC_Vm5.mjs +0 -219
  1418. package/dist/validation-DRyC_Vm5.mjs.map +0 -1
  1419. package/dist/version-C4kz0PcO.mjs +0 -7
  1420. package/dist/version-C4kz0PcO.mjs.map +0 -1
  1421. package/dist/version-jhs2BRtl.mjs +0 -9
  1422. package/dist/version-jhs2BRtl.mjs.map +0 -1
  1423. package/dist/video-DReZ48Un.mjs +0 -54
  1424. package/dist/video-DReZ48Un.mjs.map +0 -1
  1425. package/dist/virtual-modules-D0e6VbEv.mjs +0 -516
  1426. package/dist/virtual-modules-D0e6VbEv.mjs.map +0 -1
  1427. package/dist/widgets-BkcMzKct.mjs +0 -121
  1428. package/dist/widgets-BkcMzKct.mjs.map +0 -1
  1429. package/dist/wxr-taxonomies-BxI0CbTg.mjs +0 -453
  1430. package/dist/wxr-taxonomies-BxI0CbTg.mjs.map +0 -1
  1431. package/dist/wxr-taxonomies-Dad33GJi.d.mts +0 -34
  1432. package/dist/wxr-taxonomies-Dad33GJi.d.mts.map +0 -1
  1433. package/dist/zod-generator-BQilAboC.mjs +0 -424
  1434. package/dist/zod-generator-BQilAboC.mjs.map +0 -1
  1435. /package/dist/{api-tokens-D2zgAIEt.mjs → api-tokens-CdP49zVF.mjs} +0 -0
  1436. /package/dist/{ssrf-BvNItdxk.mjs → ssrf-DM0E-D_8.mjs} +0 -0
@@ -1,15 +1,15 @@
1
- import "../../parse-BOGhrwSq.mjs";
2
- import "../../types-UKr5Sf4y.mjs";
3
- import "../../types-C4P7F1Vq.mjs";
4
- import "../../options-BR9XZl7h.mjs";
5
- import "../../entry-lock-BAAlKYrz.mjs";
6
- import "../../config-C4-UxIk7.mjs";
7
- import "../../runner-DkeafPBA.mjs";
8
- import "../../storage-query-BOBmeDMD.mjs";
9
- import "../../index-DYsn97dY.mjs";
10
- import "../../types-Bq9Wohd7.mjs";
11
- import "../../hreflang-BsYo4x_M.mjs";
12
- import "../../validate-Dfv0DpZi.mjs";
1
+ import "../../parse-CWHOFc6z.mjs";
2
+ import "../../types-DCFavOii.mjs";
3
+ import "../../types-QoPHm-2w.mjs";
4
+ import "../../options-DJWaq3Ie.mjs";
5
+ import "../../entry-lock-C7VX0NGK.mjs";
6
+ import "../../config-Bsm_u_oE.mjs";
7
+ import "../../runner-BObHz5FC.mjs";
8
+ import "../../storage-query-DRyu3bSU.mjs";
9
+ import "../../index-BB9sVisO.mjs";
10
+ import "../../types-DHO7Pd25.mjs";
11
+ import "../../hreflang-CY_F5OjF.mjs";
12
+ import "../../validate-emKxGC5F.mjs";
13
13
  import { EmDashHandlers } from "../types.mjs";
14
14
  import { User } from "@emdash-cms/auth";
15
15
  import * as astro from "astro";
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.mts","names":[],"sources":["../../../src/astro/middleware/auth.ts"],"mappings":";;;;;;;;;;;;;;;;;QA2CQ,MAAA;EAAA,UACG,GAAA;IAAA,UACC,MAAA;MACT,IAAA,GAAO,IAAA;MANwC;MAQ/C,WAAA;MAFO;MAIP,OAAA;MACA,MAAA,GAAS,cAAA;IAAA;IAAA,UAEA,WAAA;MACT,IAAA;QAAQ,EAAA;MAAA;MACR,cAAA;IAAA;EAAA;AAAA;AAAA,cA8HU,SAAA,EA0KX,KAAA,CA1KoB,iBAAA"}
1
+ {"version":3,"file":"auth.d.mts","names":[],"sources":["../../../src/astro/middleware/auth.ts"],"mappings":";;;;;;;;;;;;;;;;;QA2CQ,MAAA;EAAA,UACG,GAAA;IAAA,UACC,MAAA;MACT,IAAA,GAAO,IAAA;MANwC;MAQ/C,WAAA;MAFO;MAIP,OAAA;MACA,MAAA,GAAS,cAAA;IAAA;IAAA,UAEA,WAAA;MACT,IAAA;QAAQ,EAAA;MAAA;MACR,cAAA;IAAA;EAAA;AAAA;AAAA,cAgIU,SAAA,EA0KX,KAAA,CA1KoB,iBAAA"}
@@ -1,15 +1,15 @@
1
1
  import "../../after-PcEvMY_6.mjs";
2
2
  import "../../base64-BQBZwXCx.mjs";
3
- import "../../types-C-Xp0CcN.mjs";
4
- import "../../errors-CjtE5aWF.mjs";
5
- import { r as getRegistryConfigInput } from "../../config-Bo4eOOdV.mjs";
6
- import "../../errors-hskQ0C8G.mjs";
7
- import { t as apiError } from "../../error-DxgQdaZ_.mjs";
8
- import { i as getPublicOrigin } from "../../public-url-uT1Ok2Tu.mjs";
9
- import { t as getAuthMode } from "../../mode-eieqAWLe.mjs";
10
- import { n as resolveSessionUser } from "../../session-user-1dtJc2zv.mjs";
11
- import { a as hasScope, n as TRANSFER_SCOPES } from "../../api-tokens-D2zgAIEt.mjs";
12
- import { a as resolveApiToken, o as resolveOAuthToken } from "../../api-tokens-B0ZipcZ-.mjs";
3
+ import "../../types-D2NEXtgB.mjs";
4
+ import "../../errors-B4f4It-2.mjs";
5
+ import { r as getRegistryConfigInput } from "../../config-DBU6iUQB.mjs";
6
+ import "../../errors-BOYNdIo3.mjs";
7
+ import { t as apiError } from "../../error-CVWeIOku.mjs";
8
+ import { i as getPublicOrigin } from "../../public-url-Bt98vysr.mjs";
9
+ import { t as getAuthMode } from "../../mode-C-D3qICy.mjs";
10
+ import { n as resolveSessionUser } from "../../session-user-DlpPdf8L.mjs";
11
+ import { a as hasScope, n as TRANSFER_SCOPES } from "../../api-tokens-CdP49zVF.mjs";
12
+ import { a as resolveApiToken, o as resolveOAuthToken } from "../../api-tokens-Bx38ZCQp.mjs";
13
13
  import { ulid } from "ulidx";
14
14
  import { defineMiddleware } from "astro:middleware";
15
15
  import virtualConfig from "virtual:emdash/config";
@@ -185,6 +185,7 @@ const PUBLIC_API_EXACT = new Set([
185
185
  "/_emdash/api/search",
186
186
  "/_emdash/api/search/suggest"
187
187
  ]);
188
+ const DEV_PUBLIC_API_EXACT = new Set(["/_emdash/api/typegen", "/_emdash/api/dev/scheduled-tasks"]);
188
189
  const { exact: _providerExactRoutes, prefixes: _providerPrefixRoutes } = (() => {
189
190
  const exact = /* @__PURE__ */ new Set();
190
191
  const prefixes = [];
@@ -227,7 +228,7 @@ function isPublicEmDashRoute(pathname) {
227
228
  if (PUBLIC_API_PREFIXES.some((p) => pathname.startsWith(p))) return true;
228
229
  if (_providerExactRoutes.has(pathname)) return true;
229
230
  if (_providerPrefixRoutes.some((p) => pathname.startsWith(p))) return true;
230
- if (import.meta.env.DEV && pathname === "/_emdash/api/typegen") return true;
231
+ if (import.meta.env.DEV && DEV_PUBLIC_API_EXACT.has(pathname)) return true;
231
232
  return false;
232
233
  }
233
234
  function isCsrfExemptPublicRoute(pathname) {
@@ -1 +1 @@
1
- {"version":3,"file":"auth.mjs","names":["virtualAuthenticate"],"sources":["../../../src/api/csrf.ts","../../../src/astro/middleware/csp.ts","../../../src/astro/middleware/auth.ts"],"sourcesContent":["/**\n * CSRF protection utilities.\n *\n * Two mechanisms:\n * 1. Custom header check (X-EmDash-Request: 1) — used for authenticated API routes.\n * Browsers block cross-origin custom headers, so presence proves same-origin.\n * 2. Origin check — used for public API routes that skip auth. Compares the Origin\n * header against the request origin. Same approach as Astro's `checkOrigin`.\n */\n\nimport { apiError } from \"./error.js\";\n\n/**\n * Origin-based CSRF check for public API routes that skip auth.\n *\n * State-changing requests (POST/PUT/DELETE) to public endpoints must either:\n * 1. Include the X-EmDash-Request: 1 header (custom header blocked cross-origin), OR\n * 2. Have an Origin header matching the request origin (or the configured public origin)\n *\n * This prevents cross-origin form submissions (which can't set custom headers)\n * and cross-origin fetch (blocked by CORS unless allowed). Same-origin requests\n * always include a matching Origin header.\n *\n * Returns a 403 Response if the check fails, or null if allowed.\n *\n * @param request The incoming request\n * @param url The request URL (internal origin)\n * @param publicOrigin The public-facing origin from config.siteUrl. Must be\n * `undefined` when absent — never `null` or `\"\"` (security invariant H-1a).\n */\nexport function checkPublicCsrf(\n\trequest: Request,\n\turl: URL,\n\tpublicOrigin?: string,\n): Response | null {\n\t// Custom header present — browser blocks cross-origin custom headers\n\tconst csrfHeader = request.headers.get(\"X-EmDash-Request\");\n\tif (csrfHeader === \"1\") return null;\n\n\t// Check Origin header — present on all POST/PUT/DELETE from browsers\n\tconst origin = request.headers.get(\"Origin\");\n\tif (origin) {\n\t\ttry {\n\t\t\tconst originUrl = new URL(origin);\n\t\t\t// Accept if Origin matches either the internal or public origin\n\t\t\tif (originUrl.origin === url.origin) return null;\n\t\t\tif (publicOrigin && originUrl.origin === publicOrigin) return null;\n\t\t} catch {\n\t\t\t// Malformed Origin — fall through to reject\n\t\t}\n\n\t\treturn apiError(\"CSRF_REJECTED\", \"Cross-origin request blocked\", 403);\n\t}\n\n\t// No Origin header — non-browser client (curl, server-to-server).\n\t// Allow these through since CSRF is a browser-specific attack vector.\n\t// Server-to-server requests don't carry ambient credentials (cookies).\n\treturn null;\n}\n","/**\n * Strict Content-Security-Policy for /_emdash routes (admin + API).\n *\n * Applied via middleware header rather than Astro's built-in CSP because\n * Astro's auto-hashing defeats 'unsafe-inline' (CSP3 ignores 'unsafe-inline'\n * when hashes are present), which would break user-facing pages.\n *\n * img-src allows any HTTPS origin because the admin renders user content that\n * may reference external images (migrations, external hosting, embeds).\n * Plugin security does not rely on img-src -- plugins run in V8 isolates with\n * no DOM access. connect-src stays at 'self' unless the experimental registry\n * and/or the configured storage endpoint (for direct-to-S3 signed uploads)\n * are configured, in which case those origins are allowed too.\n */\nimport type { RegistryConfigInput } from \"../../registry/types.js\";\nimport type { Storage } from \"../../storage/types.js\";\nimport type { StorageDescriptor } from \"../storage/types.js\";\n\n/** Entrypoint constant used by the `s3()` adapter (see `astro/storage/adapters.ts`). */\nconst S3_ADAPTER_ENTRYPOINT = \"emdash/storage/s3\";\n\n/**\n * Storage entrypoints are free to shape their config however they like, so\n * `endpoint` isn't a known field on `StorageDescriptor[\"config\"]` -- only\n * S3-compatible adapters (R2, S3, Minio, ...) set it. Anything else (e.g.\n * local filesystem storage) simply has no `endpoint` to allow.\n *\n * The `s3()` adapter resolves any field omitted from its config -- including\n * `endpoint` -- from the matching `S3_*` env var at runtime (see\n * `storage/s3.ts`'s `resolveS3Config`). A site configured as `s3({ ... })`\n * with only `S3_ENDPOINT` set has no `endpoint` in the descriptor's config,\n * so fall back to that env var for S3-adapter storage. Custom adapters can\n * expose their runtime upload origin through `getClientUploadOrigin()`.\n */\nexport function getConfiguredStorageEndpoint(\n\tstorage: StorageDescriptor | undefined,\n\truntimeStorage?: Pick<Storage, \"getClientUploadOrigin\"> | null,\n): string | undefined {\n\tconst config = storage?.config;\n\tif (typeof config === \"object\" && config !== null && \"endpoint\" in config) {\n\t\tconst endpoint = config.endpoint;\n\t\tif (typeof endpoint === \"string\") return endpoint;\n\t}\n\n\tif (storage?.entrypoint === S3_ADAPTER_ENTRYPOINT) {\n\t\tconst envEndpoint =\n\t\t\ttypeof process !== \"undefined\" && process.env ? process.env.S3_ENDPOINT : undefined;\n\t\tif (envEndpoint) return envEndpoint;\n\t}\n\n\treturn runtimeStorage?.getClientUploadOrigin?.();\n}\n\nfunction getRegistryAggregatorOrigin(\n\tregistry: RegistryConfigInput | undefined,\n): string | undefined {\n\tconst aggregatorUrl = typeof registry === \"string\" ? registry : registry?.aggregatorUrl;\n\tif (!aggregatorUrl) return undefined;\n\n\ttry {\n\t\tconst url = new URL(aggregatorUrl);\n\t\tif (url.protocol !== \"http:\" && url.protocol !== \"https:\") return undefined;\n\t\treturn url.origin;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction getHttpOrigin(rawUrl: string | undefined): string | undefined {\n\tif (!rawUrl) return undefined;\n\n\ttry {\n\t\tconst url = new URL(rawUrl);\n\t\tif (url.protocol !== \"http:\" && url.protocol !== \"https:\") return undefined;\n\t\treturn url.origin;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function buildEmDashCsp(registry?: RegistryConfigInput, storageEndpoint?: string): string {\n\tconst connectSrc = [\"connect-src 'self'\"];\n\tconst origins = new Set<string>();\n\tconst registryAggregatorOrigin = getRegistryAggregatorOrigin(registry);\n\tif (registryAggregatorOrigin) origins.add(registryAggregatorOrigin);\n\tconst storageOrigin = getHttpOrigin(storageEndpoint);\n\tif (storageOrigin) origins.add(storageOrigin);\n\tconnectSrc.push(...origins);\n\n\treturn [\n\t\t\"default-src 'self'\",\n\t\t\"script-src 'self' 'unsafe-inline'\",\n\t\t\"style-src 'self' 'unsafe-inline'\",\n\t\tconnectSrc.join(\" \"),\n\t\t\"form-action 'self'\",\n\t\t\"frame-src 'self' https:\",\n\t\t\"frame-ancestors 'none'\",\n\t\t\"img-src 'self' https: data: blob:\",\n\t\t\"media-src 'self' blob: https:\",\n\t\t\"object-src 'none'\",\n\t\t\"base-uri 'self'\",\n\t].join(\"; \");\n}\n","/**\n * Auth middleware for admin routes\n *\n * Checks if the user is authenticated and has appropriate permissions.\n * Supports two auth modes:\n * - Passkey (default): Session-based auth with passkey login\n * - External providers: JWT-based auth (Cloudflare Access, etc.)\n *\n * This middleware runs AFTER the setup middleware - so if we get here,\n * we know setup is complete and users exist.\n */\n\nimport type { User, RoleLevel } from \"@emdash-cms/auth\";\nimport { createKyselyAdapter } from \"@emdash-cms/auth/adapters/kysely\";\nimport { defineMiddleware } from \"astro:middleware\";\nimport { ulid } from \"ulidx\";\n// Import auth provider via virtual module (statically bundled)\n// This avoids dynamic import issues in Cloudflare Workers\nimport { authenticate as virtualAuthenticate } from \"virtual:emdash/auth\";\n// @ts-ignore - virtual module\nimport virtualConfig from \"virtual:emdash/config\";\n\nimport { checkPublicCsrf } from \"../../api/csrf.js\";\nimport { apiError } from \"../../api/error.js\";\nimport { getPublicOrigin } from \"../../api/public-url.js\";\n\n/** Cache headers for middleware error responses (matches API_CACHE_HEADERS in api/error.ts) */\nconst MW_CACHE_HEADERS = {\n\t\"Cache-Control\": \"private, no-store\",\n} as const;\nimport {\n\tresolveApiToken,\n\tresolveOAuthToken,\n\ttype ResolvedBearerToken,\n} from \"../../api/handlers/api-tokens.js\";\nimport { hasScope, TRANSFER_SCOPES } from \"../../auth/api-tokens.js\";\nimport { getAuthMode, type ExternalAuthMode } from \"../../auth/mode.js\";\nimport type { ExternalAuthConfig } from \"../../auth/types.js\";\nimport { getRegistryConfigInput } from \"../../registry/config.js\";\nimport { resolveSessionUser } from \"../session-user.js\";\nimport type { EmDashHandlers } from \"../types.js\";\nimport { buildEmDashCsp, getConfiguredStorageEndpoint } from \"./csp.js\";\n\ndeclare global {\n\tnamespace App {\n\t\tinterface Locals {\n\t\t\tuser?: User;\n\t\t\t/** Token scopes when authenticated via API token or OAuth token. Undefined for session auth. */\n\t\t\ttokenScopes?: string[];\n\t\t\t/** Id of the API or OAuth token the request authenticated with. Undefined for session auth. */\n\t\t\ttokenId?: string;\n\t\t\temdash?: EmDashHandlers;\n\t\t}\n\t\tinterface SessionData {\n\t\t\tuser: { id: string };\n\t\t\thasSeenWelcome: boolean;\n\t\t}\n\t}\n}\n\n// Role level constants (matching @emdash-cms/auth)\nconst ROLE_ADMIN = 50;\nconst MCP_ENDPOINT_PATH = \"/_emdash/api/mcp\";\nconst COMMENT_SUBMISSION_PATH = /^\\/_emdash\\/api\\/comments\\/[^/]+\\/[^/]+\\/?$/;\n\nfunction isUnsafeMethod(method: string): boolean {\n\treturn method !== \"GET\" && method !== \"HEAD\" && method !== \"OPTIONS\";\n}\n\nfunction csrfRejectedResponse(): Response {\n\treturn apiError(\"CSRF_REJECTED\", \"Missing required header\", 403);\n}\n\nfunction mcpUnauthorizedResponse(\n\turl: URL,\n\tconfig?: Parameters<typeof getPublicOrigin>[1],\n): Response {\n\tconst origin = getPublicOrigin(url, config);\n\tconst response = apiError(\"NOT_AUTHENTICATED\", \"Not authenticated\", 401);\n\t// Preserve the OAuth discovery header so MCP clients can find the auth server.\n\tresponse.headers.set(\n\t\t\"WWW-Authenticate\",\n\t\t`Bearer resource_metadata=\"${origin}/.well-known/oauth-protected-resource\"`,\n\t);\n\treturn response;\n}\n\n/**\n * API routes that skip auth — each handles its own access control.\n *\n * Prefix entries match any path starting with that prefix.\n * Exact entries (no trailing slash or wildcard) match that path only.\n */\nconst PUBLIC_API_PREFIXES = [\n\t\"/_emdash/api/setup\",\n\t\"/_emdash/api/auth/login\",\n\t\"/_emdash/api/auth/register\",\n\t\"/_emdash/api/auth/dev-bypass\",\n\t\"/_emdash/api/auth/signup/\",\n\t\"/_emdash/api/auth/magic-link/\",\n\t\"/_emdash/api/auth/invite/\",\n\t\"/_emdash/api/auth/oauth/\",\n\t\"/_emdash/api/oauth/device/token\",\n\t\"/_emdash/api/oauth/device/code\",\n\t\"/_emdash/api/oauth/token\",\n\t\"/_emdash/api/oauth/register\",\n\t\"/_emdash/api/comments/\",\n\t\"/_emdash/api/media/file/\",\n\t\"/_emdash/.well-known/\",\n];\n\nconst PUBLIC_API_EXACT = new Set([\n\t\"/_emdash/api/auth/passkey/options\",\n\t\"/_emdash/api/auth/passkey/verify\",\n\t\"/_emdash/api/auth/mode\",\n\t\"/_emdash/api/health\",\n\t\"/_emdash/api/site/domain-proof\",\n\t\"/_emdash/api/oauth/token\",\n\t\"/_emdash/api/snapshot\",\n\t\"/_emdash/api/visual-editing/toolbar-labels\",\n\t// Public site search — read-only. Unauthenticated callers only see\n\t// published content: /search forces status='published' without the\n\t// content:read_drafts permission and /suggest hardcodes it. Admin endpoints\n\t// (/enable, /rebuild, /stats) remain private because they're not in this set.\n\t\"/_emdash/api/search\",\n\t\"/_emdash/api/search/suggest\",\n]);\n\n// Build merged public routes at module load from auth provider descriptors.\n// Routes ending with \"/\" are treated as prefixes; all others are exact matches.\nconst { exact: _providerExactRoutes, prefixes: _providerPrefixRoutes } = (() => {\n\tconst exact = new Set<string>();\n\tconst prefixes: string[] = [];\n\tif (!virtualConfig?.authProviders) return { exact, prefixes };\n\tfor (const route of virtualConfig.authProviders.flatMap((p) => p.publicRoutes ?? [])) {\n\t\tif (route.endsWith(\"/\")) {\n\t\t\tprefixes.push(route);\n\t\t} else {\n\t\t\texact.add(route);\n\t\t}\n\t}\n\treturn { exact, prefixes };\n})();\n\n/**\n * OAuth protocol endpoints that are CSRF-exempt by design.\n *\n * These are RFC-defined endpoints (RFC 6749 §3.2, RFC 7591 §3, RFC 8628 §3.1/§3.4)\n * specified to be called cross-origin by external clients (MCP clients, CLIs,\n * native apps). They authenticate each request on its own merits:\n *\n * - /oauth/token: requires PKCE code_verifier, device_code, or refresh_token\n * - /oauth/register: RFC 7591 dynamic client registration — anonymous by design\n * - /oauth/device/code: RFC 8628 device flow initiation — anonymous by design\n * - /oauth/device/token: requires device_code the client already holds\n *\n * None of these rely on ambient cookie credentials, so browser-based CSRF\n * attacks have nothing to exploit. The endpoints themselves advertise\n * `Access-Control-Allow-Origin: *`. Note: /oauth/device/authorize (the user\n * consent step) is NOT in this list — it is session-authenticated.\n */\nconst CSRF_EXEMPT_PUBLIC_ROUTES = new Set([\n\t\"/_emdash/api/oauth/token\",\n\t\"/_emdash/api/oauth/register\",\n\t\"/_emdash/api/oauth/device/code\",\n\t\"/_emdash/api/oauth/device/token\",\n]);\n\nfunction isPublicEmDashRoute(pathname: string): boolean {\n\tif (PUBLIC_API_EXACT.has(pathname)) return true;\n\tif (PUBLIC_API_PREFIXES.some((p) => pathname.startsWith(p))) return true;\n\tif (_providerExactRoutes.has(pathname)) return true;\n\tif (_providerPrefixRoutes.some((p) => pathname.startsWith(p))) return true;\n\tif (import.meta.env.DEV && pathname === \"/_emdash/api/typegen\") return true;\n\treturn false;\n}\n\nfunction isCsrfExemptPublicRoute(pathname: string): boolean {\n\treturn CSRF_EXEMPT_PUBLIC_ROUTES.has(pathname);\n}\n\nexport const onRequest = defineMiddleware(async (context, next) => {\n\tconst { url } = context;\n\n\t// Only check auth on admin routes and API routes\n\tconst isAdminRoute = url.pathname.startsWith(\"/_emdash/admin\");\n\tconst isSetupRoute = url.pathname.startsWith(\"/_emdash/admin/setup\");\n\tconst isApiRoute = url.pathname.startsWith(\"/_emdash/api\");\n\tconst isPublicApiRoute = isPublicEmDashRoute(url.pathname);\n\n\tconst isPublicRoute = !isAdminRoute && !isApiRoute;\n\n\t// Public API routes skip auth but still need CSRF protection on state-changing methods.\n\t// We check Origin header against the request host (same approach as Astro's checkOrigin).\n\t// This prevents cross-origin form submissions and fetch requests from malicious sites.\n\tif (isPublicApiRoute) {\n\t\tconst method = context.request.method.toUpperCase();\n\t\tif (\n\t\t\tisUnsafeMethod(method) &&\n\t\t\t!isCsrfExemptPublicRoute(url.pathname) // OAuth protocol endpoints — cross-origin by design\n\t\t) {\n\t\t\tconst publicOrigin = getPublicOrigin(url, context.locals.emdash?.config);\n\t\t\tconst csrfError = checkPublicCsrf(context.request, url, publicOrigin);\n\t\t\tif (csrfError) return csrfError;\n\t\t}\n\t\tif (method === \"POST\" && COMMENT_SUBMISSION_PATH.test(url.pathname)) {\n\t\t\treturn handlePublicRouteAuth(context, next);\n\t\t}\n\t\t// Search filters drafts by permission, so resolve the session user when\n\t\t// one exists; anonymous callers skip the user DB lookup. Bearer tokens\n\t\t// are not resolved on public routes; token callers continue to receive\n\t\t// published results only.\n\t\tif (url.pathname === \"/_emdash/api/search\") {\n\t\t\treturn handlePublicRouteAuth(context, next);\n\t\t}\n\t\treturn next();\n\t}\n\n\t// Plugin routes: soft auth (resolve user if credentials present, but never block).\n\t// The catch-all handler decides per-route whether auth is required (public vs private).\n\t// Public plugin routes that accept POST are vulnerable to cross-origin form submissions,\n\t// so we apply the same Origin-based CSRF check as other public routes.\n\tconst isPluginRoute = url.pathname.startsWith(\"/_emdash/api/plugins/\");\n\tif (isPluginRoute) {\n\t\tconst method = context.request.method.toUpperCase();\n\t\tif (method !== \"GET\" && method !== \"HEAD\" && method !== \"OPTIONS\") {\n\t\t\tconst publicOrigin = getPublicOrigin(url, context.locals.emdash?.config);\n\t\t\tconst csrfError = checkPublicCsrf(context.request, url, publicOrigin);\n\t\t\tif (csrfError) return csrfError;\n\t\t}\n\t\treturn handlePluginRouteAuth(context, next);\n\t}\n\n\t// Setup routes: skip auth but still enforce CSRF on state-changing methods\n\tif (isSetupRoute) {\n\t\tconst method = context.request.method.toUpperCase();\n\t\tif (method !== \"GET\" && method !== \"HEAD\" && method !== \"OPTIONS\") {\n\t\t\tconst csrfHeader = context.request.headers.get(\"X-EmDash-Request\");\n\t\t\tif (csrfHeader !== \"1\") {\n\t\t\t\treturn apiError(\"CSRF_REJECTED\", \"Missing required header\", 403);\n\t\t\t}\n\t\t}\n\t\tconst response = await next();\n\t\tif (!import.meta.env.DEV) {\n\t\t\tresponse.headers.set(\n\t\t\t\t\"Content-Security-Policy\",\n\t\t\t\tbuildEmDashCsp(\n\t\t\t\t\tgetRegistryConfigInput(context.locals.emdash?.config.registry),\n\t\t\t\t\tgetConfiguredStorageEndpoint(\n\t\t\t\t\t\tcontext.locals.emdash?.config.storage,\n\t\t\t\t\t\tcontext.locals.emdash?.storage,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\treturn response;\n\t}\n\n\t// For public routes: soft auth check (set locals.user if session exists, but never block)\n\tif (isPublicRoute) {\n\t\treturn handlePublicRouteAuth(context, next);\n\t}\n\n\t// --- Everything below is /_emdash (admin + API) ---\n\n\t// Try Bearer token auth first (API tokens and OAuth tokens).\n\t// If successful, skip CSRF (tokens aren't ambient credentials like cookies).\n\tconst bearerResult = await handleBearerAuth(context);\n\n\tif (bearerResult === \"invalid\") {\n\t\tconst response = apiError(\"INVALID_TOKEN\", \"Invalid or expired token\", 401);\n\t\t// Add WWW-Authenticate header on MCP endpoint 401s to trigger OAuth discovery\n\t\tif (url.pathname === \"/_emdash/api/mcp\") {\n\t\t\tconst origin = getPublicOrigin(url, context.locals.emdash?.config);\n\t\t\tresponse.headers.set(\n\t\t\t\t\"WWW-Authenticate\",\n\t\t\t\t`Bearer resource_metadata=\"${origin}/.well-known/oauth-protected-resource\"`,\n\t\t\t);\n\t\t}\n\t\treturn response;\n\t}\n\n\tconst isTokenAuth = bearerResult === \"authenticated\";\n\n\t// MCP discovery/tooling is bearer-only. Session/external auth should never\n\t// be consulted for this endpoint, and unauthenticated requests must return\n\t// the OAuth discovery-style 401 response.\n\tconst method = context.request.method.toUpperCase();\n\tconst isMcpEndpoint = url.pathname === MCP_ENDPOINT_PATH;\n\tif (isMcpEndpoint && !isTokenAuth) {\n\t\treturn mcpUnauthorizedResponse(url, context.locals.emdash?.config);\n\t}\n\n\t// CSRF protection: require X-EmDash-Request header on state-changing requests.\n\t// Skip for token-authenticated requests (tokens aren't ambient credentials).\n\t// Browsers block cross-origin custom headers, so this prevents CSRF without tokens.\n\t// OAuth authorize consent is exempt: it's a standard HTML form POST that can't\n\t// include custom headers. The consent flow is protected by session + single-use codes.\n\tconst isOAuthConsent = url.pathname.startsWith(\"/_emdash/oauth/authorize\");\n\tif (\n\t\tisApiRoute &&\n\t\t!isTokenAuth &&\n\t\t!isOAuthConsent &&\n\t\tisUnsafeMethod(method) &&\n\t\t!isPublicApiRoute\n\t) {\n\t\tconst csrfHeader = context.request.headers.get(\"X-EmDash-Request\");\n\t\tif (csrfHeader !== \"1\") {\n\t\t\treturn csrfRejectedResponse();\n\t\t}\n\t}\n\n\t// If already authenticated via Bearer token, enforce scope then skip session/external auth\n\tif (isTokenAuth) {\n\t\t// Enforce API token scopes based on URL pattern + HTTP method\n\t\tconst scopeError = enforceTokenScope(url.pathname, method, context.locals.tokenScopes);\n\t\tif (scopeError) return scopeError;\n\n\t\tconst response = await next();\n\t\tif (!import.meta.env.DEV) {\n\t\t\tresponse.headers.set(\n\t\t\t\t\"Content-Security-Policy\",\n\t\t\t\tbuildEmDashCsp(\n\t\t\t\t\tgetRegistryConfigInput(context.locals.emdash?.config.registry),\n\t\t\t\t\tgetConfiguredStorageEndpoint(\n\t\t\t\t\t\tcontext.locals.emdash?.config.storage,\n\t\t\t\t\t\tcontext.locals.emdash?.storage,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\treturn response;\n\t}\n\n\tconst response = await handleEmDashAuth(context, next);\n\n\t// Set strict CSP on all /_emdash responses (prod only)\n\tif (!import.meta.env.DEV) {\n\t\tresponse.headers.set(\n\t\t\t\"Content-Security-Policy\",\n\t\t\tbuildEmDashCsp(\n\t\t\t\tgetRegistryConfigInput(context.locals.emdash?.config.registry),\n\t\t\t\tgetConfiguredStorageEndpoint(\n\t\t\t\t\tcontext.locals.emdash?.config.storage,\n\t\t\t\t\tcontext.locals.emdash?.storage,\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t}\n\n\treturn response;\n});\n\n/**\n * Auth handling for /_emdash routes. Returns a Response from either\n * an auth error/redirect or the downstream route handler.\n */\nasync function handleEmDashAuth(\n\tcontext: Parameters<Parameters<typeof defineMiddleware>[0]>[0],\n\tnext: Parameters<Parameters<typeof defineMiddleware>[0]>[1],\n): Promise<Response> {\n\tconst { url, locals } = context;\n\tconst { emdash } = locals;\n\n\t// Pages an anonymous visitor must be able to reach: login itself, and the\n\t// two token-bearing pages that emails link to.\n\tconst isPublicAdminRoute =\n\t\turl.pathname.startsWith(\"/_emdash/admin/login\") ||\n\t\turl.pathname.startsWith(\"/_emdash/admin/signup\") ||\n\t\turl.pathname.startsWith(\"/_emdash/admin/invite/accept\");\n\tconst isApiRoute = url.pathname.startsWith(\"/_emdash/api\");\n\n\tif (!emdash?.db) {\n\t\t// No database - let the admin handle this error\n\t\treturn next();\n\t}\n\n\t// Determine auth mode from config\n\tconst authMode = getAuthMode(emdash.config);\n\n\tif (authMode.type === \"external\") {\n\t\t// In dev mode, fall back to passkey auth since external JWT won't be present\n\t\tif (import.meta.env.DEV) {\n\t\t\tif (isPublicAdminRoute) {\n\t\t\t\treturn next();\n\t\t\t}\n\n\t\t\treturn handlePasskeyAuth(context, next, isApiRoute);\n\t\t}\n\n\t\t// External auth provider (Cloudflare Access, etc.)\n\t\treturn handleExternalAuth(context, next, authMode, isApiRoute);\n\t}\n\n\t// Passkey authentication (default)\n\tif (isPublicAdminRoute) {\n\t\treturn next();\n\t}\n\n\treturn handlePasskeyAuth(context, next, isApiRoute);\n}\n\n/**\n * Plugin-route auth. Resolves the user in three steps, stopping at the first that\n * applies:\n *\n * 1. Bearer token (all modes). A valid token authenticates; an invalid/expired one\n * returns 401 (we never silently downgrade a bad token to anonymous).\n * 2. External provider — only for a *private* route in production external-auth\n * mode. Here `handleExternalAuth` is the sole authority: the provider (e.g.\n * Cloudflare Access) is re-verified on every request, so it hard-blocks with\n * 401 on failure. It does persist an EmDash session (so public pages can\n * identify the user), but on these routes that session is deliberately NOT\n * consulted as a fallback — the provider check is authoritative every time.\n * 3. Session — everything else (non-external mode, DEV, and all public routes).\n * This is soft: it sets `locals.user` if a session exists but never blocks.\n *\n * Public routes are always allowed through. The catch-all handler still enforces\n * the `plugins:manage` permission and CSRF for private invocations.\n */\nasync function handlePluginRouteAuth(\n\tcontext: Parameters<Parameters<typeof defineMiddleware>[0]>[0],\n\tnext: Parameters<Parameters<typeof defineMiddleware>[0]>[1],\n): Promise<Response> {\n\tconst { locals, url } = context;\n\tconst { emdash } = locals;\n\n\ttry {\n\t\t// Try Bearer token auth first (API tokens and OAuth tokens)\n\t\tconst bearerResult = await handleBearerAuth(context);\n\t\tif (bearerResult === \"authenticated\") {\n\t\t\t// User and tokenScopes are set on locals by handleBearerAuth\n\t\t\treturn next();\n\t\t}\n\t\tif (bearerResult === \"invalid\") {\n\t\t\t// A token was presented but is invalid/expired — return 401 so the\n\t\t\t// caller knows their token is bad (don't silently downgrade to no-auth).\n\t\t\treturn apiError(\"INVALID_TOKEN\", \"Invalid or expired token\", 401);\n\t\t}\n\t\t// \"none\" — no token presented, try external/session auth below.\n\t} catch (error) {\n\t\tconsole.error(\"Plugin route bearer auth error:\", error);\n\t}\n\n\tconst authMode = getAuthMode(emdash?.config);\n\tif (\n\t\tauthMode.type === \"external\" &&\n\t\t!import.meta.env.DEV &&\n\t\t!isPublicPluginApiRoute(url.pathname, emdash)\n\t) {\n\t\treturn handleExternalAuth(context, next, authMode, true);\n\t}\n\n\ttry {\n\t\t// Try session auth (sets locals.user if session exists)\n\t\tconst { session } = context;\n\t\tconst sessionUser = await resolveSessionUser(session);\n\t\tif (sessionUser?.id && emdash?.db) {\n\t\t\tconst adapter = createKyselyAdapter(emdash.db);\n\t\t\tconst user = await adapter.getUserById(sessionUser.id);\n\t\t\tif (user && !user.disabled) {\n\t\t\t\tlocals.user = user;\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\t// Log but don't block — public routes should still work without session\n\t\tconsole.error(\"Plugin route session auth error:\", error);\n\t}\n\n\treturn next();\n}\n\nfunction isPublicPluginApiRoute(pathname: string, emdash: EmDashHandlers | undefined): boolean {\n\tconst prefix = \"/_emdash/api/plugins/\";\n\tconst route = pathname.slice(prefix.length);\n\tconst slashIndex = route.indexOf(\"/\");\n\tif (slashIndex <= 0 || !emdash?.getPluginRouteMeta) return false;\n\n\treturn (\n\t\temdash.getPluginRouteMeta(route.slice(0, slashIndex), route.slice(slashIndex))?.public === true\n\t);\n}\n\n/**\n * Soft auth check for public routes with edit mode cookie.\n * Checks the session and sets locals.user if valid, but never blocks the request.\n */\nasync function handlePublicRouteAuth(\n\tcontext: Parameters<Parameters<typeof defineMiddleware>[0]>[0],\n\tnext: Parameters<Parameters<typeof defineMiddleware>[0]>[1],\n): Promise<Response> {\n\tconst { locals, session } = context;\n\tconst { emdash } = locals;\n\n\ttry {\n\t\tconst sessionUser = await resolveSessionUser(session);\n\t\tif (sessionUser?.id && emdash?.db) {\n\t\t\tconst adapter = createKyselyAdapter(emdash.db);\n\t\t\tconst user = await adapter.getUserById(sessionUser.id);\n\t\t\tif (user && !user.disabled) {\n\t\t\t\tlocals.user = user;\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Silently continue — public page should render normally\n\t}\n\n\treturn next();\n}\n\n/**\n * Handle external auth provider authentication (Cloudflare Access, etc.)\n */\nasync function handleExternalAuth(\n\tcontext: Parameters<Parameters<typeof defineMiddleware>[0]>[0],\n\tnext: Parameters<Parameters<typeof defineMiddleware>[0]>[1],\n\tauthMode: ExternalAuthMode,\n\t_isApiRoute: boolean,\n): Promise<Response> {\n\tconst { locals, request } = context;\n\tconst { emdash } = locals;\n\n\ttry {\n\t\t// Use the authenticate function from the virtual module\n\t\t// (statically imported at build time to work with Cloudflare Workers)\n\t\tif (typeof virtualAuthenticate !== \"function\") {\n\t\t\tthrow new Error(\n\t\t\t\t`Auth provider ${authMode.entrypoint} does not export an authenticate function`,\n\t\t\t);\n\t\t}\n\n\t\t// Authenticate via the provider\n\t\tconst authResult = await virtualAuthenticate(request, authMode.config);\n\n\t\t// Get external auth config for auto-provision settings\n\t\t// eslint-disable-next-line typescript/no-unsafe-type-assertion -- narrowing AuthModeConfig to ExternalAuthConfig after provider check\n\t\tconst externalConfig = authMode.config as ExternalAuthConfig;\n\n\t\t// Find or create user\n\t\tconst adapter = createKyselyAdapter(emdash.db);\n\t\tlet user = await adapter.getUserByEmail(authResult.email);\n\n\t\tif (!user) {\n\t\t\t// User doesn't exist\n\t\t\tif (externalConfig.autoProvision === false) {\n\t\t\t\treturn new Response(\"User not authorized\", {\n\t\t\t\t\tstatus: 403,\n\t\t\t\t\theaders: { \"Content-Type\": \"text/plain\", ...MW_CACHE_HEADERS },\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Check if this is the first user (they become admin)\n\t\t\tconst userCount = await emdash.db\n\t\t\t\t.selectFrom(\"users\")\n\t\t\t\t.select(emdash.db.fn.count(\"id\").as(\"count\"))\n\t\t\t\t.executeTakeFirst();\n\n\t\t\tconst isFirstUser = Number(userCount?.count ?? 0) === 0;\n\t\t\tconst role = isFirstUser ? ROLE_ADMIN : authResult.role;\n\n\t\t\t// Create user\n\t\t\tconst now = new Date().toISOString();\n\t\t\tconst newUser = {\n\t\t\t\tid: ulid(),\n\t\t\t\temail: authResult.email,\n\t\t\t\tname: authResult.name,\n\t\t\t\trole,\n\t\t\t\temail_verified: 1,\n\t\t\t\tcreated_at: now,\n\t\t\t\tupdated_at: now,\n\t\t\t};\n\n\t\t\tawait emdash.db.insertInto(\"users\").values(newUser).execute();\n\n\t\t\tuser = await adapter.getUserByEmail(authResult.email);\n\n\t\t\tconsole.log(\n\t\t\t\t`[external-auth] Provisioned user: ${authResult.email} (role: ${role}, first: ${isFirstUser})`,\n\t\t\t);\n\t\t} else {\n\t\t\t// User exists - check if we need to sync anything\n\t\t\tconst updates: Record<string, unknown> = {};\n\t\t\tlet newName: string | undefined;\n\t\t\tlet newRole: RoleLevel | undefined;\n\n\t\t\tif (externalConfig.syncName !== false && authResult.name && user.name !== authResult.name) {\n\t\t\t\tnewName = authResult.name;\n\t\t\t\tupdates.name = newName;\n\t\t\t}\n\n\t\t\t// Sync role if enabled\n\t\t\tif (externalConfig.syncRoles && user.role !== authResult.role) {\n\t\t\t\tnewRole = authResult.role;\n\t\t\t\tupdates.role = newRole;\n\t\t\t}\n\n\t\t\tif (Object.keys(updates).length > 0) {\n\t\t\t\tupdates.updated_at = new Date().toISOString();\n\t\t\t\tawait emdash.db.updateTable(\"users\").set(updates).where(\"id\", \"=\", user.id).execute();\n\n\t\t\t\tuser = {\n\t\t\t\t\t...user,\n\t\t\t\t\t...(newName ? { name: newName } : {}),\n\t\t\t\t\t...(newRole ? { role: newRole } : {}),\n\t\t\t\t};\n\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[external-auth] Updated user ${authResult.email}:`,\n\t\t\t\t\tObject.keys(updates).filter((k) => k !== \"updated_at\"),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (!user) {\n\t\t\t// This shouldn't happen, but handle it gracefully\n\t\t\treturn new Response(\"Failed to provision user\", {\n\t\t\t\tstatus: 500,\n\t\t\t\theaders: { \"Content-Type\": \"text/plain\", ...MW_CACHE_HEADERS },\n\t\t\t});\n\t\t}\n\n\t\t// Check if user is disabled locally\n\t\tif (user.disabled) {\n\t\t\treturn new Response(\"Account disabled\", {\n\t\t\t\tstatus: 403,\n\t\t\t\theaders: { \"Content-Type\": \"text/plain\", ...MW_CACHE_HEADERS },\n\t\t\t});\n\t\t}\n\n\t\t// Set user in locals\n\t\tlocals.user = user;\n\n\t\t// Persist to session so public pages can identify the user\n\t\t// (external auth headers are only verified on /_emdash routes)\n\t\tconst { session } = context;\n\t\tsession?.set(\"user\", { id: user.id });\n\n\t\treturn next();\n\t} catch (error) {\n\t\tconsole.error(\"[external-auth] Auth error:\", error);\n\n\t\treturn new Response(\"Authentication failed\", {\n\t\t\tstatus: 401,\n\t\t\theaders: { \"Content-Type\": \"text/plain\", ...MW_CACHE_HEADERS },\n\t\t});\n\t}\n}\n\n/**\n * Try to authenticate via Bearer token (API token or OAuth token).\n *\n * Returns:\n * - \"authenticated\" if token is valid and user is resolved\n * - \"invalid\" if a token was provided but is invalid/expired\n * - \"none\" if no Bearer token was provided\n */\nasync function handleBearerAuth(\n\tcontext: Parameters<Parameters<typeof defineMiddleware>[0]>[0],\n): Promise<\"authenticated\" | \"invalid\" | \"none\"> {\n\tconst authHeader = context.request.headers.get(\"Authorization\");\n\tif (!authHeader?.startsWith(\"Bearer \")) return \"none\";\n\n\tconst token = authHeader.slice(7);\n\tif (!token) return \"none\";\n\n\tconst { locals } = context;\n\tconst { emdash } = locals;\n\tif (!emdash?.db) return \"none\";\n\n\t// Resolve token based on prefix\n\tlet resolved: ResolvedBearerToken | null = null;\n\n\tif (token.startsWith(\"ec_pat_\")) {\n\t\tresolved = await resolveApiToken(emdash.db, token);\n\t} else if (token.startsWith(\"ec_oat_\")) {\n\t\tresolved = await resolveOAuthToken(emdash.db, token);\n\t} else {\n\t\t// Unknown token format\n\t\treturn \"invalid\";\n\t}\n\n\tif (!resolved) return \"invalid\";\n\n\t// Look up the user\n\tconst adapter = createKyselyAdapter(emdash.db);\n\tconst user = await adapter.getUserById(resolved.userId);\n\n\tif (!user || user.disabled) return \"invalid\";\n\n\t// Set user and scopes on locals\n\tlocals.user = user;\n\tlocals.tokenScopes = resolved.scopes;\n\tlocals.tokenId = resolved.tokenId;\n\n\treturn \"authenticated\";\n}\n\n/**\n * Handle passkey (session-based) authentication\n */\nasync function handlePasskeyAuth(\n\tcontext: Parameters<Parameters<typeof defineMiddleware>[0]>[0],\n\tnext: Parameters<Parameters<typeof defineMiddleware>[0]>[1],\n\tisApiRoute: boolean,\n): Promise<Response> {\n\tconst { url, locals, session } = context;\n\tconst { emdash } = locals;\n\n\ttry {\n\t\t// Check session for user (session.get returns a Promise)\n\t\tconst sessionUser = await resolveSessionUser(session);\n\n\t\tif (!sessionUser?.id) {\n\t\t\tif (isApiRoute) {\n\t\t\t\treturn apiError(\"NOT_AUTHENTICATED\", \"Not authenticated\", 401);\n\t\t\t}\n\t\t\tconst loginUrl = new URL(\"/_emdash/admin/login\", getPublicOrigin(url, emdash?.config));\n\t\t\t// Keep the query string: a token-bearing link that lands here must\n\t\t\t// still carry its token after login.\n\t\t\tloginUrl.searchParams.set(\"redirect\", url.pathname + url.search);\n\t\t\treturn context.redirect(loginUrl.toString());\n\t\t}\n\n\t\t// Get full user from database\n\t\tconst adapter = createKyselyAdapter(emdash.db);\n\t\tconst user = await adapter.getUserById(sessionUser.id);\n\n\t\tif (!user) {\n\t\t\t// User no longer exists - clear session\n\t\t\tsession?.destroy();\n\t\t\tif (isApiRoute) {\n\t\t\t\treturn apiError(\"NOT_FOUND\", \"User not found\", 401);\n\t\t\t}\n\t\t\tconst loginUrl = new URL(\"/_emdash/admin/login\", getPublicOrigin(url, emdash?.config));\n\t\t\treturn context.redirect(loginUrl.toString());\n\t\t}\n\n\t\t// Check if user is disabled\n\t\tif (user.disabled) {\n\t\t\tsession?.destroy();\n\t\t\tif (isApiRoute) {\n\t\t\t\treturn apiError(\"ACCOUNT_DISABLED\", \"Account disabled\", 403);\n\t\t\t}\n\t\t\tconst loginUrl = new URL(\"/_emdash/admin/login\", getPublicOrigin(url, emdash?.config));\n\t\t\tloginUrl.searchParams.set(\"error\", \"account_disabled\");\n\t\t\treturn context.redirect(loginUrl.toString());\n\t\t}\n\n\t\t// Set user in locals for use by routes\n\t\tlocals.user = user;\n\t} catch (error) {\n\t\tconsole.error(\"Auth middleware error:\", error);\n\t\t// On error, redirect to login\n\t\treturn context.redirect(\"/_emdash/admin/login\");\n\t}\n\n\treturn next();\n}\n\n// =============================================================================\n// Token scope enforcement\n// =============================================================================\n\n/**\n * Scope rules: ordered list of (pathPrefix, method, requiredScope) tuples.\n * First matching rule wins. Methods: \"*\" = any, \"WRITE\" = POST/PUT/PATCH/DELETE.\n * A list of scopes is satisfied by holding any one of them.\n *\n * Routes not matched by any rule default to \"admin\" scope (fail-closed).\n */\nconst SCOPE_RULES: Array<[prefix: string, method: string, scope: string | readonly string[]]> = [\n\t// Content routes\n\t[\"/_emdash/api/content\", \"GET\", \"content:read\"],\n\t[\"/_emdash/api/content\", \"WRITE\", \"content:write\"],\n\n\t// Media routes (excluding /file/ which is public)\n\t[\"/_emdash/api/media/file\", \"*\", \"media:read\"], // public anyway, but scope if token-authed\n\t[\"/_emdash/api/media\", \"GET\", \"media:read\"],\n\t[\"/_emdash/api/media\", \"WRITE\", \"media:write\"],\n\n\t// Schema routes\n\t[\"/_emdash/api/schema\", \"GET\", \"schema:read\"],\n\t[\"/_emdash/api/schema\", \"WRITE\", \"schema:write\"],\n\n\t// Taxonomy, menu, section, widget, revision — all content domain\n\t// GET uses content:read (implicit from taxonomies:read / menus:read via role).\n\t// WRITE uses the granular scope so tokens with only taxonomies:manage or\n\t// menus:manage are not rejected. content:write implicitly grants these via\n\t// IMPLICIT_SCOPE_GRANTS in @emdash-cms/auth.\n\t[\"/_emdash/api/taxonomies\", \"GET\", \"content:read\"],\n\t[\"/_emdash/api/taxonomies/bulk-tag\", \"WRITE\", \"content:write\"],\n\t[\"/_emdash/api/taxonomies\", \"WRITE\", \"taxonomies:manage\"],\n\t[\"/_emdash/api/menus\", \"GET\", \"content:read\"],\n\t[\"/_emdash/api/menus\", \"WRITE\", \"menus:manage\"],\n\t[\"/_emdash/api/sections\", \"GET\", \"content:read\"],\n\t[\"/_emdash/api/sections\", \"WRITE\", \"content:write\"],\n\t[\"/_emdash/api/widget-areas\", \"GET\", \"content:read\"],\n\t[\"/_emdash/api/widget-areas\", \"WRITE\", \"content:write\"],\n\t[\"/_emdash/api/revisions\", \"GET\", \"content:read\"],\n\t[\"/_emdash/api/revisions\", \"WRITE\", \"content:write\"],\n\n\t// Search\n\t[\"/_emdash/api/search\", \"GET\", \"content:read\"],\n\t[\"/_emdash/api/search\", \"WRITE\", \"admin\"],\n\n\t// Site transfer — must precede the generic /admin rule so a token holding\n\t// only a transfer scope reaches the route, which requires its specific one.\n\t[\"/_emdash/api/admin/transfer\", \"*\", TRANSFER_SCOPES],\n\n\t// Import, admin, plugins — all require admin scope\n\t[\"/_emdash/api/import\", \"*\", \"admin\"],\n\t[\"/_emdash/api/admin\", \"*\", \"admin\"],\n\t[\"/_emdash/api/plugins\", \"*\", \"admin\"],\n\n\t// Backups are a full-site content export and must precede the generic\n\t// settings rules, which would otherwise let a settings:read token through.\n\t[\"/_emdash/api/settings/backups\", \"*\", \"admin\"],\n\n\t// Settings — use granular scopes so tokens with settings:read or\n\t// settings:manage are not rejected at the middleware level.\n\t[\"/_emdash/api/settings\", \"GET\", \"settings:read\"],\n\t[\"/_emdash/api/settings\", \"WRITE\", \"settings:manage\"],\n];\n\nconst WRITE_METHODS = new Set([\"POST\", \"PUT\", \"PATCH\", \"DELETE\"]);\n\n/**\n * Enforce API token scopes based on the request URL and HTTP method.\n * Returns a 403 Response if the scope is insufficient, or null if allowed.\n *\n * Session-authenticated requests (tokenScopes === undefined) are never checked.\n */\nfunction enforceTokenScope(\n\tpathname: string,\n\tmethod: string,\n\ttokenScopes: string[] | undefined,\n): Response | null {\n\t// Session auth — implicit full access, no scope restrictions\n\tif (!tokenScopes) return null;\n\n\t// MCP is authenticated here, but each tool enforces its own scope. A\n\t// blanket content:read/admin requirement would prevent plugin-scoped tokens\n\t// from reaching `mcp/server.ts`, where the actual tool policy lives.\n\tif (pathname === MCP_ENDPOINT_PATH) return null;\n\n\tconst isWrite = WRITE_METHODS.has(method);\n\n\tfor (const [prefix, ruleMethod, scope] of SCOPE_RULES) {\n\t\t// Match exact prefix or prefix followed by /\n\t\tif (pathname !== prefix && !pathname.startsWith(prefix + \"/\")) continue;\n\n\t\t// Check method match\n\t\tif (ruleMethod === \"*\" || (ruleMethod === \"WRITE\" && isWrite) || ruleMethod === method) {\n\t\t\tconst anyOf = typeof scope === \"string\" ? [scope] : scope;\n\t\t\tif (anyOf.some((required) => hasScope(tokenScopes, required))) return null;\n\n\t\t\treturn apiError(\n\t\t\t\t\"INSUFFICIENT_SCOPE\",\n\t\t\t\t`Token lacks required scope: ${anyOf.join(\" or \")}`,\n\t\t\t\t403,\n\t\t\t);\n\t\t}\n\t}\n\n\t// No rule matched — default to admin scope (fail-closed)\n\tif (hasScope(tokenScopes, \"admin\")) return null;\n\n\treturn apiError(\"INSUFFICIENT_SCOPE\", \"Token lacks required scope: admin\", 403);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"auth.mjs","names":["virtualAuthenticate"],"sources":["../../../src/api/csrf.ts","../../../src/astro/middleware/csp.ts","../../../src/astro/middleware/auth.ts"],"sourcesContent":["/**\n * CSRF protection utilities.\n *\n * Two mechanisms:\n * 1. Custom header check (X-EmDash-Request: 1) — used for authenticated API routes.\n * Browsers block cross-origin custom headers, so presence proves same-origin.\n * 2. Origin check — used for public API routes that skip auth. Compares the Origin\n * header against the request origin. Same approach as Astro's `checkOrigin`.\n */\n\nimport { apiError } from \"./error.js\";\n\n/**\n * Origin-based CSRF check for public API routes that skip auth.\n *\n * State-changing requests (POST/PUT/DELETE) to public endpoints must either:\n * 1. Include the X-EmDash-Request: 1 header (custom header blocked cross-origin), OR\n * 2. Have an Origin header matching the request origin (or the configured public origin)\n *\n * This prevents cross-origin form submissions (which can't set custom headers)\n * and cross-origin fetch (blocked by CORS unless allowed). Same-origin requests\n * always include a matching Origin header.\n *\n * Returns a 403 Response if the check fails, or null if allowed.\n *\n * @param request The incoming request\n * @param url The request URL (internal origin)\n * @param publicOrigin The public-facing origin from config.siteUrl. Must be\n * `undefined` when absent — never `null` or `\"\"` (security invariant H-1a).\n */\nexport function checkPublicCsrf(\n\trequest: Request,\n\turl: URL,\n\tpublicOrigin?: string,\n): Response | null {\n\t// Custom header present — browser blocks cross-origin custom headers\n\tconst csrfHeader = request.headers.get(\"X-EmDash-Request\");\n\tif (csrfHeader === \"1\") return null;\n\n\t// Check Origin header — present on all POST/PUT/DELETE from browsers\n\tconst origin = request.headers.get(\"Origin\");\n\tif (origin) {\n\t\ttry {\n\t\t\tconst originUrl = new URL(origin);\n\t\t\t// Accept if Origin matches either the internal or public origin\n\t\t\tif (originUrl.origin === url.origin) return null;\n\t\t\tif (publicOrigin && originUrl.origin === publicOrigin) return null;\n\t\t} catch {\n\t\t\t// Malformed Origin — fall through to reject\n\t\t}\n\n\t\treturn apiError(\"CSRF_REJECTED\", \"Cross-origin request blocked\", 403);\n\t}\n\n\t// No Origin header — non-browser client (curl, server-to-server).\n\t// Allow these through since CSRF is a browser-specific attack vector.\n\t// Server-to-server requests don't carry ambient credentials (cookies).\n\treturn null;\n}\n","/**\n * Strict Content-Security-Policy for /_emdash routes (admin + API).\n *\n * Applied via middleware header rather than Astro's built-in CSP because\n * Astro's auto-hashing defeats 'unsafe-inline' (CSP3 ignores 'unsafe-inline'\n * when hashes are present), which would break user-facing pages.\n *\n * img-src allows any HTTPS origin because the admin renders user content that\n * may reference external images (migrations, external hosting, embeds).\n * Plugin security does not rely on img-src -- plugins run in V8 isolates with\n * no DOM access. connect-src stays at 'self' unless the experimental registry\n * and/or the configured storage endpoint (for direct-to-S3 signed uploads)\n * are configured, in which case those origins are allowed too.\n */\nimport type { RegistryConfigInput } from \"../../registry/types.js\";\nimport type { Storage } from \"../../storage/types.js\";\nimport type { StorageDescriptor } from \"../storage/types.js\";\n\n/** Entrypoint constant used by the `s3()` adapter (see `astro/storage/adapters.ts`). */\nconst S3_ADAPTER_ENTRYPOINT = \"emdash/storage/s3\";\n\n/**\n * Storage entrypoints are free to shape their config however they like, so\n * `endpoint` isn't a known field on `StorageDescriptor[\"config\"]` -- only\n * S3-compatible adapters (R2, S3, Minio, ...) set it. Anything else (e.g.\n * local filesystem storage) simply has no `endpoint` to allow.\n *\n * The `s3()` adapter resolves any field omitted from its config -- including\n * `endpoint` -- from the matching `S3_*` env var at runtime (see\n * `storage/s3.ts`'s `resolveS3Config`). A site configured as `s3({ ... })`\n * with only `S3_ENDPOINT` set has no `endpoint` in the descriptor's config,\n * so fall back to that env var for S3-adapter storage. Custom adapters can\n * expose their runtime upload origin through `getClientUploadOrigin()`.\n */\nexport function getConfiguredStorageEndpoint(\n\tstorage: StorageDescriptor | undefined,\n\truntimeStorage?: Pick<Storage, \"getClientUploadOrigin\"> | null,\n): string | undefined {\n\tconst config = storage?.config;\n\tif (typeof config === \"object\" && config !== null && \"endpoint\" in config) {\n\t\tconst endpoint = config.endpoint;\n\t\tif (typeof endpoint === \"string\") return endpoint;\n\t}\n\n\tif (storage?.entrypoint === S3_ADAPTER_ENTRYPOINT) {\n\t\tconst envEndpoint =\n\t\t\ttypeof process !== \"undefined\" && process.env ? process.env.S3_ENDPOINT : undefined;\n\t\tif (envEndpoint) return envEndpoint;\n\t}\n\n\treturn runtimeStorage?.getClientUploadOrigin?.();\n}\n\nfunction getRegistryAggregatorOrigin(\n\tregistry: RegistryConfigInput | undefined,\n): string | undefined {\n\tconst aggregatorUrl = typeof registry === \"string\" ? registry : registry?.aggregatorUrl;\n\tif (!aggregatorUrl) return undefined;\n\n\ttry {\n\t\tconst url = new URL(aggregatorUrl);\n\t\tif (url.protocol !== \"http:\" && url.protocol !== \"https:\") return undefined;\n\t\treturn url.origin;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction getHttpOrigin(rawUrl: string | undefined): string | undefined {\n\tif (!rawUrl) return undefined;\n\n\ttry {\n\t\tconst url = new URL(rawUrl);\n\t\tif (url.protocol !== \"http:\" && url.protocol !== \"https:\") return undefined;\n\t\treturn url.origin;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function buildEmDashCsp(registry?: RegistryConfigInput, storageEndpoint?: string): string {\n\tconst connectSrc = [\"connect-src 'self'\"];\n\tconst origins = new Set<string>();\n\tconst registryAggregatorOrigin = getRegistryAggregatorOrigin(registry);\n\tif (registryAggregatorOrigin) origins.add(registryAggregatorOrigin);\n\tconst storageOrigin = getHttpOrigin(storageEndpoint);\n\tif (storageOrigin) origins.add(storageOrigin);\n\tconnectSrc.push(...origins);\n\n\treturn [\n\t\t\"default-src 'self'\",\n\t\t\"script-src 'self' 'unsafe-inline'\",\n\t\t\"style-src 'self' 'unsafe-inline'\",\n\t\tconnectSrc.join(\" \"),\n\t\t\"form-action 'self'\",\n\t\t\"frame-src 'self' https:\",\n\t\t\"frame-ancestors 'none'\",\n\t\t\"img-src 'self' https: data: blob:\",\n\t\t\"media-src 'self' blob: https:\",\n\t\t\"object-src 'none'\",\n\t\t\"base-uri 'self'\",\n\t].join(\"; \");\n}\n","/**\n * Auth middleware for admin routes\n *\n * Checks if the user is authenticated and has appropriate permissions.\n * Supports two auth modes:\n * - Passkey (default): Session-based auth with passkey login\n * - External providers: JWT-based auth (Cloudflare Access, etc.)\n *\n * This middleware runs AFTER the setup middleware - so if we get here,\n * we know setup is complete and users exist.\n */\n\nimport type { User, RoleLevel } from \"@emdash-cms/auth\";\nimport { createKyselyAdapter } from \"@emdash-cms/auth/adapters/kysely\";\nimport { defineMiddleware } from \"astro:middleware\";\nimport { ulid } from \"ulidx\";\n// Import auth provider via virtual module (statically bundled)\n// This avoids dynamic import issues in Cloudflare Workers\nimport { authenticate as virtualAuthenticate } from \"virtual:emdash/auth\";\n// @ts-ignore - virtual module\nimport virtualConfig from \"virtual:emdash/config\";\n\nimport { checkPublicCsrf } from \"../../api/csrf.js\";\nimport { apiError } from \"../../api/error.js\";\nimport { getPublicOrigin } from \"../../api/public-url.js\";\n\n/** Cache headers for middleware error responses (matches API_CACHE_HEADERS in api/error.ts) */\nconst MW_CACHE_HEADERS = {\n\t\"Cache-Control\": \"private, no-store\",\n} as const;\nimport {\n\tresolveApiToken,\n\tresolveOAuthToken,\n\ttype ResolvedBearerToken,\n} from \"../../api/handlers/api-tokens.js\";\nimport { hasScope, TRANSFER_SCOPES } from \"../../auth/api-tokens.js\";\nimport { getAuthMode, type ExternalAuthMode } from \"../../auth/mode.js\";\nimport type { ExternalAuthConfig } from \"../../auth/types.js\";\nimport { getRegistryConfigInput } from \"../../registry/config.js\";\nimport { resolveSessionUser } from \"../session-user.js\";\nimport type { EmDashHandlers } from \"../types.js\";\nimport { buildEmDashCsp, getConfiguredStorageEndpoint } from \"./csp.js\";\n\ndeclare global {\n\tnamespace App {\n\t\tinterface Locals {\n\t\t\tuser?: User;\n\t\t\t/** Token scopes when authenticated via API token or OAuth token. Undefined for session auth. */\n\t\t\ttokenScopes?: string[];\n\t\t\t/** Id of the API or OAuth token the request authenticated with. Undefined for session auth. */\n\t\t\ttokenId?: string;\n\t\t\temdash?: EmDashHandlers;\n\t\t}\n\t\tinterface SessionData {\n\t\t\tuser: { id: string };\n\t\t\thasSeenWelcome: boolean;\n\t\t}\n\t}\n}\n\n// Role level constants (matching @emdash-cms/auth)\nconst ROLE_ADMIN = 50;\nconst MCP_ENDPOINT_PATH = \"/_emdash/api/mcp\";\nconst COMMENT_SUBMISSION_PATH = /^\\/_emdash\\/api\\/comments\\/[^/]+\\/[^/]+\\/?$/;\n\nfunction isUnsafeMethod(method: string): boolean {\n\treturn method !== \"GET\" && method !== \"HEAD\" && method !== \"OPTIONS\";\n}\n\nfunction csrfRejectedResponse(): Response {\n\treturn apiError(\"CSRF_REJECTED\", \"Missing required header\", 403);\n}\n\nfunction mcpUnauthorizedResponse(\n\turl: URL,\n\tconfig?: Parameters<typeof getPublicOrigin>[1],\n): Response {\n\tconst origin = getPublicOrigin(url, config);\n\tconst response = apiError(\"NOT_AUTHENTICATED\", \"Not authenticated\", 401);\n\t// Preserve the OAuth discovery header so MCP clients can find the auth server.\n\tresponse.headers.set(\n\t\t\"WWW-Authenticate\",\n\t\t`Bearer resource_metadata=\"${origin}/.well-known/oauth-protected-resource\"`,\n\t);\n\treturn response;\n}\n\n/**\n * API routes that skip auth — each handles its own access control.\n *\n * Prefix entries match any path starting with that prefix.\n * Exact entries (no trailing slash or wildcard) match that path only.\n */\nconst PUBLIC_API_PREFIXES = [\n\t\"/_emdash/api/setup\",\n\t\"/_emdash/api/auth/login\",\n\t\"/_emdash/api/auth/register\",\n\t\"/_emdash/api/auth/dev-bypass\",\n\t\"/_emdash/api/auth/signup/\",\n\t\"/_emdash/api/auth/magic-link/\",\n\t\"/_emdash/api/auth/invite/\",\n\t\"/_emdash/api/auth/oauth/\",\n\t\"/_emdash/api/oauth/device/token\",\n\t\"/_emdash/api/oauth/device/code\",\n\t\"/_emdash/api/oauth/token\",\n\t\"/_emdash/api/oauth/register\",\n\t\"/_emdash/api/comments/\",\n\t\"/_emdash/api/media/file/\",\n\t\"/_emdash/.well-known/\",\n];\n\nconst PUBLIC_API_EXACT = new Set([\n\t\"/_emdash/api/auth/passkey/options\",\n\t\"/_emdash/api/auth/passkey/verify\",\n\t\"/_emdash/api/auth/mode\",\n\t\"/_emdash/api/health\",\n\t\"/_emdash/api/site/domain-proof\",\n\t\"/_emdash/api/oauth/token\",\n\t\"/_emdash/api/snapshot\",\n\t\"/_emdash/api/visual-editing/toolbar-labels\",\n\t// Public site search — read-only. Unauthenticated callers only see\n\t// published content: /search forces status='published' without the\n\t// content:read_drafts permission and /suggest hardcodes it. Admin endpoints\n\t// (/enable, /rebuild, /stats) remain private because they're not in this set.\n\t\"/_emdash/api/search\",\n\t\"/_emdash/api/search/suggest\",\n]);\n\nconst DEV_PUBLIC_API_EXACT = new Set([\"/_emdash/api/typegen\", \"/_emdash/api/dev/scheduled-tasks\"]);\n\n// Build merged public routes at module load from auth provider descriptors.\n// Routes ending with \"/\" are treated as prefixes; all others are exact matches.\nconst { exact: _providerExactRoutes, prefixes: _providerPrefixRoutes } = (() => {\n\tconst exact = new Set<string>();\n\tconst prefixes: string[] = [];\n\tif (!virtualConfig?.authProviders) return { exact, prefixes };\n\tfor (const route of virtualConfig.authProviders.flatMap((p) => p.publicRoutes ?? [])) {\n\t\tif (route.endsWith(\"/\")) {\n\t\t\tprefixes.push(route);\n\t\t} else {\n\t\t\texact.add(route);\n\t\t}\n\t}\n\treturn { exact, prefixes };\n})();\n\n/**\n * OAuth protocol endpoints that are CSRF-exempt by design.\n *\n * These are RFC-defined endpoints (RFC 6749 §3.2, RFC 7591 §3, RFC 8628 §3.1/§3.4)\n * specified to be called cross-origin by external clients (MCP clients, CLIs,\n * native apps). They authenticate each request on its own merits:\n *\n * - /oauth/token: requires PKCE code_verifier, device_code, or refresh_token\n * - /oauth/register: RFC 7591 dynamic client registration — anonymous by design\n * - /oauth/device/code: RFC 8628 device flow initiation — anonymous by design\n * - /oauth/device/token: requires device_code the client already holds\n *\n * None of these rely on ambient cookie credentials, so browser-based CSRF\n * attacks have nothing to exploit. The endpoints themselves advertise\n * `Access-Control-Allow-Origin: *`. Note: /oauth/device/authorize (the user\n * consent step) is NOT in this list — it is session-authenticated.\n */\nconst CSRF_EXEMPT_PUBLIC_ROUTES = new Set([\n\t\"/_emdash/api/oauth/token\",\n\t\"/_emdash/api/oauth/register\",\n\t\"/_emdash/api/oauth/device/code\",\n\t\"/_emdash/api/oauth/device/token\",\n]);\n\nfunction isPublicEmDashRoute(pathname: string): boolean {\n\tif (PUBLIC_API_EXACT.has(pathname)) return true;\n\tif (PUBLIC_API_PREFIXES.some((p) => pathname.startsWith(p))) return true;\n\tif (_providerExactRoutes.has(pathname)) return true;\n\tif (_providerPrefixRoutes.some((p) => pathname.startsWith(p))) return true;\n\tif (import.meta.env.DEV && DEV_PUBLIC_API_EXACT.has(pathname)) return true;\n\treturn false;\n}\n\nfunction isCsrfExemptPublicRoute(pathname: string): boolean {\n\treturn CSRF_EXEMPT_PUBLIC_ROUTES.has(pathname);\n}\n\nexport const onRequest = defineMiddleware(async (context, next) => {\n\tconst { url } = context;\n\n\t// Only check auth on admin routes and API routes\n\tconst isAdminRoute = url.pathname.startsWith(\"/_emdash/admin\");\n\tconst isSetupRoute = url.pathname.startsWith(\"/_emdash/admin/setup\");\n\tconst isApiRoute = url.pathname.startsWith(\"/_emdash/api\");\n\tconst isPublicApiRoute = isPublicEmDashRoute(url.pathname);\n\n\tconst isPublicRoute = !isAdminRoute && !isApiRoute;\n\n\t// Public API routes skip auth but still need CSRF protection on state-changing methods.\n\t// We check Origin header against the request host (same approach as Astro's checkOrigin).\n\t// This prevents cross-origin form submissions and fetch requests from malicious sites.\n\tif (isPublicApiRoute) {\n\t\tconst method = context.request.method.toUpperCase();\n\t\tif (\n\t\t\tisUnsafeMethod(method) &&\n\t\t\t!isCsrfExemptPublicRoute(url.pathname) // OAuth protocol endpoints — cross-origin by design\n\t\t) {\n\t\t\tconst publicOrigin = getPublicOrigin(url, context.locals.emdash?.config);\n\t\t\tconst csrfError = checkPublicCsrf(context.request, url, publicOrigin);\n\t\t\tif (csrfError) return csrfError;\n\t\t}\n\t\tif (method === \"POST\" && COMMENT_SUBMISSION_PATH.test(url.pathname)) {\n\t\t\treturn handlePublicRouteAuth(context, next);\n\t\t}\n\t\t// Search filters drafts by permission, so resolve the session user when\n\t\t// one exists; anonymous callers skip the user DB lookup. Bearer tokens\n\t\t// are not resolved on public routes; token callers continue to receive\n\t\t// published results only.\n\t\tif (url.pathname === \"/_emdash/api/search\") {\n\t\t\treturn handlePublicRouteAuth(context, next);\n\t\t}\n\t\treturn next();\n\t}\n\n\t// Plugin routes: soft auth (resolve user if credentials present, but never block).\n\t// The catch-all handler decides per-route whether auth is required (public vs private).\n\t// Public plugin routes that accept POST are vulnerable to cross-origin form submissions,\n\t// so we apply the same Origin-based CSRF check as other public routes.\n\tconst isPluginRoute = url.pathname.startsWith(\"/_emdash/api/plugins/\");\n\tif (isPluginRoute) {\n\t\tconst method = context.request.method.toUpperCase();\n\t\tif (method !== \"GET\" && method !== \"HEAD\" && method !== \"OPTIONS\") {\n\t\t\tconst publicOrigin = getPublicOrigin(url, context.locals.emdash?.config);\n\t\t\tconst csrfError = checkPublicCsrf(context.request, url, publicOrigin);\n\t\t\tif (csrfError) return csrfError;\n\t\t}\n\t\treturn handlePluginRouteAuth(context, next);\n\t}\n\n\t// Setup routes: skip auth but still enforce CSRF on state-changing methods\n\tif (isSetupRoute) {\n\t\tconst method = context.request.method.toUpperCase();\n\t\tif (method !== \"GET\" && method !== \"HEAD\" && method !== \"OPTIONS\") {\n\t\t\tconst csrfHeader = context.request.headers.get(\"X-EmDash-Request\");\n\t\t\tif (csrfHeader !== \"1\") {\n\t\t\t\treturn apiError(\"CSRF_REJECTED\", \"Missing required header\", 403);\n\t\t\t}\n\t\t}\n\t\tconst response = await next();\n\t\tif (!import.meta.env.DEV) {\n\t\t\tresponse.headers.set(\n\t\t\t\t\"Content-Security-Policy\",\n\t\t\t\tbuildEmDashCsp(\n\t\t\t\t\tgetRegistryConfigInput(context.locals.emdash?.config.registry),\n\t\t\t\t\tgetConfiguredStorageEndpoint(\n\t\t\t\t\t\tcontext.locals.emdash?.config.storage,\n\t\t\t\t\t\tcontext.locals.emdash?.storage,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\treturn response;\n\t}\n\n\t// For public routes: soft auth check (set locals.user if session exists, but never block)\n\tif (isPublicRoute) {\n\t\treturn handlePublicRouteAuth(context, next);\n\t}\n\n\t// --- Everything below is /_emdash (admin + API) ---\n\n\t// Try Bearer token auth first (API tokens and OAuth tokens).\n\t// If successful, skip CSRF (tokens aren't ambient credentials like cookies).\n\tconst bearerResult = await handleBearerAuth(context);\n\n\tif (bearerResult === \"invalid\") {\n\t\tconst response = apiError(\"INVALID_TOKEN\", \"Invalid or expired token\", 401);\n\t\t// Add WWW-Authenticate header on MCP endpoint 401s to trigger OAuth discovery\n\t\tif (url.pathname === \"/_emdash/api/mcp\") {\n\t\t\tconst origin = getPublicOrigin(url, context.locals.emdash?.config);\n\t\t\tresponse.headers.set(\n\t\t\t\t\"WWW-Authenticate\",\n\t\t\t\t`Bearer resource_metadata=\"${origin}/.well-known/oauth-protected-resource\"`,\n\t\t\t);\n\t\t}\n\t\treturn response;\n\t}\n\n\tconst isTokenAuth = bearerResult === \"authenticated\";\n\n\t// MCP discovery/tooling is bearer-only. Session/external auth should never\n\t// be consulted for this endpoint, and unauthenticated requests must return\n\t// the OAuth discovery-style 401 response.\n\tconst method = context.request.method.toUpperCase();\n\tconst isMcpEndpoint = url.pathname === MCP_ENDPOINT_PATH;\n\tif (isMcpEndpoint && !isTokenAuth) {\n\t\treturn mcpUnauthorizedResponse(url, context.locals.emdash?.config);\n\t}\n\n\t// CSRF protection: require X-EmDash-Request header on state-changing requests.\n\t// Skip for token-authenticated requests (tokens aren't ambient credentials).\n\t// Browsers block cross-origin custom headers, so this prevents CSRF without tokens.\n\t// OAuth authorize consent is exempt: it's a standard HTML form POST that can't\n\t// include custom headers. The consent flow is protected by session + single-use codes.\n\tconst isOAuthConsent = url.pathname.startsWith(\"/_emdash/oauth/authorize\");\n\tif (\n\t\tisApiRoute &&\n\t\t!isTokenAuth &&\n\t\t!isOAuthConsent &&\n\t\tisUnsafeMethod(method) &&\n\t\t!isPublicApiRoute\n\t) {\n\t\tconst csrfHeader = context.request.headers.get(\"X-EmDash-Request\");\n\t\tif (csrfHeader !== \"1\") {\n\t\t\treturn csrfRejectedResponse();\n\t\t}\n\t}\n\n\t// If already authenticated via Bearer token, enforce scope then skip session/external auth\n\tif (isTokenAuth) {\n\t\t// Enforce API token scopes based on URL pattern + HTTP method\n\t\tconst scopeError = enforceTokenScope(url.pathname, method, context.locals.tokenScopes);\n\t\tif (scopeError) return scopeError;\n\n\t\tconst response = await next();\n\t\tif (!import.meta.env.DEV) {\n\t\t\tresponse.headers.set(\n\t\t\t\t\"Content-Security-Policy\",\n\t\t\t\tbuildEmDashCsp(\n\t\t\t\t\tgetRegistryConfigInput(context.locals.emdash?.config.registry),\n\t\t\t\t\tgetConfiguredStorageEndpoint(\n\t\t\t\t\t\tcontext.locals.emdash?.config.storage,\n\t\t\t\t\t\tcontext.locals.emdash?.storage,\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\treturn response;\n\t}\n\n\tconst response = await handleEmDashAuth(context, next);\n\n\t// Set strict CSP on all /_emdash responses (prod only)\n\tif (!import.meta.env.DEV) {\n\t\tresponse.headers.set(\n\t\t\t\"Content-Security-Policy\",\n\t\t\tbuildEmDashCsp(\n\t\t\t\tgetRegistryConfigInput(context.locals.emdash?.config.registry),\n\t\t\t\tgetConfiguredStorageEndpoint(\n\t\t\t\t\tcontext.locals.emdash?.config.storage,\n\t\t\t\t\tcontext.locals.emdash?.storage,\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t}\n\n\treturn response;\n});\n\n/**\n * Auth handling for /_emdash routes. Returns a Response from either\n * an auth error/redirect or the downstream route handler.\n */\nasync function handleEmDashAuth(\n\tcontext: Parameters<Parameters<typeof defineMiddleware>[0]>[0],\n\tnext: Parameters<Parameters<typeof defineMiddleware>[0]>[1],\n): Promise<Response> {\n\tconst { url, locals } = context;\n\tconst { emdash } = locals;\n\n\t// Pages an anonymous visitor must be able to reach: login itself, and the\n\t// two token-bearing pages that emails link to.\n\tconst isPublicAdminRoute =\n\t\turl.pathname.startsWith(\"/_emdash/admin/login\") ||\n\t\turl.pathname.startsWith(\"/_emdash/admin/signup\") ||\n\t\turl.pathname.startsWith(\"/_emdash/admin/invite/accept\");\n\tconst isApiRoute = url.pathname.startsWith(\"/_emdash/api\");\n\n\tif (!emdash?.db) {\n\t\t// No database - let the admin handle this error\n\t\treturn next();\n\t}\n\n\t// Determine auth mode from config\n\tconst authMode = getAuthMode(emdash.config);\n\n\tif (authMode.type === \"external\") {\n\t\t// In dev mode, fall back to passkey auth since external JWT won't be present\n\t\tif (import.meta.env.DEV) {\n\t\t\tif (isPublicAdminRoute) {\n\t\t\t\treturn next();\n\t\t\t}\n\n\t\t\treturn handlePasskeyAuth(context, next, isApiRoute);\n\t\t}\n\n\t\t// External auth provider (Cloudflare Access, etc.)\n\t\treturn handleExternalAuth(context, next, authMode, isApiRoute);\n\t}\n\n\t// Passkey authentication (default)\n\tif (isPublicAdminRoute) {\n\t\treturn next();\n\t}\n\n\treturn handlePasskeyAuth(context, next, isApiRoute);\n}\n\n/**\n * Plugin-route auth. Resolves the user in three steps, stopping at the first that\n * applies:\n *\n * 1. Bearer token (all modes). A valid token authenticates; an invalid/expired one\n * returns 401 (we never silently downgrade a bad token to anonymous).\n * 2. External provider — only for a *private* route in production external-auth\n * mode. Here `handleExternalAuth` is the sole authority: the provider (e.g.\n * Cloudflare Access) is re-verified on every request, so it hard-blocks with\n * 401 on failure. It does persist an EmDash session (so public pages can\n * identify the user), but on these routes that session is deliberately NOT\n * consulted as a fallback — the provider check is authoritative every time.\n * 3. Session — everything else (non-external mode, DEV, and all public routes).\n * This is soft: it sets `locals.user` if a session exists but never blocks.\n *\n * Public routes are always allowed through. The catch-all handler still enforces\n * the `plugins:manage` permission and CSRF for private invocations.\n */\nasync function handlePluginRouteAuth(\n\tcontext: Parameters<Parameters<typeof defineMiddleware>[0]>[0],\n\tnext: Parameters<Parameters<typeof defineMiddleware>[0]>[1],\n): Promise<Response> {\n\tconst { locals, url } = context;\n\tconst { emdash } = locals;\n\n\ttry {\n\t\t// Try Bearer token auth first (API tokens and OAuth tokens)\n\t\tconst bearerResult = await handleBearerAuth(context);\n\t\tif (bearerResult === \"authenticated\") {\n\t\t\t// User and tokenScopes are set on locals by handleBearerAuth\n\t\t\treturn next();\n\t\t}\n\t\tif (bearerResult === \"invalid\") {\n\t\t\t// A token was presented but is invalid/expired — return 401 so the\n\t\t\t// caller knows their token is bad (don't silently downgrade to no-auth).\n\t\t\treturn apiError(\"INVALID_TOKEN\", \"Invalid or expired token\", 401);\n\t\t}\n\t\t// \"none\" — no token presented, try external/session auth below.\n\t} catch (error) {\n\t\tconsole.error(\"Plugin route bearer auth error:\", error);\n\t}\n\n\tconst authMode = getAuthMode(emdash?.config);\n\tif (\n\t\tauthMode.type === \"external\" &&\n\t\t!import.meta.env.DEV &&\n\t\t!isPublicPluginApiRoute(url.pathname, emdash)\n\t) {\n\t\treturn handleExternalAuth(context, next, authMode, true);\n\t}\n\n\ttry {\n\t\t// Try session auth (sets locals.user if session exists)\n\t\tconst { session } = context;\n\t\tconst sessionUser = await resolveSessionUser(session);\n\t\tif (sessionUser?.id && emdash?.db) {\n\t\t\tconst adapter = createKyselyAdapter(emdash.db);\n\t\t\tconst user = await adapter.getUserById(sessionUser.id);\n\t\t\tif (user && !user.disabled) {\n\t\t\t\tlocals.user = user;\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\t// Log but don't block — public routes should still work without session\n\t\tconsole.error(\"Plugin route session auth error:\", error);\n\t}\n\n\treturn next();\n}\n\nfunction isPublicPluginApiRoute(pathname: string, emdash: EmDashHandlers | undefined): boolean {\n\tconst prefix = \"/_emdash/api/plugins/\";\n\tconst route = pathname.slice(prefix.length);\n\tconst slashIndex = route.indexOf(\"/\");\n\tif (slashIndex <= 0 || !emdash?.getPluginRouteMeta) return false;\n\n\treturn (\n\t\temdash.getPluginRouteMeta(route.slice(0, slashIndex), route.slice(slashIndex))?.public === true\n\t);\n}\n\n/**\n * Soft auth check for public routes with edit mode cookie.\n * Checks the session and sets locals.user if valid, but never blocks the request.\n */\nasync function handlePublicRouteAuth(\n\tcontext: Parameters<Parameters<typeof defineMiddleware>[0]>[0],\n\tnext: Parameters<Parameters<typeof defineMiddleware>[0]>[1],\n): Promise<Response> {\n\tconst { locals, session } = context;\n\tconst { emdash } = locals;\n\n\ttry {\n\t\tconst sessionUser = await resolveSessionUser(session);\n\t\tif (sessionUser?.id && emdash?.db) {\n\t\t\tconst adapter = createKyselyAdapter(emdash.db);\n\t\t\tconst user = await adapter.getUserById(sessionUser.id);\n\t\t\tif (user && !user.disabled) {\n\t\t\t\tlocals.user = user;\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Silently continue — public page should render normally\n\t}\n\n\treturn next();\n}\n\n/**\n * Handle external auth provider authentication (Cloudflare Access, etc.)\n */\nasync function handleExternalAuth(\n\tcontext: Parameters<Parameters<typeof defineMiddleware>[0]>[0],\n\tnext: Parameters<Parameters<typeof defineMiddleware>[0]>[1],\n\tauthMode: ExternalAuthMode,\n\t_isApiRoute: boolean,\n): Promise<Response> {\n\tconst { locals, request } = context;\n\tconst { emdash } = locals;\n\n\ttry {\n\t\t// Use the authenticate function from the virtual module\n\t\t// (statically imported at build time to work with Cloudflare Workers)\n\t\tif (typeof virtualAuthenticate !== \"function\") {\n\t\t\tthrow new Error(\n\t\t\t\t`Auth provider ${authMode.entrypoint} does not export an authenticate function`,\n\t\t\t);\n\t\t}\n\n\t\t// Authenticate via the provider\n\t\tconst authResult = await virtualAuthenticate(request, authMode.config);\n\n\t\t// Get external auth config for auto-provision settings\n\t\t// eslint-disable-next-line typescript/no-unsafe-type-assertion -- narrowing AuthModeConfig to ExternalAuthConfig after provider check\n\t\tconst externalConfig = authMode.config as ExternalAuthConfig;\n\n\t\t// Find or create user\n\t\tconst adapter = createKyselyAdapter(emdash.db);\n\t\tlet user = await adapter.getUserByEmail(authResult.email);\n\n\t\tif (!user) {\n\t\t\t// User doesn't exist\n\t\t\tif (externalConfig.autoProvision === false) {\n\t\t\t\treturn new Response(\"User not authorized\", {\n\t\t\t\t\tstatus: 403,\n\t\t\t\t\theaders: { \"Content-Type\": \"text/plain\", ...MW_CACHE_HEADERS },\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Check if this is the first user (they become admin)\n\t\t\tconst userCount = await emdash.db\n\t\t\t\t.selectFrom(\"users\")\n\t\t\t\t.select(emdash.db.fn.count(\"id\").as(\"count\"))\n\t\t\t\t.executeTakeFirst();\n\n\t\t\tconst isFirstUser = Number(userCount?.count ?? 0) === 0;\n\t\t\tconst role = isFirstUser ? ROLE_ADMIN : authResult.role;\n\n\t\t\t// Create user\n\t\t\tconst now = new Date().toISOString();\n\t\t\tconst newUser = {\n\t\t\t\tid: ulid(),\n\t\t\t\temail: authResult.email,\n\t\t\t\tname: authResult.name,\n\t\t\t\trole,\n\t\t\t\temail_verified: 1,\n\t\t\t\tcreated_at: now,\n\t\t\t\tupdated_at: now,\n\t\t\t};\n\n\t\t\tawait emdash.db.insertInto(\"users\").values(newUser).execute();\n\n\t\t\tuser = await adapter.getUserByEmail(authResult.email);\n\n\t\t\tconsole.log(\n\t\t\t\t`[external-auth] Provisioned user: ${authResult.email} (role: ${role}, first: ${isFirstUser})`,\n\t\t\t);\n\t\t} else {\n\t\t\t// User exists - check if we need to sync anything\n\t\t\tconst updates: Record<string, unknown> = {};\n\t\t\tlet newName: string | undefined;\n\t\t\tlet newRole: RoleLevel | undefined;\n\n\t\t\tif (externalConfig.syncName !== false && authResult.name && user.name !== authResult.name) {\n\t\t\t\tnewName = authResult.name;\n\t\t\t\tupdates.name = newName;\n\t\t\t}\n\n\t\t\t// Sync role if enabled\n\t\t\tif (externalConfig.syncRoles && user.role !== authResult.role) {\n\t\t\t\tnewRole = authResult.role;\n\t\t\t\tupdates.role = newRole;\n\t\t\t}\n\n\t\t\tif (Object.keys(updates).length > 0) {\n\t\t\t\tupdates.updated_at = new Date().toISOString();\n\t\t\t\tawait emdash.db.updateTable(\"users\").set(updates).where(\"id\", \"=\", user.id).execute();\n\n\t\t\t\tuser = {\n\t\t\t\t\t...user,\n\t\t\t\t\t...(newName ? { name: newName } : {}),\n\t\t\t\t\t...(newRole ? { role: newRole } : {}),\n\t\t\t\t};\n\n\t\t\t\tconsole.log(\n\t\t\t\t\t`[external-auth] Updated user ${authResult.email}:`,\n\t\t\t\t\tObject.keys(updates).filter((k) => k !== \"updated_at\"),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (!user) {\n\t\t\t// This shouldn't happen, but handle it gracefully\n\t\t\treturn new Response(\"Failed to provision user\", {\n\t\t\t\tstatus: 500,\n\t\t\t\theaders: { \"Content-Type\": \"text/plain\", ...MW_CACHE_HEADERS },\n\t\t\t});\n\t\t}\n\n\t\t// Check if user is disabled locally\n\t\tif (user.disabled) {\n\t\t\treturn new Response(\"Account disabled\", {\n\t\t\t\tstatus: 403,\n\t\t\t\theaders: { \"Content-Type\": \"text/plain\", ...MW_CACHE_HEADERS },\n\t\t\t});\n\t\t}\n\n\t\t// Set user in locals\n\t\tlocals.user = user;\n\n\t\t// Persist to session so public pages can identify the user\n\t\t// (external auth headers are only verified on /_emdash routes)\n\t\tconst { session } = context;\n\t\tsession?.set(\"user\", { id: user.id });\n\n\t\treturn next();\n\t} catch (error) {\n\t\tconsole.error(\"[external-auth] Auth error:\", error);\n\n\t\treturn new Response(\"Authentication failed\", {\n\t\t\tstatus: 401,\n\t\t\theaders: { \"Content-Type\": \"text/plain\", ...MW_CACHE_HEADERS },\n\t\t});\n\t}\n}\n\n/**\n * Try to authenticate via Bearer token (API token or OAuth token).\n *\n * Returns:\n * - \"authenticated\" if token is valid and user is resolved\n * - \"invalid\" if a token was provided but is invalid/expired\n * - \"none\" if no Bearer token was provided\n */\nasync function handleBearerAuth(\n\tcontext: Parameters<Parameters<typeof defineMiddleware>[0]>[0],\n): Promise<\"authenticated\" | \"invalid\" | \"none\"> {\n\tconst authHeader = context.request.headers.get(\"Authorization\");\n\tif (!authHeader?.startsWith(\"Bearer \")) return \"none\";\n\n\tconst token = authHeader.slice(7);\n\tif (!token) return \"none\";\n\n\tconst { locals } = context;\n\tconst { emdash } = locals;\n\tif (!emdash?.db) return \"none\";\n\n\t// Resolve token based on prefix\n\tlet resolved: ResolvedBearerToken | null = null;\n\n\tif (token.startsWith(\"ec_pat_\")) {\n\t\tresolved = await resolveApiToken(emdash.db, token);\n\t} else if (token.startsWith(\"ec_oat_\")) {\n\t\tresolved = await resolveOAuthToken(emdash.db, token);\n\t} else {\n\t\t// Unknown token format\n\t\treturn \"invalid\";\n\t}\n\n\tif (!resolved) return \"invalid\";\n\n\t// Look up the user\n\tconst adapter = createKyselyAdapter(emdash.db);\n\tconst user = await adapter.getUserById(resolved.userId);\n\n\tif (!user || user.disabled) return \"invalid\";\n\n\t// Set user and scopes on locals\n\tlocals.user = user;\n\tlocals.tokenScopes = resolved.scopes;\n\tlocals.tokenId = resolved.tokenId;\n\n\treturn \"authenticated\";\n}\n\n/**\n * Handle passkey (session-based) authentication\n */\nasync function handlePasskeyAuth(\n\tcontext: Parameters<Parameters<typeof defineMiddleware>[0]>[0],\n\tnext: Parameters<Parameters<typeof defineMiddleware>[0]>[1],\n\tisApiRoute: boolean,\n): Promise<Response> {\n\tconst { url, locals, session } = context;\n\tconst { emdash } = locals;\n\n\ttry {\n\t\t// Check session for user (session.get returns a Promise)\n\t\tconst sessionUser = await resolveSessionUser(session);\n\n\t\tif (!sessionUser?.id) {\n\t\t\tif (isApiRoute) {\n\t\t\t\treturn apiError(\"NOT_AUTHENTICATED\", \"Not authenticated\", 401);\n\t\t\t}\n\t\t\tconst loginUrl = new URL(\"/_emdash/admin/login\", getPublicOrigin(url, emdash?.config));\n\t\t\t// Keep the query string: a token-bearing link that lands here must\n\t\t\t// still carry its token after login.\n\t\t\tloginUrl.searchParams.set(\"redirect\", url.pathname + url.search);\n\t\t\treturn context.redirect(loginUrl.toString());\n\t\t}\n\n\t\t// Get full user from database\n\t\tconst adapter = createKyselyAdapter(emdash.db);\n\t\tconst user = await adapter.getUserById(sessionUser.id);\n\n\t\tif (!user) {\n\t\t\t// User no longer exists - clear session\n\t\t\tsession?.destroy();\n\t\t\tif (isApiRoute) {\n\t\t\t\treturn apiError(\"NOT_FOUND\", \"User not found\", 401);\n\t\t\t}\n\t\t\tconst loginUrl = new URL(\"/_emdash/admin/login\", getPublicOrigin(url, emdash?.config));\n\t\t\treturn context.redirect(loginUrl.toString());\n\t\t}\n\n\t\t// Check if user is disabled\n\t\tif (user.disabled) {\n\t\t\tsession?.destroy();\n\t\t\tif (isApiRoute) {\n\t\t\t\treturn apiError(\"ACCOUNT_DISABLED\", \"Account disabled\", 403);\n\t\t\t}\n\t\t\tconst loginUrl = new URL(\"/_emdash/admin/login\", getPublicOrigin(url, emdash?.config));\n\t\t\tloginUrl.searchParams.set(\"error\", \"account_disabled\");\n\t\t\treturn context.redirect(loginUrl.toString());\n\t\t}\n\n\t\t// Set user in locals for use by routes\n\t\tlocals.user = user;\n\t} catch (error) {\n\t\tconsole.error(\"Auth middleware error:\", error);\n\t\t// On error, redirect to login\n\t\treturn context.redirect(\"/_emdash/admin/login\");\n\t}\n\n\treturn next();\n}\n\n// =============================================================================\n// Token scope enforcement\n// =============================================================================\n\n/**\n * Scope rules: ordered list of (pathPrefix, method, requiredScope) tuples.\n * First matching rule wins. Methods: \"*\" = any, \"WRITE\" = POST/PUT/PATCH/DELETE.\n * A list of scopes is satisfied by holding any one of them.\n *\n * Routes not matched by any rule default to \"admin\" scope (fail-closed).\n */\nconst SCOPE_RULES: Array<[prefix: string, method: string, scope: string | readonly string[]]> = [\n\t// Content routes\n\t[\"/_emdash/api/content\", \"GET\", \"content:read\"],\n\t[\"/_emdash/api/content\", \"WRITE\", \"content:write\"],\n\n\t// Media routes (excluding /file/ which is public)\n\t[\"/_emdash/api/media/file\", \"*\", \"media:read\"], // public anyway, but scope if token-authed\n\t[\"/_emdash/api/media\", \"GET\", \"media:read\"],\n\t[\"/_emdash/api/media\", \"WRITE\", \"media:write\"],\n\n\t// Schema routes\n\t[\"/_emdash/api/schema\", \"GET\", \"schema:read\"],\n\t[\"/_emdash/api/schema\", \"WRITE\", \"schema:write\"],\n\n\t// Taxonomy, menu, section, widget, revision — all content domain\n\t// GET uses content:read (implicit from taxonomies:read / menus:read via role).\n\t// WRITE uses the granular scope so tokens with only taxonomies:manage or\n\t// menus:manage are not rejected. content:write implicitly grants these via\n\t// IMPLICIT_SCOPE_GRANTS in @emdash-cms/auth.\n\t[\"/_emdash/api/taxonomies\", \"GET\", \"content:read\"],\n\t[\"/_emdash/api/taxonomies/bulk-tag\", \"WRITE\", \"content:write\"],\n\t[\"/_emdash/api/taxonomies\", \"WRITE\", \"taxonomies:manage\"],\n\t[\"/_emdash/api/menus\", \"GET\", \"content:read\"],\n\t[\"/_emdash/api/menus\", \"WRITE\", \"menus:manage\"],\n\t[\"/_emdash/api/sections\", \"GET\", \"content:read\"],\n\t[\"/_emdash/api/sections\", \"WRITE\", \"content:write\"],\n\t[\"/_emdash/api/widget-areas\", \"GET\", \"content:read\"],\n\t[\"/_emdash/api/widget-areas\", \"WRITE\", \"content:write\"],\n\t[\"/_emdash/api/revisions\", \"GET\", \"content:read\"],\n\t[\"/_emdash/api/revisions\", \"WRITE\", \"content:write\"],\n\n\t// Search\n\t[\"/_emdash/api/search\", \"GET\", \"content:read\"],\n\t[\"/_emdash/api/search\", \"WRITE\", \"admin\"],\n\n\t// Site transfer — must precede the generic /admin rule so a token holding\n\t// only a transfer scope reaches the route, which requires its specific one.\n\t[\"/_emdash/api/admin/transfer\", \"*\", TRANSFER_SCOPES],\n\n\t// Import, admin, plugins — all require admin scope\n\t[\"/_emdash/api/import\", \"*\", \"admin\"],\n\t[\"/_emdash/api/admin\", \"*\", \"admin\"],\n\t[\"/_emdash/api/plugins\", \"*\", \"admin\"],\n\n\t// Backups are a full-site content export and must precede the generic\n\t// settings rules, which would otherwise let a settings:read token through.\n\t[\"/_emdash/api/settings/backups\", \"*\", \"admin\"],\n\n\t// Settings — use granular scopes so tokens with settings:read or\n\t// settings:manage are not rejected at the middleware level.\n\t[\"/_emdash/api/settings\", \"GET\", \"settings:read\"],\n\t[\"/_emdash/api/settings\", \"WRITE\", \"settings:manage\"],\n];\n\nconst WRITE_METHODS = new Set([\"POST\", \"PUT\", \"PATCH\", \"DELETE\"]);\n\n/**\n * Enforce API token scopes based on the request URL and HTTP method.\n * Returns a 403 Response if the scope is insufficient, or null if allowed.\n *\n * Session-authenticated requests (tokenScopes === undefined) are never checked.\n */\nfunction enforceTokenScope(\n\tpathname: string,\n\tmethod: string,\n\ttokenScopes: string[] | undefined,\n): Response | null {\n\t// Session auth — implicit full access, no scope restrictions\n\tif (!tokenScopes) return null;\n\n\t// MCP is authenticated here, but each tool enforces its own scope. A\n\t// blanket content:read/admin requirement would prevent plugin-scoped tokens\n\t// from reaching `mcp/server.ts`, where the actual tool policy lives.\n\tif (pathname === MCP_ENDPOINT_PATH) return null;\n\n\tconst isWrite = WRITE_METHODS.has(method);\n\n\tfor (const [prefix, ruleMethod, scope] of SCOPE_RULES) {\n\t\t// Match exact prefix or prefix followed by /\n\t\tif (pathname !== prefix && !pathname.startsWith(prefix + \"/\")) continue;\n\n\t\t// Check method match\n\t\tif (ruleMethod === \"*\" || (ruleMethod === \"WRITE\" && isWrite) || ruleMethod === method) {\n\t\t\tconst anyOf = typeof scope === \"string\" ? [scope] : scope;\n\t\t\tif (anyOf.some((required) => hasScope(tokenScopes, required))) return null;\n\n\t\t\treturn apiError(\n\t\t\t\t\"INSUFFICIENT_SCOPE\",\n\t\t\t\t`Token lacks required scope: ${anyOf.join(\" or \")}`,\n\t\t\t\t403,\n\t\t\t);\n\t\t}\n\t}\n\n\t// No rule matched — default to admin scope (fail-closed)\n\tif (hasScope(tokenScopes, \"admin\")) return null;\n\n\treturn apiError(\"INSUFFICIENT_SCOPE\", \"Token lacks required scope: admin\", 403);\n}\n"],"mappings":"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"}
@@ -1,10 +1,10 @@
1
1
  import "../../dialect-helpers-7_IqPdh9.mjs";
2
2
  import "../../base64-BQBZwXCx.mjs";
3
- import "../../types-C-Xp0CcN.mjs";
4
- import "../../errors-CjtE5aWF.mjs";
5
- import "../../errors-hskQ0C8G.mjs";
6
- import { t as apiError } from "../../error-DxgQdaZ_.mjs";
7
- import { a as readSiteWriteFence, o as recordSiteWrite } from "../../fence-vc3aHgRA.mjs";
3
+ import "../../types-D2NEXtgB.mjs";
4
+ import "../../errors-B4f4It-2.mjs";
5
+ import "../../errors-BOYNdIo3.mjs";
6
+ import { t as apiError } from "../../error-CVWeIOku.mjs";
7
+ import { a as readSiteWriteFence, o as recordSiteWrite } from "../../fence-C3MUitUN.mjs";
8
8
  import { defineMiddleware } from "astro:middleware";
9
9
 
10
10
  //#region src/astro/middleware/media-usage-write-fence.ts
@@ -1 +1 @@
1
- {"version":3,"file":"redirect.d.mts","names":[],"sources":["../../../src/astro/middleware/redirect.ts"],"mappings":";;;;;;AAuDA;;;;;;;;;;;;cAAa,SAAA,EAsHX,KAAA,CAtHoB,iBAAA"}
1
+ {"version":3,"file":"redirect.d.mts","names":[],"sources":["../../../src/astro/middleware/redirect.ts"],"mappings":";;;;;;AAoGA;;;;;;;;;;;;cAAa,SAAA,EAsGX,KAAA,CAtGoB,iBAAA"}
@@ -3,14 +3,15 @@ import "../../config-CvmjJcVw.mjs";
3
3
  import { t as after } from "../../after-PcEvMY_6.mjs";
4
4
  import "../../base64-BQBZwXCx.mjs";
5
5
  import "../../request-cache-C4CIo5ad.mjs";
6
- import "../../types-C-Xp0CcN.mjs";
6
+ import "../../types-D2NEXtgB.mjs";
7
7
  import "../../resolve-D-kqyKns.mjs";
8
8
  import { t as isSiteRelativeDestination } from "../../destination-r2zIAZ2S.mjs";
9
- import { t as RedirectRepository } from "../../redirect-B39kTQ_0.mjs";
10
- import { i as matchCachedPatterns, r as loadCachedRedirects } from "../../cache-x0z8t_m9.mjs";
11
- import { n as createRedirectSource } from "../../artifacts-D-O-qj9C.mjs";
12
- import { c as getDb } from "../../loader-CetY659y.mjs";
13
- import { n as isTerminalStatus } from "../../status-Dl85BK39.mjs";
9
+ import { t as RedirectRepository } from "../../redirect-DiS_3mA4.mjs";
10
+ import { i as matchCachedPatterns, r as loadCachedRedirects } from "../../cache-CEU9wo_h.mjs";
11
+ import { n as createRedirectSource } from "../../artifacts-htGyfCSt.mjs";
12
+ import { c as getDb } from "../../loader-CswroUbe.mjs";
13
+ import "../../json-recordset-BUjxhr77.mjs";
14
+ import { n as isTerminalStatus } from "../../status-BFNdxzKc.mjs";
14
15
  import { defineMiddleware } from "astro:middleware";
15
16
 
16
17
  //#region src/astro/middleware/redirect.ts
@@ -33,6 +34,39 @@ function recordHitInBackground(repo, id) {
33
34
  }
34
35
  });
35
36
  }
37
+ /** Exact rules first, with or without a trailing slash, then patterns in precedence order. */
38
+ function matchRedirect(cached, pathname) {
39
+ let exact = cached.exact.get(pathname);
40
+ if (!exact && pathname.length > 1) {
41
+ const alt = pathname.endsWith("/") ? pathname.slice(0, -1) : `${pathname}/`;
42
+ exact = cached.exact.get(alt);
43
+ }
44
+ if (exact) return {
45
+ redirect: exact,
46
+ destination: exact.destination
47
+ };
48
+ return matchCachedPatterns(cached.patterns, pathname);
49
+ }
50
+ /** The response for a matched rule, or null when its destination is not safe to send. */
51
+ function redirectResponse(context, repo, { redirect, destination }) {
52
+ if (isTerminalStatus(redirect.type)) {
53
+ recordHitInBackground(repo, redirect.id);
54
+ return new Response(null, { status: redirect.type });
55
+ }
56
+ if (!isSiteRelativeDestination(destination)) {
57
+ warnUnsafeDestination(redirect.id);
58
+ return null;
59
+ }
60
+ recordHitInBackground(repo, redirect.id);
61
+ const code = isRedirectCode(redirect.type) ? redirect.type : 301;
62
+ return context.redirect(destination, code);
63
+ }
64
+ /** Whether Astro's route cache will store the response: it does once a max age or a tag is set. */
65
+ function routeCacheStores(cache) {
66
+ if (!cache?.enabled) return false;
67
+ const { maxAge, tags } = cache.options;
68
+ return maxAge !== void 0 || (tags?.length ?? 0) > 0;
69
+ }
36
70
  const onRequest = defineMiddleware(async (context, next) => {
37
71
  const { pathname } = context.url;
38
72
  if (SKIP_PREFIXES.some((prefix) => pathname.startsWith(prefix))) return next();
@@ -45,43 +79,29 @@ const onRequest = defineMiddleware(async (context, next) => {
45
79
  }
46
80
  try {
47
81
  const repo = new RedirectRepository(db);
48
- const cached = await loadCachedRedirects(createRedirectSource(db));
49
- let exact = cached.exact.get(pathname);
50
- if (!exact && pathname.length > 1) {
51
- const alt = pathname.endsWith("/") ? pathname.slice(0, -1) : `${pathname}/`;
52
- exact = cached.exact.get(alt);
82
+ const source = createRedirectSource(db);
83
+ const routeCache = context.cache;
84
+ let cached = await loadCachedRedirects(source);
85
+ let match = matchRedirect(cached, pathname);
86
+ let verified = false;
87
+ if (match && routeCacheStores(routeCache)) {
88
+ cached = await loadCachedRedirects(source, { verify: true });
89
+ verified = true;
90
+ match = matchRedirect(cached, pathname);
53
91
  }
54
- if (exact) {
55
- if (isTerminalStatus(exact.type)) {
56
- recordHitInBackground(repo, exact.id);
57
- return new Response(null, { status: exact.type });
58
- }
59
- const dest = exact.destination;
60
- if (!isSiteRelativeDestination(dest)) {
61
- warnUnsafeDestination(exact.id);
62
- return next();
63
- }
64
- recordHitInBackground(repo, exact.id);
65
- const code = isRedirectCode(exact.type) ? exact.type : 301;
66
- return context.redirect(dest, code);
67
- }
68
- const patternMatch = matchCachedPatterns(cached.patterns, pathname);
69
- if (patternMatch) {
70
- const { redirect, destination } = patternMatch;
71
- if (isTerminalStatus(redirect.type)) {
72
- recordHitInBackground(repo, redirect.id);
73
- return new Response(null, { status: redirect.type });
74
- }
75
- if (!isSiteRelativeDestination(destination)) {
76
- warnUnsafeDestination(redirect.id);
77
- return next();
92
+ if (match) return redirectResponse(context, repo, match) ?? next();
93
+ const response = await next();
94
+ if (response.status === 404) routeCache?.set(false);
95
+ if (!verified && routeCacheStores(routeCache)) {
96
+ const current = await loadCachedRedirects(source, { verify: true }).catch(() => cached);
97
+ const late = current === cached ? null : matchRedirect(current, pathname);
98
+ const redirected = late && redirectResponse(context, repo, late);
99
+ if (redirected) {
100
+ routeCache?.set(false);
101
+ after(() => response.body?.pipeTo(new WritableStream()));
102
+ return redirected;
78
103
  }
79
- recordHitInBackground(repo, redirect.id);
80
- const code = isRedirectCode(redirect.type) ? redirect.type : 301;
81
- return context.redirect(destination, code);
82
104
  }
83
- const response = await next();
84
- if (response.status === 404) context.cache?.set(false);
85
105
  const location = response.headers.get("location");
86
106
  const missedByRedirect = isRedirectCode(response.status) && (location === "/404" || location === "/404/");
87
107
  if (response.status === 404 && pathname !== "/404" && pathname !== "/404/" || missedByRedirect) {
@@ -1 +1 @@
1
- {"version":3,"file":"redirect.mjs","names":[],"sources":["../../../src/astro/middleware/redirect.ts"],"sourcesContent":["/**\n * Redirect middleware\n *\n * Intercepts incoming requests and checks for matching redirect rules.\n * Runs after runtime init (needs db) but before setup/auth (should handle\n * ALL routes, including public ones, and should be fast).\n *\n * Skip paths:\n * - /_emdash/* (admin UI, API routes, auth endpoints)\n * - /_image (Astro image optimization)\n * - Static assets (files with extensions)\n *\n * 404 logging happens post-response: if next() returns 404 and the path\n * wasn't already matched by a redirect, log it.\n */\n\nimport type { APIContext } from \"astro\";\nimport { defineMiddleware } from \"astro:middleware\";\n\nimport { after } from \"../../after.js\";\nimport { RedirectRepository } from \"../../database/repositories/redirect.js\";\nimport { getDb } from \"../../loader.js\";\nimport { createRedirectSource } from \"../../redirects/artifacts.js\";\nimport { loadCachedRedirects, matchCachedPatterns } from \"../../redirects/cache.js\";\nimport { isSiteRelativeDestination } from \"../../redirects/destination.js\";\nimport { isTerminalStatus } from \"../../redirects/status.js\";\n\n/** Paths that should never be intercepted by redirects */\nconst SKIP_PREFIXES = [\"/_emdash\", \"/_image\"];\n\n/** Static asset extensions -- don't redirect file requests */\nconst ASSET_EXTENSION = /\\.\\w{1,10}$/;\n\ntype RedirectCode = 301 | 302 | 303 | 307 | 308;\n\nfunction isRedirectCode(code: number): code is RedirectCode {\n\treturn code === 301 || code === 302 || code === 303 || code === 307 || code === 308;\n}\n\nfunction warnUnsafeDestination(id: string): void {\n\tconsole.warn(\n\t\t`[emdash:redirects] Skipping redirect ${id}: destination is not a site-relative path`,\n\t);\n}\n\nfunction recordHitInBackground(repo: RedirectRepository, id: string): void {\n\tafter(async () => {\n\t\ttry {\n\t\t\tawait repo.recordHit(id);\n\t\t} catch (error) {\n\t\t\tconsole.error(\"[emdash:redirects] failed to record redirect hit:\", error);\n\t\t}\n\t});\n}\n\nexport const onRequest = defineMiddleware(async (context, next) => {\n\tconst { pathname } = context.url;\n\n\t// Skip internal paths and static assets\n\tif (SKIP_PREFIXES.some((prefix) => pathname.startsWith(prefix))) {\n\t\treturn next();\n\t}\n\tif (ASSET_EXTENSION.test(pathname)) {\n\t\treturn next();\n\t}\n\n\t// Public visitors hit the runtime's anonymous fast path, which intentionally\n\t// omits `db` from `locals.emdash` to keep the public render boundary minimal\n\t// (issue #808). Fall back to `getDb()`, which transparently returns the\n\t// per-request scoped db (set in ALS by the runtime middleware) or the\n\t// singleton — same path the loader and template helpers use.\n\tlet db = context.locals.emdash?.db;\n\tif (!db) {\n\t\ttry {\n\t\t\tdb = await getDb();\n\t\t} catch {\n\t\t\treturn next();\n\t\t}\n\t}\n\n\ttry {\n\t\tconst repo = new RedirectRepository(db);\n\n\t\t// One query loads the published rules into the cache; warm requests\n\t\t// issue zero queries, and an expired cache checks the published version\n\t\t// in the background. Empty-redirect sites cache an empty Map + array.\n\t\tconst cached = await loadCachedRedirects(createRedirectSource(db));\n\n\t\t// 1. Exact match (O(1) Map lookup)\n\t\tlet exact = cached.exact.get(pathname);\n\t\tif (!exact && pathname.length > 1) {\n\t\t\tconst alt = pathname.endsWith(\"/\") ? pathname.slice(0, -1) : `${pathname}/`;\n\t\t\texact = cached.exact.get(alt);\n\t\t}\n\t\tif (exact) {\n\t\t\t// Terminal statuses (410 Gone / 451): serve the status directly,\n\t\t\t// with no Location header.\n\t\t\tif (isTerminalStatus(exact.type)) {\n\t\t\t\trecordHitInBackground(repo, exact.id);\n\t\t\t\treturn new Response(null, { status: exact.type });\n\t\t\t}\n\t\t\tconst dest = exact.destination;\n\t\t\tif (!isSiteRelativeDestination(dest)) {\n\t\t\t\twarnUnsafeDestination(exact.id);\n\t\t\t\treturn next();\n\t\t\t}\n\t\t\trecordHitInBackground(repo, exact.id);\n\t\t\tconst code = isRedirectCode(exact.type) ? exact.type : 301;\n\t\t\treturn context.redirect(dest, code);\n\t\t}\n\n\t\t// 2. Pattern match (compile once, match every request)\n\t\tconst patternMatch = matchCachedPatterns(cached.patterns, pathname);\n\t\tif (patternMatch) {\n\t\t\tconst { redirect, destination } = patternMatch;\n\t\t\t// Terminal statuses (410 Gone / 451): serve the status directly.\n\t\t\tif (isTerminalStatus(redirect.type)) {\n\t\t\t\trecordHitInBackground(repo, redirect.id);\n\t\t\t\treturn new Response(null, { status: redirect.type });\n\t\t\t}\n\t\t\tif (!isSiteRelativeDestination(destination)) {\n\t\t\t\twarnUnsafeDestination(redirect.id);\n\t\t\t\treturn next();\n\t\t\t}\n\t\t\trecordHitInBackground(repo, redirect.id);\n\t\t\tconst code = isRedirectCode(redirect.type) ? redirect.type : 301;\n\t\t\treturn context.redirect(destination, code);\n\t\t}\n\n\t\t// No redirect matched -- proceed and check for 404\n\t\tconst response = await next();\n\n\t\t// Keep a 404 out of the route cache: publishing the missing entry later\n\t\t// purges content tags, not the missed path, so a cached 404 would outlive\n\t\t// the fix. Astro has no cache handle for URLs that match no route, but a\n\t\t// page answering a content miss with Astro.rewrite(\"/404\") has one.\n\t\tif (response.status === 404) {\n\t\t\tconst routeCache: APIContext[\"cache\"] | undefined = context.cache;\n\t\t\trouteCache?.set(false);\n\t\t}\n\n\t\t// Log misses under the path the visitor requested.\n\t\t// Two shapes count as a miss: a 404 response (an unmatched route, or a\n\t\t// page answering a content miss with Astro.rewrite(\"/404\")), and a\n\t\t// matched route answering a content miss with a redirect to /404 —\n\t\t// there the missed path exists only on this first pass, before the\n\t\t// browser follows the redirect. The error page itself is never logged: /404\n\t\t// answers 404 by design and carries no path information.\n\t\tconst location = response.headers.get(\"location\");\n\t\tconst missedByRedirect =\n\t\t\tisRedirectCode(response.status) && (location === \"/404\" || location === \"/404/\");\n\t\tconst missedDirectly = response.status === 404 && pathname !== \"/404\" && pathname !== \"/404/\";\n\t\tif (missedDirectly || missedByRedirect) {\n\t\t\tconst referrer = context.request.headers.get(\"referer\") ?? null;\n\t\t\tconst userAgent = context.request.headers.get(\"user-agent\") ?? null;\n\t\t\tafter(async () => {\n\t\t\t\ttry {\n\t\t\t\t\tawait repo.log404({\n\t\t\t\t\t\tpath: pathname,\n\t\t\t\t\t\treferrer,\n\t\t\t\t\t\tuserAgent,\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(\"[emdash:redirects] failed to log 404:\", error);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn response;\n\t} catch {\n\t\t// If the redirects table doesn't exist yet (pre-migration), skip silently\n\t\treturn next();\n\t}\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"redirect.mjs","names":[],"sources":["../../../src/astro/middleware/redirect.ts"],"sourcesContent":["/**\n * Redirect middleware\n *\n * Intercepts incoming requests and checks for matching redirect rules.\n * Runs after runtime init (needs db) but before setup/auth (should handle\n * ALL routes, including public ones, and should be fast).\n *\n * Skip paths:\n * - /_emdash/* (admin UI, API routes, auth endpoints)\n * - /_image (Astro image optimization)\n * - Static assets (files with extensions)\n *\n * 404 logging happens post-response: if next() returns 404 and the path\n * wasn't already matched by a redirect, log it.\n */\n\nimport type { APIContext } from \"astro\";\nimport { defineMiddleware } from \"astro:middleware\";\n\nimport { after } from \"../../after.js\";\nimport { RedirectRepository } from \"../../database/repositories/redirect.js\";\nimport { getDb } from \"../../loader.js\";\nimport { createRedirectSource } from \"../../redirects/artifacts.js\";\nimport type { CachedRedirects, RedirectRule } from \"../../redirects/cache.js\";\nimport { loadCachedRedirects, matchCachedPatterns } from \"../../redirects/cache.js\";\nimport { isSiteRelativeDestination } from \"../../redirects/destination.js\";\nimport { isTerminalStatus } from \"../../redirects/status.js\";\n\n/** Paths that should never be intercepted by redirects */\nconst SKIP_PREFIXES = [\"/_emdash\", \"/_image\"];\n\n/** Static asset extensions -- don't redirect file requests */\nconst ASSET_EXTENSION = /\\.\\w{1,10}$/;\n\ntype RedirectCode = 301 | 302 | 303 | 307 | 308;\n\nfunction isRedirectCode(code: number): code is RedirectCode {\n\treturn code === 301 || code === 302 || code === 303 || code === 307 || code === 308;\n}\n\nfunction warnUnsafeDestination(id: string): void {\n\tconsole.warn(\n\t\t`[emdash:redirects] Skipping redirect ${id}: destination is not a site-relative path`,\n\t);\n}\n\nfunction recordHitInBackground(repo: RedirectRepository, id: string): void {\n\tafter(async () => {\n\t\ttry {\n\t\t\tawait repo.recordHit(id);\n\t\t} catch (error) {\n\t\t\tconsole.error(\"[emdash:redirects] failed to record redirect hit:\", error);\n\t\t}\n\t});\n}\n\ninterface RedirectMatch {\n\tredirect: RedirectRule;\n\tdestination: string;\n}\n\n/** Exact rules first, with or without a trailing slash, then patterns in precedence order. */\nfunction matchRedirect(cached: CachedRedirects, pathname: string): RedirectMatch | null {\n\tlet exact = cached.exact.get(pathname);\n\tif (!exact && pathname.length > 1) {\n\t\tconst alt = pathname.endsWith(\"/\") ? pathname.slice(0, -1) : `${pathname}/`;\n\t\texact = cached.exact.get(alt);\n\t}\n\tif (exact) return { redirect: exact, destination: exact.destination };\n\treturn matchCachedPatterns(cached.patterns, pathname);\n}\n\n/** The response for a matched rule, or null when its destination is not safe to send. */\nfunction redirectResponse(\n\tcontext: APIContext,\n\trepo: RedirectRepository,\n\t{ redirect, destination }: RedirectMatch,\n): Response | null {\n\t// Terminal statuses (410 Gone / 451): serve the status directly,\n\t// with no Location header.\n\tif (isTerminalStatus(redirect.type)) {\n\t\trecordHitInBackground(repo, redirect.id);\n\t\treturn new Response(null, { status: redirect.type });\n\t}\n\tif (!isSiteRelativeDestination(destination)) {\n\t\twarnUnsafeDestination(redirect.id);\n\t\treturn null;\n\t}\n\trecordHitInBackground(repo, redirect.id);\n\tconst code = isRedirectCode(redirect.type) ? redirect.type : 301;\n\treturn context.redirect(destination, code);\n}\n\n/** Whether Astro's route cache will store the response: it does once a max age or a tag is set. */\nfunction routeCacheStores(cache: APIContext[\"cache\"] | undefined): boolean {\n\tif (!cache?.enabled) return false;\n\tconst { maxAge, tags } = cache.options;\n\treturn maxAge !== undefined || (tags?.length ?? 0) > 0;\n}\n\nexport const onRequest = defineMiddleware(async (context, next) => {\n\tconst { pathname } = context.url;\n\n\t// Skip internal paths and static assets\n\tif (SKIP_PREFIXES.some((prefix) => pathname.startsWith(prefix))) {\n\t\treturn next();\n\t}\n\tif (ASSET_EXTENSION.test(pathname)) {\n\t\treturn next();\n\t}\n\n\t// Public visitors hit the runtime's anonymous fast path, which intentionally\n\t// omits `db` from `locals.emdash` to keep the public render boundary minimal\n\t// (issue #808). Fall back to `getDb()`, which transparently returns the\n\t// per-request scoped db (set in ALS by the runtime middleware) or the\n\t// singleton — same path the loader and template helpers use.\n\tlet db = context.locals.emdash?.db;\n\tif (!db) {\n\t\ttry {\n\t\t\tdb = await getDb();\n\t\t} catch {\n\t\t\treturn next();\n\t\t}\n\t}\n\n\ttry {\n\t\tconst repo = new RedirectRepository(db);\n\t\tconst source = createRedirectSource(db);\n\t\tconst routeCache: APIContext[\"cache\"] | undefined = context.cache;\n\n\t\t// One query loads the published rules into the cache; warm requests\n\t\t// issue zero queries, and an expired cache checks the published version\n\t\t// in the background. Empty-redirect sites cache an empty Map + array.\n\t\t// A response the route cache stores is served to every visitor until it\n\t\t// is purged, so before one is returned the rules are verified current.\n\t\tlet cached = await loadCachedRedirects(source);\n\t\tlet match = matchRedirect(cached, pathname);\n\t\tlet verified = false;\n\t\tif (match && routeCacheStores(routeCache)) {\n\t\t\tcached = await loadCachedRedirects(source, { verify: true });\n\t\t\tverified = true;\n\t\t\tmatch = matchRedirect(cached, pathname);\n\t\t}\n\t\tif (match) return redirectResponse(context, repo, match) ?? next();\n\n\t\t// No redirect matched -- proceed and check for 404\n\t\tconst response = await next();\n\n\t\t// Keep a 404 out of the route cache: publishing the missing entry later\n\t\t// purges content tags, not the missed path, so a cached 404 would outlive\n\t\t// the fix. Astro has no cache handle for URLs that match no route, but a\n\t\t// page answering a content miss with Astro.rewrite(\"/404\") has one.\n\t\tif (response.status === 404) {\n\t\t\trouteCache?.set(false);\n\t\t}\n\n\t\tif (!verified && routeCacheStores(routeCache)) {\n\t\t\tconst current = await loadCachedRedirects(source, { verify: true }).catch(() => cached);\n\t\t\tconst late = current === cached ? null : matchRedirect(current, pathname);\n\t\t\tconst redirected = late && redirectResponse(context, repo, late);\n\t\t\tif (redirected) {\n\t\t\t\trouteCache?.set(false);\n\t\t\t\t// Finish the discarded render instead of cancelling it: a render cut off\n\t\t\t\t// with its request never settles an isolate-wide fetch it started, and\n\t\t\t\t// every later render awaiting that fetch hangs.\n\t\t\t\tafter(() => response.body?.pipeTo(new WritableStream()));\n\t\t\t\treturn redirected;\n\t\t\t}\n\t\t}\n\n\t\t// Log misses under the path the visitor requested.\n\t\t// Two shapes count as a miss: a 404 response (an unmatched route, or a\n\t\t// page answering a content miss with Astro.rewrite(\"/404\")), and a\n\t\t// matched route answering a content miss with a redirect to /404 —\n\t\t// there the missed path exists only on this first pass, before the\n\t\t// browser follows the redirect. The error page itself is never logged: /404\n\t\t// answers 404 by design and carries no path information.\n\t\tconst location = response.headers.get(\"location\");\n\t\tconst missedByRedirect =\n\t\t\tisRedirectCode(response.status) && (location === \"/404\" || location === \"/404/\");\n\t\tconst missedDirectly = response.status === 404 && pathname !== \"/404\" && pathname !== \"/404/\";\n\t\tif (missedDirectly || missedByRedirect) {\n\t\t\tconst referrer = context.request.headers.get(\"referer\") ?? null;\n\t\t\tconst userAgent = context.request.headers.get(\"user-agent\") ?? null;\n\t\t\tafter(async () => {\n\t\t\t\ttry {\n\t\t\t\t\tawait repo.log404({\n\t\t\t\t\t\tpath: pathname,\n\t\t\t\t\t\treferrer,\n\t\t\t\t\t\tuserAgent,\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(\"[emdash:redirects] failed to log 404:\", error);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn response;\n\t} catch {\n\t\t// If the redirects table doesn't exist yet (pre-migration), skip silently\n\t\treturn next();\n\t}\n});\n"],"mappings":"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"}