emdash 0.35.0 → 0.37.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 (971) hide show
  1. package/dist/activation-K0kGBWuJ.mjs +382 -0
  2. package/dist/activation-K0kGBWuJ.mjs.map +1 -0
  3. package/dist/{adapters-Bb1vG41D.d.mts → adapters-BDQwg236.d.mts} +6 -4
  4. package/dist/{adapters-Bb1vG41D.d.mts.map → adapters-BDQwg236.d.mts.map} +1 -1
  5. package/dist/{allowed-origins-DW7sYyqg.mjs → allowed-origins-BGglilcs.mjs} +2 -2
  6. package/dist/{allowed-origins-DW7sYyqg.mjs.map → allowed-origins-BGglilcs.mjs.map} +1 -1
  7. package/dist/api/route-utils.d.mts +3 -3
  8. package/dist/api/route-utils.mjs +23 -21
  9. package/dist/api/route-utils.mjs.map +1 -1
  10. package/dist/api/schemas/index.d.mts +2 -2
  11. package/dist/api/schemas/index.mjs +5 -5
  12. package/dist/api-Dz6rgoa3.mjs +10040 -0
  13. package/dist/api-Dz6rgoa3.mjs.map +1 -0
  14. package/dist/{api-tokens-KO24G1Fd.mjs → api-tokens-BSsQACNe.mjs} +2 -2
  15. package/dist/{api-tokens-KO24G1Fd.mjs.map → api-tokens-BSsQACNe.mjs.map} +1 -1
  16. package/dist/{apply-kUDt80-G.mjs → apply-B4SIOxR1.mjs} +34 -35
  17. package/dist/{apply-kUDt80-G.mjs.map → apply-B4SIOxR1.mjs.map} +1 -1
  18. package/dist/astro/image-endpoint.mjs +2 -2
  19. package/dist/astro/image-endpoint.mjs.map +1 -1
  20. package/dist/astro/index.d.mts +12 -12
  21. package/dist/astro/index.d.mts.map +1 -1
  22. package/dist/astro/index.mjs +128 -44
  23. package/dist/astro/index.mjs.map +1 -1
  24. package/dist/astro/middleware/auth.d.mts +10 -10
  25. package/dist/astro/middleware/auth.d.mts.map +1 -1
  26. package/dist/astro/middleware/auth.mjs +10 -7
  27. package/dist/astro/middleware/auth.mjs.map +1 -1
  28. package/dist/astro/middleware/media-usage-write-fence.mjs +2 -2
  29. package/dist/astro/middleware/redirect.mjs +4 -4
  30. package/dist/astro/middleware/request-context.mjs +3 -3
  31. package/dist/astro/middleware/setup.mjs +1 -1
  32. package/dist/astro/middleware.d.mts +11 -12
  33. package/dist/astro/middleware.d.mts.map +1 -1
  34. package/dist/astro/middleware.mjs +237 -1412
  35. package/dist/astro/middleware.mjs.map +1 -1
  36. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +6 -6
  37. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +6 -6
  38. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +3 -3
  39. package/dist/astro/routes/api/admin/api-tokens/index.d.mts.map +1 -1
  40. package/dist/astro/routes/api/admin/api-tokens/index.mjs +5 -5
  41. package/dist/astro/routes/api/admin/api-tokens/index.mjs.map +1 -1
  42. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +4 -4
  43. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +9 -9
  44. package/dist/astro/routes/api/admin/byline-fields/index.mjs +9 -9
  45. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +9 -9
  46. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +16 -16
  47. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +16 -16
  48. package/dist/astro/routes/api/admin/bylines/index.mjs +16 -16
  49. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +13 -13
  50. package/dist/astro/routes/api/admin/comments/_id_.mjs +5 -5
  51. package/dist/astro/routes/api/admin/comments/bulk.mjs +10 -10
  52. package/dist/astro/routes/api/admin/comments/counts.mjs +5 -5
  53. package/dist/astro/routes/api/admin/comments/index.mjs +10 -10
  54. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +4 -4
  55. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
  56. package/dist/astro/routes/api/admin/media-usage/activation.d.mts +9 -0
  57. package/dist/astro/routes/api/admin/media-usage/activation.d.mts.map +1 -0
  58. package/dist/astro/routes/api/admin/media-usage/activation.mjs +46 -0
  59. package/dist/astro/routes/api/admin/media-usage/activation.mjs.map +1 -0
  60. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +14 -13
  61. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs.map +1 -1
  62. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +14 -13
  63. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs.map +1 -1
  64. package/dist/astro/routes/api/admin/media-usage/progress.d.mts +9 -0
  65. package/dist/astro/routes/api/admin/media-usage/progress.d.mts.map +1 -0
  66. package/dist/astro/routes/api/admin/media-usage/progress.mjs +44 -0
  67. package/dist/astro/routes/api/admin/media-usage/progress.mjs.map +1 -0
  68. package/dist/astro/routes/api/admin/media-usage/repair.mjs +16 -11
  69. package/dist/astro/routes/api/admin/media-usage/repair.mjs.map +1 -1
  70. package/dist/astro/routes/api/admin/media-usage/work/index.mjs +14 -13
  71. package/dist/astro/routes/api/admin/media-usage/work/index.mjs.map +1 -1
  72. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +14 -13
  73. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs.map +1 -1
  74. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +4 -4
  75. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs.map +1 -1
  76. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +4 -4
  77. package/dist/astro/routes/api/admin/oauth-clients/index.mjs.map +1 -1
  78. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +55 -49
  79. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  80. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +55 -49
  81. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  82. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +53 -47
  83. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  84. package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +4 -4
  85. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +53 -47
  86. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
  87. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +54 -48
  88. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  89. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +54 -48
  90. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  91. package/dist/astro/routes/api/admin/plugins/index.mjs +53 -47
  92. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  93. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +2 -2
  94. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +53 -47
  95. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  96. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +54 -48
  97. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  98. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +53 -47
  99. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  100. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +54 -48
  101. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  102. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.d.mts.map +1 -1
  103. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +60 -50
  104. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  105. package/dist/astro/routes/api/admin/plugins/registry/artifact.d.mts.map +1 -1
  106. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +179 -139
  107. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  108. package/dist/astro/routes/api/admin/plugins/registry/install.d.mts.map +1 -1
  109. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +61 -51
  110. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  111. package/dist/astro/routes/api/admin/plugins/registry/verify.d.mts +8 -0
  112. package/dist/astro/routes/api/admin/plugins/registry/verify.d.mts.map +1 -0
  113. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs +93 -0
  114. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs.map +1 -0
  115. package/dist/astro/routes/api/admin/plugins/updates.mjs +53 -47
  116. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  117. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +53 -47
  118. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  119. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +2 -2
  120. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +53 -47
  121. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  122. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +2 -2
  123. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +1 -1
  124. package/dist/astro/routes/api/admin/users/_id_/index.mjs +7 -7
  125. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +3 -3
  126. package/dist/astro/routes/api/admin/users/index.mjs +6 -6
  127. package/dist/astro/routes/api/auth/dev-bypass.mjs +3 -3
  128. package/dist/astro/routes/api/auth/invite/accept.mjs +1 -1
  129. package/dist/astro/routes/api/auth/invite/complete.mjs +11 -11
  130. package/dist/astro/routes/api/auth/invite/index.mjs +8 -8
  131. package/dist/astro/routes/api/auth/invite/register-options.mjs +10 -10
  132. package/dist/astro/routes/api/auth/logout.mjs +2 -2
  133. package/dist/astro/routes/api/auth/magic-link/send.mjs +10 -10
  134. package/dist/astro/routes/api/auth/magic-link/verify.mjs +2 -2
  135. package/dist/astro/routes/api/auth/me.d.mts.map +1 -1
  136. package/dist/astro/routes/api/auth/me.mjs +19 -9
  137. package/dist/astro/routes/api/auth/me.mjs.map +1 -1
  138. package/dist/astro/routes/api/auth/mode.mjs +2 -2
  139. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
  140. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  141. package/dist/astro/routes/api/auth/passkey/_id_.mjs +6 -6
  142. package/dist/astro/routes/api/auth/passkey/index.mjs +1 -1
  143. package/dist/astro/routes/api/auth/passkey/options.mjs +12 -12
  144. package/dist/astro/routes/api/auth/passkey/register/options.mjs +10 -10
  145. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +11 -11
  146. package/dist/astro/routes/api/auth/passkey/verify.mjs +11 -11
  147. package/dist/astro/routes/api/auth/signup/complete.mjs +11 -11
  148. package/dist/astro/routes/api/auth/signup/request.mjs +10 -10
  149. package/dist/astro/routes/api/auth/signup/verify.mjs +1 -1
  150. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +14 -14
  151. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +13 -13
  152. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +2 -2
  153. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.d.mts.map +1 -1
  154. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +14 -5
  155. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs.map +1 -1
  156. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
  157. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +2 -2
  158. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +11 -11
  159. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +13 -10
  160. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
  161. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +17 -15
  162. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
  163. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +17 -15
  164. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
  165. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
  166. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +2 -2
  167. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +8 -8
  168. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +14 -14
  169. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +2 -2
  170. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.d.mts.map +1 -1
  171. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +14 -5
  172. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs.map +1 -1
  173. package/dist/astro/routes/api/content/_collection_/_id_.mjs +8 -8
  174. package/dist/astro/routes/api/content/_collection_/authors.mjs +2 -2
  175. package/dist/astro/routes/api/content/_collection_/index.mjs +8 -8
  176. package/dist/astro/routes/api/content/_collection_/trash.mjs +7 -7
  177. package/dist/astro/routes/api/dashboard.mjs +8 -8
  178. package/dist/astro/routes/api/dev/emails.mjs +2 -2
  179. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  180. package/dist/astro/routes/api/import/probe.mjs +17 -17
  181. package/dist/astro/routes/api/import/wordpress/analyze.mjs +2 -2
  182. package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -11
  183. package/dist/astro/routes/api/import/wordpress/execute.mjs +13 -13
  184. package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -10
  185. package/dist/astro/routes/api/import/wordpress/media.mjs +11 -11
  186. package/dist/astro/routes/api/import/wordpress/prepare.mjs +9 -9
  187. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +11 -11
  188. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +12 -10
  189. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
  190. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  191. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +17 -17
  192. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +11 -11
  193. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +27 -27
  194. package/dist/astro/routes/api/manifest.mjs +4 -4
  195. package/dist/astro/routes/api/manifest.mjs.map +1 -1
  196. package/dist/astro/routes/api/mcp.mjs +188 -65
  197. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  198. package/dist/astro/routes/api/media/_id_/confirm.mjs +11 -11
  199. package/dist/astro/routes/api/media/_id_/replace.d.mts +8 -0
  200. package/dist/astro/routes/api/media/_id_/replace.d.mts.map +1 -0
  201. package/dist/astro/routes/api/media/_id_/replace.mjs +91 -0
  202. package/dist/astro/routes/api/media/_id_/replace.mjs.map +1 -0
  203. package/dist/astro/routes/api/media/_id_/upload.mjs +6 -6
  204. package/dist/astro/routes/api/media/_id_/usage.mjs +18 -13
  205. package/dist/astro/routes/api/media/_id_/usage.mjs.map +1 -1
  206. package/dist/astro/routes/api/media/_id_.d.mts.map +1 -1
  207. package/dist/astro/routes/api/media/_id_.mjs +21 -13
  208. package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
  209. package/dist/astro/routes/api/media/file/_...key_.d.mts.map +1 -1
  210. package/dist/astro/routes/api/media/file/_...key_.mjs +3 -2
  211. package/dist/astro/routes/api/media/file/_...key_.mjs.map +1 -1
  212. package/dist/astro/routes/api/media/folders/_id_.d.mts +10 -0
  213. package/dist/astro/routes/api/media/folders/_id_.d.mts.map +1 -0
  214. package/dist/astro/routes/api/media/folders/_id_.mjs +52 -0
  215. package/dist/astro/routes/api/media/folders/_id_.mjs.map +1 -0
  216. package/dist/astro/routes/api/media/folders/index.d.mts +9 -0
  217. package/dist/astro/routes/api/media/folders/index.d.mts.map +1 -0
  218. package/dist/astro/routes/api/media/folders/index.mjs +41 -0
  219. package/dist/astro/routes/api/media/folders/index.mjs.map +1 -0
  220. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +2 -2
  221. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +2 -2
  222. package/dist/astro/routes/api/media/providers/index.mjs +2 -2
  223. package/dist/astro/routes/api/media/upload-url.mjs +16 -14
  224. package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
  225. package/dist/astro/routes/api/media.d.mts.map +1 -1
  226. package/dist/astro/routes/api/media.mjs +59 -27
  227. package/dist/astro/routes/api/media.mjs.map +1 -1
  228. package/dist/astro/routes/api/menus/_name_/items/_id_.d.mts.map +1 -1
  229. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +20 -13
  230. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
  231. package/dist/astro/routes/api/menus/_name_/items.d.mts.map +1 -1
  232. package/dist/astro/routes/api/menus/_name_/items.mjs +15 -11
  233. package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
  234. package/dist/astro/routes/api/menus/_name_/reorder.d.mts.map +1 -1
  235. package/dist/astro/routes/api/menus/_name_/reorder.mjs +15 -11
  236. package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
  237. package/dist/astro/routes/api/menus/_name_/translations.d.mts.map +1 -1
  238. package/dist/astro/routes/api/menus/_name_/translations.mjs +16 -12
  239. package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
  240. package/dist/astro/routes/api/menus/_name_.d.mts.map +1 -1
  241. package/dist/astro/routes/api/menus/_name_.mjs +21 -14
  242. package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
  243. package/dist/astro/routes/api/menus/index.d.mts.map +1 -1
  244. package/dist/astro/routes/api/menus/index.mjs +15 -11
  245. package/dist/astro/routes/api/menus/index.mjs.map +1 -1
  246. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  247. package/dist/astro/routes/api/oauth/device/authorize.mjs +5 -5
  248. package/dist/astro/routes/api/oauth/device/code.mjs +8 -8
  249. package/dist/astro/routes/api/oauth/device/token.mjs +7 -7
  250. package/dist/astro/routes/api/oauth/register.mjs +2 -2
  251. package/dist/astro/routes/api/oauth/token/refresh.mjs +5 -5
  252. package/dist/astro/routes/api/oauth/token/revoke.mjs +5 -5
  253. package/dist/astro/routes/api/oauth/token.mjs +5 -5
  254. package/dist/astro/routes/api/openapi.json.mjs +253 -40
  255. package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
  256. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +4 -4
  257. package/dist/astro/routes/api/redirects/404s/index.mjs +10 -10
  258. package/dist/astro/routes/api/redirects/404s/summary.mjs +10 -10
  259. package/dist/astro/routes/api/redirects/_id_.mjs +11 -11
  260. package/dist/astro/routes/api/redirects/index.mjs +11 -11
  261. package/dist/astro/routes/api/relations/_id_/index.mjs +17 -15
  262. package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
  263. package/dist/astro/routes/api/relations/_id_/translations.mjs +12 -10
  264. package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -1
  265. package/dist/astro/routes/api/relations/index.mjs +17 -15
  266. package/dist/astro/routes/api/relations/index.mjs.map +1 -1
  267. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +2 -2
  268. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
  269. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +53 -47
  270. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  271. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +53 -47
  272. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  273. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +53 -47
  274. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  275. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +53 -47
  276. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  277. package/dist/astro/routes/api/schema/collections/index.mjs +53 -47
  278. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  279. package/dist/astro/routes/api/schema/collections/reorder.mjs +53 -47
  280. package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
  281. package/dist/astro/routes/api/schema/index.mjs +10 -8
  282. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  283. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +53 -47
  284. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  285. package/dist/astro/routes/api/schema/orphans/index.mjs +53 -47
  286. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  287. package/dist/astro/routes/api/search/enable.mjs +10 -10
  288. package/dist/astro/routes/api/search/index.mjs +9 -9
  289. package/dist/astro/routes/api/search/rebuild.mjs +10 -10
  290. package/dist/astro/routes/api/search/stats.mjs +5 -5
  291. package/dist/astro/routes/api/search/suggest.mjs +9 -9
  292. package/dist/astro/routes/api/sections/_slug_.mjs +9 -9
  293. package/dist/astro/routes/api/sections/index.mjs +9 -9
  294. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +6 -6
  295. package/dist/astro/routes/api/settings/backups/archives/index.mjs +5 -5
  296. package/dist/astro/routes/api/settings/backups/export.mjs +6 -6
  297. package/dist/astro/routes/api/settings/backups/index.mjs +7 -7
  298. package/dist/astro/routes/api/settings/email.mjs +5 -5
  299. package/dist/astro/routes/api/settings/email.mjs.map +1 -1
  300. package/dist/astro/routes/api/settings.d.mts.map +1 -1
  301. package/dist/astro/routes/api/settings.mjs +20 -16
  302. package/dist/astro/routes/api/settings.mjs.map +1 -1
  303. package/dist/astro/routes/api/setup/admin-verify.mjs +12 -12
  304. package/dist/astro/routes/api/setup/admin.mjs +11 -11
  305. package/dist/astro/routes/api/setup/dev-bypass.d.mts.map +1 -1
  306. package/dist/astro/routes/api/setup/dev-bypass.mjs +35 -28
  307. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  308. package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
  309. package/dist/astro/routes/api/setup/index.mjs +32 -30
  310. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  311. package/dist/astro/routes/api/setup/status.mjs +3 -3
  312. package/dist/astro/routes/api/snapshot.mjs +7 -7
  313. package/dist/astro/routes/api/taxonomies/_name_/reorder.d.mts.map +1 -1
  314. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +20 -16
  315. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs.map +1 -1
  316. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.d.mts.map +1 -1
  317. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +21 -17
  318. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
  319. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.d.mts.map +1 -1
  320. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +25 -18
  321. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
  322. package/dist/astro/routes/api/taxonomies/_name_/terms/index.d.mts.map +1 -1
  323. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +20 -16
  324. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
  325. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +14 -14
  326. package/dist/astro/routes/api/taxonomies/_name_.d.mts.map +1 -1
  327. package/dist/astro/routes/api/taxonomies/_name_.mjs +26 -19
  328. package/dist/astro/routes/api/taxonomies/_name_.mjs.map +1 -1
  329. package/dist/astro/routes/api/taxonomies/index.d.mts.map +1 -1
  330. package/dist/astro/routes/api/taxonomies/index.mjs +20 -16
  331. package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
  332. package/dist/astro/routes/api/themes/preview.mjs +5 -5
  333. package/dist/astro/routes/api/typegen.mjs +4 -4
  334. package/dist/astro/routes/api/well-known/auth.mjs +2 -2
  335. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  336. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  337. package/dist/astro/routes/api/widget-areas/_name_/reorder.d.mts.map +1 -1
  338. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +10 -8
  339. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs.map +1 -1
  340. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.d.mts.map +1 -1
  341. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +17 -13
  342. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs.map +1 -1
  343. package/dist/astro/routes/api/widget-areas/_name_/widgets.d.mts.map +1 -1
  344. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +15 -12
  345. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs.map +1 -1
  346. package/dist/astro/routes/api/widget-areas/_name_.d.mts.map +1 -1
  347. package/dist/astro/routes/api/widget-areas/_name_.mjs +8 -6
  348. package/dist/astro/routes/api/widget-areas/_name_.mjs.map +1 -1
  349. package/dist/astro/routes/api/widget-areas/index.d.mts.map +1 -1
  350. package/dist/astro/routes/api/widget-areas/index.mjs +15 -12
  351. package/dist/astro/routes/api/widget-areas/index.mjs.map +1 -1
  352. package/dist/astro/routes/api/widget-components.mjs +2 -2
  353. package/dist/astro/routes/robots.txt.mjs +7 -7
  354. package/dist/astro/routes/sitemap-_collection_.xml.mjs +10 -10
  355. package/dist/astro/routes/sitemap.xml.mjs +8 -8
  356. package/dist/astro/types.d.mts +37 -17
  357. package/dist/astro/types.d.mts.map +1 -1
  358. package/dist/auth/providers/github.d.mts +1 -1
  359. package/dist/auth/providers/google.d.mts +1 -1
  360. package/dist/{authorize-DUElxgOQ.mjs → authorize-Bkf_UHhD.mjs} +2 -2
  361. package/dist/{authorize-DUElxgOQ.mjs.map → authorize-Bkf_UHhD.mjs.map} +1 -1
  362. package/dist/{backup-DWYpJlLj.mjs → backup-rwVAl9NI.mjs} +5 -5
  363. package/dist/{backup-DWYpJlLj.mjs.map → backup-rwVAl9NI.mjs.map} +1 -1
  364. package/dist/{bundle-vn56sLos.mjs → bundle-C8S2Zl6U.mjs} +4 -4
  365. package/dist/{bundle-vn56sLos.mjs.map → bundle-C8S2Zl6U.mjs.map} +1 -1
  366. package/dist/{byline-yjvWq4ip.mjs → byline-DuhF7NWl.mjs} +27 -14
  367. package/dist/byline-DuhF7NWl.mjs.map +1 -0
  368. package/dist/{byline-fields-txaLGoME.mjs → byline-fields-BovY4KYM.mjs} +2 -2
  369. package/dist/{byline-fields-txaLGoME.mjs.map → byline-fields-BovY4KYM.mjs.map} +1 -1
  370. package/dist/{byline-registry-DDun8sxh.mjs → byline-registry-Bpu9-MVs.mjs} +2 -2
  371. package/dist/{byline-registry-DDun8sxh.mjs.map → byline-registry-Bpu9-MVs.mjs.map} +1 -1
  372. package/dist/{bylines-DjXS5p0P.mjs → bylines-CJ5nd6Lw.mjs} +7 -7
  373. package/dist/{bylines-DjXS5p0P.mjs.map → bylines-CJ5nd6Lw.mjs.map} +1 -1
  374. package/dist/{bylines-Bu7pchQ4.mjs → bylines-RwBAeOF1.mjs} +3 -3
  375. package/dist/{bylines-Bu7pchQ4.mjs.map → bylines-RwBAeOF1.mjs.map} +1 -1
  376. package/dist/{cache-C46-3Irl.mjs → cache-BF5Kvn59.mjs} +4 -4
  377. package/dist/{cache-C46-3Irl.mjs.map → cache-BF5Kvn59.mjs.map} +1 -1
  378. package/dist/capture-triggers-CNW1q3HK.mjs +362 -0
  379. package/dist/capture-triggers-CNW1q3HK.mjs.map +1 -0
  380. package/dist/{challenge-store-SIL5DsF2.mjs → challenge-store-DQN_Yrck.mjs} +5 -3
  381. package/dist/challenge-store-DQN_Yrck.mjs.map +1 -0
  382. package/dist/chrome-tags-D8fiZG94.mjs +24 -0
  383. package/dist/chrome-tags-D8fiZG94.mjs.map +1 -0
  384. package/dist/{chunks-fiZ8G9RJ.mjs → chunks-C4szrD8o.mjs} +2 -2
  385. package/dist/{chunks-fiZ8G9RJ.mjs.map → chunks-C4szrD8o.mjs.map} +1 -1
  386. package/dist/cli/index.mjs +37 -53
  387. package/dist/cli/index.mjs.map +1 -1
  388. package/dist/client/cf-access.d.mts +1 -1
  389. package/dist/client/index.d.mts +74 -4
  390. package/dist/client/index.d.mts.map +1 -1
  391. package/dist/client/index.mjs +54 -2
  392. package/dist/client/index.mjs.map +1 -1
  393. package/dist/{collection-deletion-DQPvMD8R.mjs → collection-deletion-Bj07NHbj.mjs} +13 -356
  394. package/dist/collection-deletion-Bj07NHbj.mjs.map +1 -0
  395. package/dist/{comment-reaction-D-2J84UE.mjs → comment-reaction-BhrvSHml.mjs} +2 -2
  396. package/dist/{comment-reaction-D-2J84UE.mjs.map → comment-reaction-BhrvSHml.mjs.map} +1 -1
  397. package/dist/{comment-Dxlep6cE.mjs → comment-vxOzWbZN.mjs} +2 -2
  398. package/dist/{comment-Dxlep6cE.mjs.map → comment-vxOzWbZN.mjs.map} +1 -1
  399. package/dist/{comments-CTfZtLmM.mjs → comments-Ct4ensnf.mjs} +2 -2
  400. package/dist/{comments-CTfZtLmM.mjs.map → comments-Ct4ensnf.mjs.map} +1 -1
  401. package/dist/{components-CQy3lh9x.mjs → components-DJbo1z0S.mjs} +1 -1
  402. package/dist/{components-CQy3lh9x.mjs.map → components-DJbo1z0S.mjs.map} +1 -1
  403. package/dist/{config-COQzTe5Q.d.mts → config-B9eZ340f.d.mts} +1 -1
  404. package/dist/{config-COQzTe5Q.d.mts.map → config-B9eZ340f.d.mts.map} +1 -1
  405. package/dist/config-it29yDLA.mjs +1163 -0
  406. package/dist/config-it29yDLA.mjs.map +1 -0
  407. package/dist/{content-ZHCc1ngN.mjs → content-DjvM0T92.mjs} +86 -45
  408. package/dist/content-DjvM0T92.mjs.map +1 -0
  409. package/dist/{content-list-query-wJ2WN8Vp.d.mts → content-list-query-Btqd4uV2.d.mts} +1 -1
  410. package/dist/{content-list-query-wJ2WN8Vp.d.mts.map → content-list-query-Btqd4uV2.d.mts.map} +1 -1
  411. package/dist/{content-refresh-B_8SJzuU.mjs → content-refresh-Bwp-8yGy.mjs} +1139 -111
  412. package/dist/content-refresh-Bwp-8yGy.mjs.map +1 -0
  413. package/dist/{media-usage-BZCydfvu.mjs → content-repair-Czdp7jz5.mjs} +5 -196
  414. package/dist/content-repair-Czdp7jz5.mjs.map +1 -0
  415. package/dist/{context-ZldbZcle.mjs → context-CX6gxOLW.mjs} +55 -20
  416. package/dist/context-CX6gxOLW.mjs.map +1 -0
  417. package/dist/{cron-Y9aLtgrA.mjs → cron-C6o7VppJ.mjs} +1 -1
  418. package/dist/{cron-Y9aLtgrA.mjs.map → cron-C6o7VppJ.mjs.map} +1 -1
  419. package/dist/{dashboard-DvHbk_cv.mjs → dashboard-C2kTeeRI.mjs} +5 -5
  420. package/dist/{dashboard-DvHbk_cv.mjs.map → dashboard-C2kTeeRI.mjs.map} +1 -1
  421. package/dist/db/index.d.mts +3 -3
  422. package/dist/db/index.mjs +3 -3
  423. package/dist/db/index.mjs.map +1 -1
  424. package/dist/db/libsql-migrations.d.mts +1 -1
  425. package/dist/db/libsql-migrations.mjs +4 -4
  426. package/dist/db/libsql.d.mts +1 -1
  427. package/dist/db/postgres-migrations.d.mts +1 -1
  428. package/dist/db/postgres-migrations.mjs +4 -4
  429. package/dist/db/postgres.d.mts +1 -1
  430. package/dist/db/postgres.d.mts.map +1 -1
  431. package/dist/db/postgres.mjs +19 -3
  432. package/dist/db/postgres.mjs.map +1 -1
  433. package/dist/db/sqlite-migrations.d.mts +1 -1
  434. package/dist/db/sqlite-migrations.mjs +4 -4
  435. package/dist/db/sqlite.d.mts +1 -1
  436. package/dist/db/sqlite.mjs +3 -3
  437. package/dist/db/sqlite.mjs.map +1 -1
  438. package/dist/{default-DdDl3fxv.mjs → default-Clra32mw.mjs} +1 -1
  439. package/dist/{default-DdDl3fxv.mjs.map → default-Clra32mw.mjs.map} +1 -1
  440. package/dist/{deferred-tasks-SDWxrgzJ.d.mts → deferred-tasks-CvDETTJO.d.mts} +1 -1
  441. package/dist/{deferred-tasks-SDWxrgzJ.d.mts.map → deferred-tasks-CvDETTJO.d.mts.map} +1 -1
  442. package/dist/dev-typegen-DzOPfsNj.mjs +29 -0
  443. package/dist/dev-typegen-DzOPfsNj.mjs.map +1 -0
  444. package/dist/{device-flow-C0GdD_z8.mjs → device-flow-D2oCWvLJ.mjs} +5 -5
  445. package/dist/{device-flow-C0GdD_z8.mjs.map → device-flow-D2oCWvLJ.mjs.map} +1 -1
  446. package/dist/{direct-executor-CDXeJCSs.mjs → direct-executor-Bfa5_ToE.mjs} +3 -3
  447. package/dist/{direct-executor-CDXeJCSs.mjs.map → direct-executor-Bfa5_ToE.mjs.map} +1 -1
  448. package/dist/{dist-D_6CKR8z.mjs → dist-89xCrGqi.mjs} +1 -1
  449. package/dist/{dist-D_6CKR8z.mjs.map → dist-89xCrGqi.mjs.map} +1 -1
  450. package/dist/{email-console-BHNjIwiB.mjs → email-console-Dzb6uGYa.mjs} +1 -1
  451. package/dist/{email-console-BHNjIwiB.mjs.map → email-console-Dzb6uGYa.mjs.map} +1 -1
  452. package/dist/{enrich-_ySMEvEE.mjs → enrich-BX0IDp4z.mjs} +3 -3
  453. package/dist/{enrich-_ySMEvEE.mjs.map → enrich-BX0IDp4z.mjs.map} +1 -1
  454. package/dist/{error-DupyJZE2.mjs → error-DFrQjppn.mjs} +2 -2
  455. package/dist/{error-DupyJZE2.mjs.map → error-DFrQjppn.mjs.map} +1 -1
  456. package/dist/{errors-CLUPm7aD.mjs → errors-DsVoDUjJ.mjs} +24 -2
  457. package/dist/errors-DsVoDUjJ.mjs.map +1 -0
  458. package/dist/{escape-DUY2r2Zs.mjs → escape-HmHTC1Is.mjs} +1 -1
  459. package/dist/{escape-DUY2r2Zs.mjs.map → escape-HmHTC1Is.mjs.map} +1 -1
  460. package/dist/{field-defs-cache-BzwBlJrR.mjs → field-defs-cache-BM4SIRqH.mjs} +5 -5
  461. package/dist/{field-defs-cache-BzwBlJrR.mjs.map → field-defs-cache-BM4SIRqH.mjs.map} +1 -1
  462. package/dist/focal-point-BeWFo6Xx.mjs +23 -0
  463. package/dist/focal-point-BeWFo6Xx.mjs.map +1 -0
  464. package/dist/{fts-manager-DyZEohZC.mjs → fts-manager-Do1BlW2r.mjs} +3 -3
  465. package/dist/{fts-manager-DyZEohZC.mjs.map → fts-manager-Do1BlW2r.mjs.map} +1 -1
  466. package/dist/{hash-Cg0TXJPV.mjs → hash-3JJPlHF2.mjs} +1 -1
  467. package/dist/{hash-Cg0TXJPV.mjs.map → hash-3JJPlHF2.mjs.map} +1 -1
  468. package/dist/hook-result-DCh2WUpe.d.mts +31 -0
  469. package/dist/hook-result-DCh2WUpe.d.mts.map +1 -0
  470. package/dist/{hreflang-DwT2E0Sa.d.mts → hreflang-B6hbAuuO.d.mts} +2 -2
  471. package/dist/{hreflang-DwT2E0Sa.d.mts.map → hreflang-B6hbAuuO.d.mts.map} +1 -1
  472. package/dist/{hreflang-BBe83kKa.mjs → hreflang-DQbPZliA.mjs} +7 -7
  473. package/dist/{hreflang-BBe83kKa.mjs.map → hreflang-DQbPZliA.mjs.map} +1 -1
  474. package/dist/{identity-Ys6Dlc9C.mjs → identity-DksvEazf.mjs} +3 -3
  475. package/dist/{identity-Ys6Dlc9C.mjs.map → identity-DksvEazf.mjs.map} +1 -1
  476. package/dist/{import-DPkLmeXO.mjs → import-CJpaBBBT.mjs} +6 -6
  477. package/dist/{import-DPkLmeXO.mjs.map → import-CJpaBBBT.mjs.map} +1 -1
  478. package/dist/{index-BVBZj4-7.d.mts → index-BJNMCWmu.d.mts} +267 -82
  479. package/dist/index-BJNMCWmu.d.mts.map +1 -0
  480. package/dist/{index-C9KuQyO-.d.mts → index-Du8K7bWa.d.mts} +3 -3
  481. package/dist/{index-C9KuQyO-.d.mts.map → index-Du8K7bWa.d.mts.map} +1 -1
  482. package/dist/index.d.mts +22 -21
  483. package/dist/index.mjs +79 -73
  484. package/dist/{init-lock-6b309ZrF.mjs → init-lock-DJkX6Hto.mjs} +1 -1
  485. package/dist/{init-lock-6b309ZrF.mjs.map → init-lock-DJkX6Hto.mjs.map} +1 -1
  486. package/dist/{load-YJ2xl3ra.mjs → load-CawHjTOH.mjs} +2 -2
  487. package/dist/{load-YJ2xl3ra.mjs.map → load-CawHjTOH.mjs.map} +1 -1
  488. package/dist/{loader-CdG_Ci3H.mjs → loader-Z8vl7zTq.mjs} +48 -13
  489. package/dist/loader-Z8vl7zTq.mjs.map +1 -0
  490. package/dist/{manifest-builder-B252yQUf.mjs → manifest-builder-COtzuca2.mjs} +2 -2
  491. package/dist/{manifest-builder-B252yQUf.mjs.map → manifest-builder-COtzuca2.mjs.map} +1 -1
  492. package/dist/{manifest-schema-BXbUAHod.mjs → manifest-schema-BNWwR8Vd.mjs} +5 -5
  493. package/dist/manifest-schema-BNWwR8Vd.mjs.map +1 -0
  494. package/dist/media/image-endpoint.d.mts +4 -2
  495. package/dist/media/image-endpoint.d.mts.map +1 -1
  496. package/dist/media/image-endpoint.mjs +6 -4
  497. package/dist/media/image-endpoint.mjs.map +1 -1
  498. package/dist/media/index.d.mts +1 -1
  499. package/dist/media/index.mjs +13 -3
  500. package/dist/media/index.mjs.map +1 -1
  501. package/dist/media/local-runtime.d.mts +14 -12
  502. package/dist/media/local-runtime.d.mts.map +1 -1
  503. package/dist/media/local-runtime.mjs +12 -6
  504. package/dist/media/local-runtime.mjs.map +1 -1
  505. package/dist/{media-CzhAn2--.mjs → media-BBm8Wg3f.mjs} +69 -12
  506. package/dist/media-BBm8Wg3f.mjs.map +1 -0
  507. package/dist/{media-BWWWb8kg.mjs → media-BHjus86Y.mjs} +133 -9
  508. package/dist/media-BHjus86Y.mjs.map +1 -0
  509. package/dist/{media-allowlist-D6x-Us02.mjs → media-allowlist-CoTBWoDp.mjs} +3 -2
  510. package/dist/media-allowlist-CoTBWoDp.mjs.map +1 -0
  511. package/dist/media-folders-BGkATs8n.mjs +210 -0
  512. package/dist/media-folders-BGkATs8n.mjs.map +1 -0
  513. package/dist/{media-upload-CHBVn6m-.mjs → media-upload-BCidR-EY.mjs} +9 -9
  514. package/dist/{media-upload-CHBVn6m-.mjs.map → media-upload-BCidR-EY.mjs.map} +1 -1
  515. package/dist/{media-url-BvoX88FA.mjs → media-url-DHoPr0hq.mjs} +1 -1
  516. package/dist/{media-url-BvoX88FA.mjs.map → media-url-DHoPr0hq.mjs.map} +1 -1
  517. package/dist/media-usage-CdY5jhSR.mjs +1833 -0
  518. package/dist/media-usage-CdY5jhSR.mjs.map +1 -0
  519. package/dist/media-usage-activation-BgeMtK5C.mjs +78 -0
  520. package/dist/media-usage-activation-BgeMtK5C.mjs.map +1 -0
  521. package/dist/{media-usage-work-CLo_6tct.mjs → media-usage-work-CnGCdHxx.mjs} +4 -4
  522. package/dist/{media-usage-work-CLo_6tct.mjs.map → media-usage-work-CnGCdHxx.mjs.map} +1 -1
  523. package/dist/{media-usage-work-DrCbqBcl.mjs → media-usage-work-D6D9sMCA.mjs} +221 -59
  524. package/dist/media-usage-work-D6D9sMCA.mjs.map +1 -0
  525. package/dist/{media-usage-write-fence-aHEgN1zB.mjs → media-usage-write-fence-hjeD4u7s.mjs} +2 -2
  526. package/dist/{media-usage-write-fence-aHEgN1zB.mjs.map → media-usage-write-fence-hjeD4u7s.mjs.map} +1 -1
  527. package/dist/{menus-DSo5QeW0.mjs → menus-6qSwTNxG.mjs} +375 -107
  528. package/dist/menus-6qSwTNxG.mjs.map +1 -0
  529. package/dist/{menus-TCNSd2vp.mjs → menus-uvPLXMZf.mjs} +4 -4
  530. package/dist/{menus-TCNSd2vp.mjs.map → menus-uvPLXMZf.mjs.map} +1 -1
  531. package/dist/migrations/index.d.mts +1 -1
  532. package/dist/migrations/index.mjs +3 -3
  533. package/dist/{mime-DfIVjNkr.mjs → mime-CUIG6x84.mjs} +1 -1
  534. package/dist/mime-CUIG6x84.mjs.map +1 -0
  535. package/dist/{mode-BDoH_WcF.mjs → mode-DN_WneRx.mjs} +1 -1
  536. package/dist/{mode-BDoH_WcF.mjs.map → mode-DN_WneRx.mjs.map} +1 -1
  537. package/dist/node-sqlite-compat-BuJXIeMz.mjs +46 -0
  538. package/dist/node-sqlite-compat-BuJXIeMz.mjs.map +1 -0
  539. package/dist/{normalize-Bc-s_r-a.mjs → normalize-C2xNjTSG.mjs} +36 -5
  540. package/dist/normalize-C2xNjTSG.mjs.map +1 -0
  541. package/dist/{oauth-authorization-iOikmrJd.mjs → oauth-authorization-Dj6Kwc21.mjs} +5 -5
  542. package/dist/{oauth-authorization-iOikmrJd.mjs.map → oauth-authorization-Dj6Kwc21.mjs.map} +1 -1
  543. package/dist/{oauth-clients-CvI0nHMJ.mjs → oauth-clients-FD7I0J8m.mjs} +1 -1
  544. package/dist/{oauth-clients-CvI0nHMJ.mjs.map → oauth-clients-FD7I0J8m.mjs.map} +1 -1
  545. package/dist/{oauth-state-store-Ba8KZlwW.mjs → oauth-state-store-DkmDOmHs.mjs} +1 -1
  546. package/dist/{oauth-state-store-Ba8KZlwW.mjs.map → oauth-state-store-DkmDOmHs.mjs.map} +1 -1
  547. package/dist/{oauth-user-lookup-C5SQwGYC.mjs → oauth-user-lookup-CvIwGpYd.mjs} +1 -1
  548. package/dist/{oauth-user-lookup-C5SQwGYC.mjs.map → oauth-user-lookup-CvIwGpYd.mjs.map} +1 -1
  549. package/dist/object-cache/memory.d.mts +1 -1
  550. package/dist/{object-cache-71tPfV4A.mjs → object-cache-DVKnyOfy.mjs} +19 -3
  551. package/dist/object-cache-DVKnyOfy.mjs.map +1 -0
  552. package/dist/{options-CBXIHUoT.mjs → options-BHPeIbBd.mjs} +1 -1
  553. package/dist/{options-CBXIHUoT.mjs.map → options-BHPeIbBd.mjs.map} +1 -1
  554. package/dist/{options--hhz-jZ1.d.mts → options-CYb4y7hM.d.mts} +24 -11
  555. package/dist/options-CYb4y7hM.d.mts.map +1 -0
  556. package/dist/page/index.d.mts +2 -2
  557. package/dist/{parse-DFbuc-Fh.mjs → parse-Ckpg-Qfp.mjs} +2 -2
  558. package/dist/{parse-DFbuc-Fh.mjs.map → parse-Ckpg-Qfp.mjs.map} +1 -1
  559. package/dist/{passkey-config-DFAmUyuE.mjs → passkey-config-O_lj3y0k.mjs} +1 -1
  560. package/dist/{passkey-config-DFAmUyuE.mjs.map → passkey-config-O_lj3y0k.mjs.map} +1 -1
  561. package/dist/{patterns-CiyXeDgr.mjs → patterns-D9iDO3j8.mjs} +1 -1
  562. package/dist/{patterns-CiyXeDgr.mjs.map → patterns-D9iDO3j8.mjs.map} +1 -1
  563. package/dist/{placeholder-Dp0K3RkD.d.mts → placeholder-4X9BrRrp.d.mts} +7 -1
  564. package/dist/placeholder-4X9BrRrp.d.mts.map +1 -0
  565. package/dist/plugin-types.d.mts +8 -3
  566. package/dist/plugin-types.d.mts.map +1 -1
  567. package/dist/plugin-utils.d.mts +10 -10
  568. package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
  569. package/dist/plugins/adapt-sandbox-entry.mjs +2 -2
  570. package/dist/{policy-TluUIxuu.mjs → policy-Dhtwntrt.mjs} +2 -2
  571. package/dist/{policy-TluUIxuu.mjs.map → policy-Dhtwntrt.mjs.map} +1 -1
  572. package/dist/{portable-text-imBW5cHK.mjs → portable-text-U85hOafW.mjs} +1 -1
  573. package/dist/{portable-text-imBW5cHK.mjs.map → portable-text-U85hOafW.mjs.map} +1 -1
  574. package/dist/{preview-PW-nOnq4.mjs → preview-B_vJLvf8.mjs} +2 -2
  575. package/dist/{preview-PW-nOnq4.mjs.map → preview-B_vJLvf8.mjs.map} +1 -1
  576. package/dist/{protocol-DjsJHTlK.d.mts → protocol-JdD2YhY9.d.mts} +2 -2
  577. package/dist/{protocol-DjsJHTlK.d.mts.map → protocol-JdD2YhY9.d.mts.map} +1 -1
  578. package/dist/{public-url-CWoFhQT8.mjs → public-url-CarhZJgf.mjs} +1 -1
  579. package/dist/{public-url-CWoFhQT8.mjs.map → public-url-CarhZJgf.mjs.map} +1 -1
  580. package/dist/{query-zTVAR1Sl.mjs → query-BZKZcG5b.mjs} +15 -15
  581. package/dist/{query-zTVAR1Sl.mjs.map → query-BZKZcG5b.mjs.map} +1 -1
  582. package/dist/{query-BWs7O5Il.mjs → query-BndaFxxp.mjs} +5 -5
  583. package/dist/{query-BWs7O5Il.mjs.map → query-BndaFxxp.mjs.map} +1 -1
  584. package/dist/{rate-limit-Bx4g9m3p.mjs → rate-limit-BZmATC6W.mjs} +2 -2
  585. package/dist/{rate-limit-Bx4g9m3p.mjs.map → rate-limit-BZmATC6W.mjs.map} +1 -1
  586. package/dist/{redirect-COsS6SWJ.mjs → redirect-CZkbozu9.mjs} +2 -2
  587. package/dist/{redirect-COsS6SWJ.mjs.map → redirect-CZkbozu9.mjs.map} +1 -1
  588. package/dist/{redirect-BgAOGHDq.mjs → redirect-CzqnLxK-.mjs} +1 -1
  589. package/dist/{redirect-BgAOGHDq.mjs.map → redirect-CzqnLxK-.mjs.map} +1 -1
  590. package/dist/{redirects-DTDHWH31.mjs → redirects-BLNOWQTn.mjs} +64 -29
  591. package/dist/redirects-BLNOWQTn.mjs.map +1 -0
  592. package/dist/{redirects-DyChwDkG.mjs → redirects-CqzNM0KM.mjs} +5 -5
  593. package/dist/{redirects-DyChwDkG.mjs.map → redirects-CqzNM0KM.mjs.map} +1 -1
  594. package/dist/{registry-Cqa2I749.mjs → registry-AZAsRsor.mjs} +30 -126
  595. package/dist/registry-AZAsRsor.mjs.map +1 -0
  596. package/dist/{relation-BnHB0T4J.mjs → relation-04DfKRTO.mjs} +2 -2
  597. package/dist/{relation-BnHB0T4J.mjs.map → relation-04DfKRTO.mjs.map} +1 -1
  598. package/dist/{relations-BBApI4e2.mjs → relations-C4htk5sb.mjs} +7 -7
  599. package/dist/relations-C4htk5sb.mjs.map +1 -0
  600. package/dist/{relations-D5sM5fW0.mjs → relations-CcFwDJdJ.mjs} +4 -4
  601. package/dist/{relations-D5sM5fW0.mjs.map → relations-CcFwDJdJ.mjs.map} +1 -1
  602. package/dist/{relations-BHo5A8Zf.d.mts → relations-DnRK4YIT.d.mts} +347 -54
  603. package/dist/relations-DnRK4YIT.d.mts.map +1 -0
  604. package/dist/{request-cache-BSUptuJR.mjs → request-cache-DH9zdCOD.mjs} +1 -1
  605. package/dist/{request-cache-BSUptuJR.mjs.map → request-cache-DH9zdCOD.mjs.map} +1 -1
  606. package/dist/request-context.d.mts +1 -1
  607. package/dist/{request-meta-DgZJh3zG.mjs → request-meta-DYxLlnmz.mjs} +2 -2
  608. package/dist/{request-meta-DgZJh3zG.mjs.map → request-meta-DYxLlnmz.mjs.map} +1 -1
  609. package/dist/{resolve-DOhVEvty.mjs → resolve-prZ3mP7l.mjs} +1 -1
  610. package/dist/{resolve-DOhVEvty.mjs.map → resolve-prZ3mP7l.mjs.map} +1 -1
  611. package/dist/{runner-C1T11CfC.mjs → runner-BLIDKpmA.mjs} +471 -290
  612. package/dist/runner-BLIDKpmA.mjs.map +1 -0
  613. package/dist/{runner-BYHZn3Jy.d.mts → runner-YKfIMnaF.d.mts} +3 -2
  614. package/dist/runner-YKfIMnaF.d.mts.map +1 -0
  615. package/dist/runtime.d.mts +11 -11
  616. package/dist/runtime.mjs +1 -1
  617. package/dist/{schema-DZ5YVVZj.mjs → schema-CGnBeLiW.mjs} +3 -3
  618. package/dist/{schema-DZ5YVVZj.mjs.map → schema-CGnBeLiW.mjs.map} +1 -1
  619. package/dist/{schema-2AOsSn2v.mjs → schema-DYr-Vd-L.mjs} +36 -6
  620. package/dist/{schema-2AOsSn2v.mjs.map → schema-DYr-Vd-L.mjs.map} +1 -1
  621. package/dist/{scopes-8ClPF2bC.mjs → scopes-BhWvBavj.mjs} +3 -3
  622. package/dist/{scopes-8ClPF2bC.mjs.map → scopes-BhWvBavj.mjs.map} +1 -1
  623. package/dist/{search-u1QYdOCG.mjs → search-C-qDk4kx.mjs} +4 -4
  624. package/dist/{search-u1QYdOCG.mjs.map → search-C-qDk4kx.mjs.map} +1 -1
  625. package/dist/{secrets-BEgsAQEU.mjs → secrets-rEtHt-6z.mjs} +3 -3
  626. package/dist/{secrets-BEgsAQEU.mjs.map → secrets-rEtHt-6z.mjs.map} +1 -1
  627. package/dist/{sections-DmHviGyM.mjs → sections-B_nYvlwn.mjs} +2 -2
  628. package/dist/{sections-DmHviGyM.mjs.map → sections-B_nYvlwn.mjs.map} +1 -1
  629. package/dist/seed/index.d.mts +2 -2
  630. package/dist/seed/index.mjs +25 -23
  631. package/dist/seo/index.d.mts +3 -3
  632. package/dist/seo/index.mjs +17 -15
  633. package/dist/seo/index.mjs.map +1 -1
  634. package/dist/{seo-Dq4G-RrO.mjs → seo-926NRIgt.mjs} +3 -3
  635. package/dist/{seo-Dq4G-RrO.mjs.map → seo-926NRIgt.mjs.map} +1 -1
  636. package/dist/{seo-AFpVvTqr.mjs → seo-CVWkdv6x.mjs} +1 -1
  637. package/dist/{seo-AFpVvTqr.mjs.map → seo-CVWkdv6x.mjs.map} +1 -1
  638. package/dist/{service-BpArayPr.mjs → service-CJl3ZAYs.mjs} +3 -3
  639. package/dist/{service-BpArayPr.mjs.map → service-CJl3ZAYs.mjs.map} +1 -1
  640. package/dist/{session-user-BEorKVT-.mjs → session-user-BlMgqCHS.mjs} +1 -1
  641. package/dist/{session-user-BEorKVT-.mjs.map → session-user-BlMgqCHS.mjs.map} +1 -1
  642. package/dist/{settings-xRdoUZr0.mjs → settings--wobrkkC.mjs} +21 -8
  643. package/dist/settings--wobrkkC.mjs.map +1 -0
  644. package/dist/{settings-DE9xtzqd.mjs → settings-Cwm6o2jY.mjs} +3 -3
  645. package/dist/{settings-DE9xtzqd.mjs.map → settings-Cwm6o2jY.mjs.map} +1 -1
  646. package/dist/{setup-complete-BnT8pq_C.mjs → setup-complete-DQbClIN2.mjs} +2 -2
  647. package/dist/{setup-complete-BnT8pq_C.mjs.map → setup-complete-DQbClIN2.mjs.map} +1 -1
  648. package/dist/{setup-nonce-CBitf_oQ.mjs → setup-nonce-DZCFS2sn.mjs} +1 -1
  649. package/dist/{setup-nonce-CBitf_oQ.mjs.map → setup-nonce-DZCFS2sn.mjs.map} +1 -1
  650. package/dist/{single-flight-cache-B0eLKS6K.mjs → single-flight-cache-BPuGPdcN.mjs} +2 -2
  651. package/dist/{single-flight-cache-B0eLKS6K.mjs.map → single-flight-cache-BPuGPdcN.mjs.map} +1 -1
  652. package/dist/{site-url-DjpIXMXJ.mjs → site-url-BrxA_E9H.mjs} +3 -3
  653. package/dist/{site-url-DjpIXMXJ.mjs.map → site-url-BrxA_E9H.mjs.map} +1 -1
  654. package/dist/{snapshot-BBlGkb2q.mjs → snapshot--OCDTqdb.mjs} +1 -1
  655. package/dist/{snapshot-BBlGkb2q.mjs.map → snapshot--OCDTqdb.mjs.map} +1 -1
  656. package/dist/{ssrf-Cpvg_n3A.mjs → ssrf-5sIM5jzl.mjs} +23 -6
  657. package/dist/{ssrf-Cpvg_n3A.mjs.map → ssrf-5sIM5jzl.mjs.map} +1 -1
  658. package/dist/{state-DYwPue40.mjs → state-BpFVsJZB.mjs} +12 -4
  659. package/dist/state-BpFVsJZB.mjs.map +1 -0
  660. package/dist/{status-CWVYpbD8.mjs → status-B777-dXz.mjs} +1 -1
  661. package/dist/{status-CWVYpbD8.mjs.map → status-B777-dXz.mjs.map} +1 -1
  662. package/dist/storage/local.d.mts +2 -1
  663. package/dist/storage/local.d.mts.map +1 -1
  664. package/dist/storage/local.mjs +1 -1
  665. package/dist/storage/local.mjs.map +1 -1
  666. package/dist/storage/s3.d.mts +2 -1
  667. package/dist/storage/s3.d.mts.map +1 -1
  668. package/dist/storage/s3.mjs +3 -2
  669. package/dist/storage/s3.mjs.map +1 -1
  670. package/dist/{target-DixqqV5i.mjs → target-BmR0iTwz.mjs} +1 -1
  671. package/dist/{target-DixqqV5i.mjs.map → target-BmR0iTwz.mjs.map} +1 -1
  672. package/dist/{taxonomies-OHUIiIpI.mjs → taxonomies-DkAkMupr.mjs} +17 -14
  673. package/dist/taxonomies-DkAkMupr.mjs.map +1 -0
  674. package/dist/{taxonomies-BlrncHi9.mjs → taxonomies-Wfy_Lg12.mjs} +43 -17
  675. package/dist/taxonomies-Wfy_Lg12.mjs.map +1 -0
  676. package/dist/{taxonomy-BqCZ1TdU.mjs → taxonomy-tJepplLL.mjs} +5 -5
  677. package/dist/{taxonomy-BqCZ1TdU.mjs.map → taxonomy-tJepplLL.mjs.map} +1 -1
  678. package/dist/{tokens-C39klX8R.mjs → tokens-BCO1oruF.mjs} +1 -1
  679. package/dist/{tokens-C39klX8R.mjs.map → tokens-BCO1oruF.mjs.map} +1 -1
  680. package/dist/{transaction-NQj4VJ7Z.mjs → transaction-0KOpOyMu.mjs} +2 -1
  681. package/dist/{transaction-NQj4VJ7Z.mjs.map → transaction-0KOpOyMu.mjs.map} +1 -1
  682. package/dist/{transport-DBJwa-Si.mjs → transport-Dr3qtwXC.mjs} +4 -3
  683. package/dist/{transport-DBJwa-Si.mjs.map → transport-Dr3qtwXC.mjs.map} +1 -1
  684. package/dist/{transport-RQE36APG.d.mts → transport-xh6YKW2G.d.mts} +1 -1
  685. package/dist/{transport-RQE36APG.d.mts.map → transport-xh6YKW2G.d.mts.map} +1 -1
  686. package/dist/{trusted-proxy-CEVekpby.mjs → trusted-proxy-BR5F1Otp.mjs} +1 -1
  687. package/dist/{trusted-proxy-CEVekpby.mjs.map → trusted-proxy-BR5F1Otp.mjs.map} +1 -1
  688. package/dist/{types-BW1syrlw.mjs → types-3qNFPlci.mjs} +1 -1
  689. package/dist/{types-BW1syrlw.mjs.map → types-3qNFPlci.mjs.map} +1 -1
  690. package/dist/types-75KIqzL9.mjs.map +1 -1
  691. package/dist/{types-DrJrVCT1.d.mts → types-B6GrPic4.d.mts} +9 -3
  692. package/dist/{types-DrJrVCT1.d.mts.map → types-B6GrPic4.d.mts.map} +1 -1
  693. package/dist/{types-DN64_zzZ.d.mts → types-BuHW4xDE.d.mts} +11 -10
  694. package/dist/types-BuHW4xDE.d.mts.map +1 -0
  695. package/dist/{types-DWRhk9xZ.d.mts → types-C00oyCZp.d.mts} +1 -1
  696. package/dist/{types-DWRhk9xZ.d.mts.map → types-C00oyCZp.d.mts.map} +1 -1
  697. package/dist/{types-BntycPTF.d.mts → types-CDtkNSFQ.d.mts} +1 -1
  698. package/dist/{types-BntycPTF.d.mts.map → types-CDtkNSFQ.d.mts.map} +1 -1
  699. package/dist/{types-Dfk8KI5R.d.mts → types-CPeXo1wF.d.mts} +1 -1
  700. package/dist/{types-Dfk8KI5R.d.mts.map → types-CPeXo1wF.d.mts.map} +1 -1
  701. package/dist/types-CQPWhPxE.mjs.map +1 -1
  702. package/dist/{types-BcqdcT-r.d.mts → types-CXFkwEGC.d.mts} +3 -2
  703. package/dist/types-CXFkwEGC.d.mts.map +1 -0
  704. package/dist/{types-CtzytVXn.mjs → types-DM3vioBY.mjs} +1 -1
  705. package/dist/{types-CtzytVXn.mjs.map → types-DM3vioBY.mjs.map} +1 -1
  706. package/dist/{types-CXnOzDe1.d.mts → types-DczELMop.d.mts} +1 -1
  707. package/dist/{types-CXnOzDe1.d.mts.map → types-DczELMop.d.mts.map} +1 -1
  708. package/dist/types-DfuTR6dL.mjs +3 -0
  709. package/dist/{types-DQIDRKF2.d.mts → types-FV23hEoW.d.mts} +10 -1
  710. package/dist/types-FV23hEoW.d.mts.map +1 -0
  711. package/dist/{types-C2pMvO62.d.mts → types-xDMtUFnO.d.mts} +2 -1
  712. package/dist/types-xDMtUFnO.d.mts.map +1 -0
  713. package/dist/{upload-attempts-D4FS8LT6.mjs → upload-attempts-BsqoQ1fn.mjs} +1 -1
  714. package/dist/{upload-attempts-D4FS8LT6.mjs.map → upload-attempts-BsqoQ1fn.mjs.map} +1 -1
  715. package/dist/{url-pattern-BHS0V5Ng.mjs → url-pattern-D4c2czpJ.mjs} +1 -1
  716. package/dist/{url-pattern-BHS0V5Ng.mjs.map → url-pattern-D4c2czpJ.mjs.map} +1 -1
  717. package/dist/{user-DJZfUJVE.mjs → user-BTZ40aq6.mjs} +2 -2
  718. package/dist/{user-DJZfUJVE.mjs.map → user-BTZ40aq6.mjs.map} +1 -1
  719. package/dist/{utils-D4vD_Y98.mjs → utils-BKvNjjhY.mjs} +1 -1
  720. package/dist/{utils-D4vD_Y98.mjs.map → utils-BKvNjjhY.mjs.map} +1 -1
  721. package/dist/{validate-BMLBvxOC.mjs → validate-DE_LRwo9.mjs} +2 -2
  722. package/dist/{validate-BMLBvxOC.mjs.map → validate-DE_LRwo9.mjs.map} +1 -1
  723. package/dist/{validate-CTqt5nuE.d.mts → validate-DUP27OYD.d.mts} +5 -5
  724. package/dist/{validate-CTqt5nuE.d.mts.map → validate-DUP27OYD.d.mts.map} +1 -1
  725. package/dist/{validation-npvENUCB.mjs → validation-BMImFJ11.mjs} +10 -8
  726. package/dist/{validation-npvENUCB.mjs.map → validation-BMImFJ11.mjs.map} +1 -1
  727. package/dist/version-Bii3suaO.mjs +7 -0
  728. package/dist/{version-DB_fqCSI.mjs.map → version-Bii3suaO.mjs.map} +1 -1
  729. package/dist/{widgets-BD3ho7Rq.mjs → widgets-D3gJ10xU.mjs} +18 -5
  730. package/dist/widgets-D3gJ10xU.mjs.map +1 -0
  731. package/dist/{wxr-taxonomies-Ca68766D.d.mts → wxr-taxonomies-B2Og_6rU.d.mts} +1 -1
  732. package/dist/{wxr-taxonomies-Ca68766D.d.mts.map → wxr-taxonomies-B2Og_6rU.d.mts.map} +1 -1
  733. package/dist/{wxr-taxonomies-B1R3vBoD.mjs → wxr-taxonomies-Cxngsjwo.mjs} +4 -4
  734. package/dist/{wxr-taxonomies-B1R3vBoD.mjs.map → wxr-taxonomies-Cxngsjwo.mjs.map} +1 -1
  735. package/dist/{zod-generator-LC-on_Vb.mjs → zod-generator-BuYSQJB7.mjs} +32 -22
  736. package/dist/zod-generator-BuYSQJB7.mjs.map +1 -0
  737. package/package.json +20 -9
  738. package/src/api/errors.ts +22 -0
  739. package/src/api/handlers/content.ts +49 -11
  740. package/src/api/handlers/index.ts +18 -0
  741. package/src/api/handlers/manifest.ts +161 -12
  742. package/src/api/handlers/media-allowlist.ts +1 -0
  743. package/src/api/handlers/media-folders.ts +130 -0
  744. package/src/api/handlers/media-usage-activation.ts +102 -0
  745. package/src/api/handlers/media-usage.ts +108 -0
  746. package/src/api/handlers/media.ts +92 -2
  747. package/src/api/handlers/registry.ts +483 -561
  748. package/src/api/handlers/taxonomies.ts +16 -9
  749. package/src/api/openapi/document.ts +277 -7
  750. package/src/api/parse.ts +1 -1
  751. package/src/api/schemas/auth.ts +4 -4
  752. package/src/api/schemas/bylines.ts +3 -3
  753. package/src/api/schemas/comments.ts +1 -1
  754. package/src/api/schemas/common.ts +3 -2
  755. package/src/api/schemas/content.ts +78 -22
  756. package/src/api/schemas/media-usage.ts +77 -0
  757. package/src/api/schemas/media.ts +121 -0
  758. package/src/api/schemas/redirects.ts +6 -1
  759. package/src/api/schemas/schema.ts +4 -0
  760. package/src/api/schemas/setup.ts +1 -1
  761. package/src/api/schemas/taxonomies.ts +2 -2
  762. package/src/api/schemas/users.ts +1 -1
  763. package/src/api/types.ts +23 -10
  764. package/src/astro/dev-typegen.ts +35 -0
  765. package/src/astro/image-endpoint.ts +2 -2
  766. package/src/astro/integration/dev-typegen.ts +91 -0
  767. package/src/astro/integration/index.ts +9 -44
  768. package/src/astro/integration/routes.ts +23 -0
  769. package/src/astro/integration/vite-config.ts +23 -9
  770. package/src/astro/middleware/auth.ts +4 -0
  771. package/src/astro/middleware.ts +5 -7
  772. package/src/astro/routes/api/admin/api-tokens/index.ts +4 -1
  773. package/src/astro/routes/api/admin/media-usage/activation.ts +42 -0
  774. package/src/astro/routes/api/admin/media-usage/progress.ts +37 -0
  775. package/src/astro/routes/api/admin/oauth-clients/[id].ts +1 -1
  776. package/src/astro/routes/api/admin/oauth-clients/index.ts +1 -1
  777. package/src/astro/routes/api/admin/plugins/registry/[id]/update.ts +4 -0
  778. package/src/astro/routes/api/admin/plugins/registry/artifact.ts +247 -101
  779. package/src/astro/routes/api/admin/plugins/registry/install.ts +4 -0
  780. package/src/astro/routes/api/admin/plugins/registry/verify.ts +60 -0
  781. package/src/astro/routes/api/auth/me.ts +14 -2
  782. package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +8 -2
  783. package/src/astro/routes/api/content/[collection]/[id]/publish.ts +2 -1
  784. package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +6 -2
  785. package/src/astro/routes/api/manifest.ts +1 -1
  786. package/src/astro/routes/api/media/[id]/replace.ts +114 -0
  787. package/src/astro/routes/api/media/[id].ts +3 -0
  788. package/src/astro/routes/api/media/file/[...key].ts +4 -1
  789. package/src/astro/routes/api/media/folders/[id].ts +55 -0
  790. package/src/astro/routes/api/media/folders/index.ts +37 -0
  791. package/src/astro/routes/api/media/upload-url.ts +8 -4
  792. package/src/astro/routes/api/media.ts +66 -10
  793. package/src/astro/routes/api/menus/[name]/items/[id].ts +7 -2
  794. package/src/astro/routes/api/menus/[name]/items.ts +4 -1
  795. package/src/astro/routes/api/menus/[name]/reorder.ts +4 -1
  796. package/src/astro/routes/api/menus/[name]/translations.ts +4 -1
  797. package/src/astro/routes/api/menus/[name].ts +7 -2
  798. package/src/astro/routes/api/menus/index.ts +4 -1
  799. package/src/astro/routes/api/settings/email.ts +1 -1
  800. package/src/astro/routes/api/settings.ts +4 -1
  801. package/src/astro/routes/api/setup/dev-bypass.ts +12 -0
  802. package/src/astro/routes/api/taxonomies/[name]/reorder.ts +4 -1
  803. package/src/astro/routes/api/taxonomies/[name]/terms/[slug]/translations.ts +4 -1
  804. package/src/astro/routes/api/taxonomies/[name]/terms/[slug].ts +7 -2
  805. package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +4 -1
  806. package/src/astro/routes/api/taxonomies/[name].ts +7 -2
  807. package/src/astro/routes/api/taxonomies/index.ts +4 -1
  808. package/src/astro/routes/api/widget-areas/[name]/reorder.ts +3 -1
  809. package/src/astro/routes/api/widget-areas/[name]/widgets/[id].ts +5 -2
  810. package/src/astro/routes/api/widget-areas/[name]/widgets.ts +3 -1
  811. package/src/astro/routes/api/widget-areas/[name].ts +3 -1
  812. package/src/astro/routes/api/widget-areas/index.ts +3 -1
  813. package/src/astro/types.ts +34 -6
  814. package/src/auth/challenge-store.ts +3 -1
  815. package/src/aws-sdk.d.ts +1 -0
  816. package/src/cache/chrome-tags.ts +24 -0
  817. package/src/client/index.ts +140 -2
  818. package/src/client/transport.ts +6 -2
  819. package/src/components/EmDashImage.astro +156 -51
  820. package/src/components/EmDashMedia.astro +2 -1
  821. package/src/components/Gallery.astro +7 -0
  822. package/src/components/InlinePortableTextEditor.tsx +136 -2
  823. package/src/components/LiveSearch.astro +23 -0
  824. package/src/components/inline-code-block.tsx +180 -49
  825. package/src/components/widgets/Archives.astro +2 -37
  826. package/src/content/converters/gallery.ts +2 -0
  827. package/src/content/converters/index.ts +2 -0
  828. package/src/content/converters/mark-safety.ts +1 -0
  829. package/src/content/converters/portable-text-identity.ts +139 -0
  830. package/src/content/converters/portable-text-to-prosemirror.ts +202 -69
  831. package/src/content/converters/prosemirror-to-portable-text.ts +96 -25
  832. package/src/content/converters/types.ts +3 -0
  833. package/src/database/connection.ts +2 -31
  834. package/src/database/index.ts +1 -1
  835. package/src/database/json-recordset.ts +16 -0
  836. package/src/database/migrations/017_authorization_codes.ts +14 -4
  837. package/src/database/migrations/019_i18n.ts +1 -1
  838. package/src/database/migrations/071_restore_content_bylines_table.ts +43 -0
  839. package/src/database/migrations/072_media_folders.ts +72 -0
  840. package/src/database/migrations/073_media_focal_point.ts +57 -0
  841. package/src/database/migrations/074_content_deleted_scheduled_index.ts +55 -0
  842. package/src/database/migrations/runner.ts +11 -3
  843. package/src/database/repositories/byline.ts +32 -16
  844. package/src/database/repositories/content.ts +119 -51
  845. package/src/database/repositories/media-folders.ts +115 -0
  846. package/src/database/repositories/media-usage-work.ts +395 -111
  847. package/src/database/repositories/media-usage.ts +1104 -47
  848. package/src/database/repositories/media.ts +156 -29
  849. package/src/database/repositories/plugin-storage.ts +74 -9
  850. package/src/database/repositories/types.ts +8 -7
  851. package/src/database/transaction.ts +1 -0
  852. package/src/database/types.ts +13 -0
  853. package/src/db/adapters.ts +10 -3
  854. package/src/db/node-sqlite-compat.ts +78 -0
  855. package/src/db/postgres.ts +23 -0
  856. package/src/db/sqlite.ts +3 -3
  857. package/src/emdash-runtime.ts +186 -251
  858. package/src/fields/boolean.ts +1 -1
  859. package/src/fields/datetime.ts +1 -1
  860. package/src/fields/file.ts +1 -1
  861. package/src/fields/image.ts +7 -1
  862. package/src/fields/integer.ts +1 -1
  863. package/src/fields/json.ts +1 -1
  864. package/src/fields/multiselect.ts +1 -1
  865. package/src/fields/number.ts +1 -1
  866. package/src/fields/portable-text.ts +1 -1
  867. package/src/fields/richtext.ts +1 -1
  868. package/src/fields/select.ts +1 -1
  869. package/src/fields/slug.ts +1 -1
  870. package/src/fields/text.ts +1 -1
  871. package/src/fields/textarea.ts +1 -1
  872. package/src/fields/types.ts +8 -4
  873. package/src/index.ts +30 -3
  874. package/src/loader.ts +63 -10
  875. package/src/mcp/server.ts +228 -24
  876. package/src/media/focal-point.ts +37 -0
  877. package/src/media/image-endpoint.ts +5 -2
  878. package/src/media/local-runtime.ts +8 -0
  879. package/src/media/mime.ts +1 -0
  880. package/src/media/normalize.ts +25 -4
  881. package/src/media/types.ts +10 -0
  882. package/src/media/usage/activation.ts +162 -35
  883. package/src/media/usage/capture-triggers.ts +19 -3
  884. package/src/media/usage/cleanup.ts +9 -8
  885. package/src/media/usage/collection-deletion-processor.ts +7 -3
  886. package/src/media/usage/collection-deletion.ts +10 -0
  887. package/src/media/usage/content-refresh.ts +258 -39
  888. package/src/media/usage/content-snapshots.ts +128 -31
  889. package/src/media/usage/extractor.ts +32 -13
  890. package/src/media/usage/maintenance-engine.ts +166 -0
  891. package/src/media/usage/reconciliation-processor.ts +106 -29
  892. package/src/media/usage/reconciliation.ts +90 -7
  893. package/src/media/usage/work-processor.ts +342 -101
  894. package/src/menus/index.ts +16 -0
  895. package/src/object-cache/index.ts +44 -2
  896. package/src/plugin-types.ts +18 -1
  897. package/src/plugins/hooks.ts +4 -1
  898. package/src/plugins/index.ts +7 -0
  899. package/src/plugins/manager.ts +2 -1
  900. package/src/plugins/manifest-schema.ts +1 -1
  901. package/src/plugins/routes.ts +3 -1
  902. package/src/plugins/sandbox/hook-result.ts +52 -0
  903. package/src/plugins/sandbox/index.ts +10 -0
  904. package/src/plugins/save-rejection.ts +20 -0
  905. package/src/plugins/scheduler/node.ts +1 -13
  906. package/src/plugins/scheduler/types.ts +0 -2
  907. package/src/plugins/state.ts +13 -3
  908. package/src/plugins/types.ts +6 -0
  909. package/src/registry/artifact-checksum.ts +15 -0
  910. package/src/registry/artifact-fetch.ts +530 -0
  911. package/src/registry/artifact-verification.ts +85 -0
  912. package/src/registry/authoritative-records.ts +180 -0
  913. package/src/registry/config.ts +24 -6
  914. package/src/registry/record-labels.ts +28 -0
  915. package/src/registry/types.ts +12 -15
  916. package/src/schema/registry.ts +26 -3
  917. package/src/schema/types.ts +1 -0
  918. package/src/schema/zod-generator.ts +28 -17
  919. package/src/security/ssrf.ts +26 -4
  920. package/src/seed/apply.ts +4 -4
  921. package/src/settings/index.ts +16 -0
  922. package/src/storage/local.ts +1 -0
  923. package/src/storage/s3.ts +2 -0
  924. package/src/storage/types.ts +2 -0
  925. package/src/taxonomies/index.ts +40 -20
  926. package/src/ui.ts +2 -0
  927. package/src/widgets/archives.ts +67 -0
  928. package/src/widgets/index.ts +16 -0
  929. package/dist/api-BeBglVxU.mjs +0 -4695
  930. package/dist/api-BeBglVxU.mjs.map +0 -1
  931. package/dist/byline-yjvWq4ip.mjs.map +0 -1
  932. package/dist/challenge-store-SIL5DsF2.mjs.map +0 -1
  933. package/dist/collection-deletion-DQPvMD8R.mjs.map +0 -1
  934. package/dist/content-ZHCc1ngN.mjs.map +0 -1
  935. package/dist/content-refresh-B_8SJzuU.mjs.map +0 -1
  936. package/dist/context-ZldbZcle.mjs.map +0 -1
  937. package/dist/errors-CLUPm7aD.mjs.map +0 -1
  938. package/dist/index-BVBZj4-7.d.mts.map +0 -1
  939. package/dist/loader-CdG_Ci3H.mjs.map +0 -1
  940. package/dist/manifest-schema-BXbUAHod.mjs.map +0 -1
  941. package/dist/media-BWWWb8kg.mjs.map +0 -1
  942. package/dist/media-CzhAn2--.mjs.map +0 -1
  943. package/dist/media-allowlist-D6x-Us02.mjs.map +0 -1
  944. package/dist/media-usage-BZCydfvu.mjs.map +0 -1
  945. package/dist/media-usage-work-DrCbqBcl.mjs.map +0 -1
  946. package/dist/menus-DSo5QeW0.mjs.map +0 -1
  947. package/dist/mime-DfIVjNkr.mjs.map +0 -1
  948. package/dist/normalize-Bc-s_r-a.mjs.map +0 -1
  949. package/dist/object-cache-71tPfV4A.mjs.map +0 -1
  950. package/dist/options--hhz-jZ1.d.mts.map +0 -1
  951. package/dist/placeholder-Dp0K3RkD.d.mts.map +0 -1
  952. package/dist/redirects-DTDHWH31.mjs.map +0 -1
  953. package/dist/registry-Cqa2I749.mjs.map +0 -1
  954. package/dist/relations-BBApI4e2.mjs.map +0 -1
  955. package/dist/relations-BHo5A8Zf.d.mts.map +0 -1
  956. package/dist/runner-BYHZn3Jy.d.mts.map +0 -1
  957. package/dist/runner-C1T11CfC.mjs.map +0 -1
  958. package/dist/settings-xRdoUZr0.mjs.map +0 -1
  959. package/dist/state-DYwPue40.mjs.map +0 -1
  960. package/dist/taxonomies-BlrncHi9.mjs.map +0 -1
  961. package/dist/taxonomies-OHUIiIpI.mjs.map +0 -1
  962. package/dist/types-BcqdcT-r.d.mts.map +0 -1
  963. package/dist/types-C2pMvO62.d.mts.map +0 -1
  964. package/dist/types-CP1CflWf.mjs +0 -3
  965. package/dist/types-DN64_zzZ.d.mts.map +0 -1
  966. package/dist/types-DQIDRKF2.d.mts.map +0 -1
  967. package/dist/version-DB_fqCSI.mjs +0 -7
  968. package/dist/widgets-BD3ho7Rq.mjs.map +0 -1
  969. package/dist/zod-generator-LC-on_Vb.mjs.map +0 -1
  970. /package/dist/{api-tokens-rIXC6LdE.mjs → api-tokens-BfYts-sq.mjs} +0 -0
  971. /package/dist/{ssrf-DpXgKsna.mjs → ssrf-Dg3cIT-b.mjs} +0 -0
@@ -1,57 +1,23 @@
1
- import "../../../../../../dialect-helpers-BSbfaO3F.mjs";
2
- import "../../../../../../config-C3EBstHi.mjs";
3
- import "../../../../../../after-CBU2vkoO.mjs";
4
- import "../../../../../../object-cache-71tPfV4A.mjs";
5
- import "../../../../../../content-ZHCc1ngN.mjs";
6
- import "../../../../../../slugify-B994zkXC.mjs";
7
1
  import "../../../../../../base64-CvLhUKQv.mjs";
8
2
  import "../../../../../../types-CQPWhPxE.mjs";
9
- import "../../../../../../media-CzhAn2--.mjs";
10
- import "../../../../../../user-DJZfUJVE.mjs";
11
- import "../../../../../../taxonomy-BqCZ1TdU.mjs";
12
- import "../../../../../../comment-Dxlep6cE.mjs";
13
- import "../../../../../../options-CBXIHUoT.mjs";
14
- import "../../../../../../menus-TCNSd2vp.mjs";
15
- import "../../../../../../redirect-COsS6SWJ.mjs";
16
- import "../../../../../../request-cache-BSUptuJR.mjs";
17
- import "../../../../../../byline-registry-DDun8sxh.mjs";
18
- import "../../../../../../field-defs-cache-BzwBlJrR.mjs";
19
- import "../../../../../../byline-yjvWq4ip.mjs";
20
- import "../../../../../../seo-Dq4G-RrO.mjs";
21
- import "../../../../../../cache-C46-3Irl.mjs";
22
- import "../../../../../../fts-manager-DyZEohZC.mjs";
23
- import "../../../../../../resolve-DOhVEvty.mjs";
24
- import "../../../../../../loader-CdG_Ci3H.mjs";
25
- import "../../../../../../taxonomies-BlrncHi9.mjs";
26
- import { c as validateAggregatorUrl, o as coerceRegistryConfig, t as assertSafeArtifactUrl } from "../../../../../../api-BeBglVxU.mjs";
27
- import "../../../../../../dashboard-DvHbk_cv.mjs";
28
- import "../../../../../../hash-Cg0TXJPV.mjs";
29
- import "../../../../../../content-refresh-B_8SJzuU.mjs";
30
- import "../../../../../../media-usage-work-DrCbqBcl.mjs";
31
- import "../../../../../../media-usage-BZCydfvu.mjs";
32
- import "../../../../../../collection-deletion-DQPvMD8R.mjs";
33
- import "../../../../../../media-usage-work-CLo_6tct.mjs";
34
- import "../../../../../../registry-Cqa2I749.mjs";
35
- import "../../../../../../query-BWs7O5Il.mjs";
36
- import "../../../../../../zod-generator-LC-on_Vb.mjs";
37
- import "../../../../../../schema-DZ5YVVZj.mjs";
38
- import "../../../../../../schema-2AOsSn2v.mjs";
39
- import "../../../../../../seo-AFpVvTqr.mjs";
40
- import "../../../../../../sections-DmHviGyM.mjs";
41
- import "../../../../../../settings-xRdoUZr0.mjs";
42
- import "../../../../../../settings-DE9xtzqd.mjs";
43
- import "../../../../../../taxonomies-OHUIiIpI.mjs";
44
- import "../../../../../../manifest-schema-BXbUAHod.mjs";
45
- import "../../../../../../types-CP1CflWf.mjs";
46
- import "../../../../../../ssrf-Cpvg_n3A.mjs";
47
- import { t as apiError } from "../../../../../../error-DupyJZE2.mjs";
48
- import "../../../../../../parse-DFbuc-Fh.mjs";
49
- import "../../../../../../media-BWWWb8kg.mjs";
50
- import "../../../../../../redirects-DTDHWH31.mjs";
51
- import "../../../../../../relations-BBApI4e2.mjs";
52
- import "../../../../../../status-CWVYpbD8.mjs";
53
- import { r as requirePerm } from "../../../../../../authorize-DUElxgOQ.mjs";
3
+ import { d as fetchVerifiedResource, l as recordScopedImageCacheUrl, m as verifyMultihash, n as coerceRegistryConfig, o as validateAggregatorUrl, p as multihashFromBlobCid, s as fetchRegistryArtifactUrl, u as resolvePublisherPdsEndpoint } from "../../../../../../config-it29yDLA.mjs";
4
+ import { i as resolveAndValidateExternalUrlTarget } from "../../../../../../ssrf-5sIM5jzl.mjs";
5
+ import { t as apiError } from "../../../../../../error-DFrQjppn.mjs";
6
+ import { r as requirePerm } from "../../../../../../authorize-Bkf_UHhD.mjs";
7
+ import { evaluateRegistryReleaseWithdrawal } from "@emdash-cms/registry-client/withdrawal";
8
+ import { NSID, RECORD_SCOPED_BLOB_CACHE_TYPE } from "@emdash-cms/registry-lexicons";
54
9
 
10
+ //#region src/registry/artifact-checksum.ts
11
+ const SHA256_HEX_PATTERN = /^[0-9a-fA-F]{64}$/;
12
+ async function verifyRegistryArtifactChecksum(bytes, checksum) {
13
+ if (SHA256_HEX_PATTERN.test(checksum)) {
14
+ const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", Uint8Array.from(bytes)));
15
+ return Array.from(digest, (byte) => byte.toString(16).padStart(2, "0")).join("") === checksum.toLowerCase();
16
+ }
17
+ return (await verifyMultihash(bytes, checksum)).success;
18
+ }
19
+
20
+ //#endregion
55
21
  //#region src/astro/routes/api/admin/plugins/registry/artifact.ts
56
22
  const prerender = false;
57
23
  /**
@@ -61,14 +27,12 @@ const prerender = false;
61
27
  * executes when navigated to as a top-level document), and the publisher
62
28
  * supplies the bytes. Rather than serve it behind mitigations, we refuse it
63
29
  * end-to-end — the publish CLI rejects SVG artifacts too, so a conforming
64
- * release never references one. AVIF is included.
30
+ * release never references one.
65
31
  */
66
32
  const ALLOWED_IMAGE_TYPES = new Set([
67
33
  "image/png",
68
34
  "image/jpeg",
69
- "image/webp",
70
- "image/gif",
71
- "image/avif"
35
+ "image/webp"
72
36
  ]);
73
37
  /** Artifact kinds the proxy can resolve. `screenshot` additionally needs `index`. */
74
38
  const ALLOWED_KINDS = new Set([
@@ -80,10 +44,11 @@ const ALLOWED_KINDS = new Set([
80
44
  const DID_PATTERN = /^did:[a-z]+:.+/;
81
45
  /** Slug grammar: ASCII letter then letters / digits / `-` / `_`. Mirrors the install route. */
82
46
  const SLUG_PATTERN = /^[a-zA-Z][a-zA-Z0-9_-]*$/;
47
+ const CID_PATTERN = /^b[a-z2-7]+$/;
83
48
  /** Non-negative integer, for the screenshot index param. */
84
49
  const INDEX_PATTERN = /^\d+$/;
85
50
  /** Cap proxied images so a hostile host can't stream an unbounded body. */
86
- const MAX_IMAGE_BYTES = 5 * 1024 * 1024;
51
+ const MAX_IMAGE_BYTES = 1024 * 1024;
87
52
  /** Redirect hops to follow, re-validating each target against SSRF rules. */
88
53
  const MAX_REDIRECTS = 5;
89
54
  /** Wall-clock budget covering connect + headers + body for the artifact fetch. */
@@ -113,35 +78,48 @@ function timedFetch(totalDeadline) {
113
78
  });
114
79
  };
115
80
  }
116
- /**
117
- * Narrow one entry of a release's `artifacts` map to a usable image URL.
118
- *
119
- * The embedded `release` record is lexicon-validated at the DiscoveryClient
120
- * boundary, but `artifacts` is an aggregator pass-through typed `unknown`, so
121
- * the entry's shape is not guaranteed. Returns the `url` string only when the
122
- * value is an object carrying a non-empty string `url`; everything else
123
- * (missing key, wrong type, no `url`) yields `null`.
124
- */
125
- function declaredArtifactUrl(value) {
81
+ function declaredArtifact(value) {
126
82
  if (!value || typeof value !== "object") return null;
127
- const url = value.url;
128
- if (typeof url !== "string" || url.length === 0) return null;
129
- return url;
83
+ const entry = value;
84
+ const url = entry.url;
85
+ const blob = entry.blob;
86
+ const checksum = entry.checksum;
87
+ const blobCid = objectProperty(objectProperty(blob, "ref"), "$link");
88
+ const blobMimeType = objectProperty(blob, "mimeType");
89
+ const blobSize = objectProperty(blob, "size");
90
+ const hasUrl = typeof url === "string" && url.length > 0;
91
+ const hasBlob = typeof blobCid === "string" && blobCid.length > 0 && typeof blobMimeType === "string" && Number.isSafeInteger(blobSize) && Number(blobSize) >= 0;
92
+ if (!hasUrl && !hasBlob || typeof checksum !== "string" || checksum.length === 0) return null;
93
+ return {
94
+ ...hasUrl ? { url } : {},
95
+ ...hasBlob ? { blob: {
96
+ $type: "blob",
97
+ ref: { $link: blobCid },
98
+ mimeType: blobMimeType,
99
+ size: Number(blobSize)
100
+ } } : {},
101
+ checksum,
102
+ requiresAuth: entry.requiresAuth === true
103
+ };
130
104
  }
131
105
  /**
132
- * Resolve the declared artifact URL for `(kind, index)` from a release's
106
+ * Resolve the declared artifact source for `(kind, index)` from a release's
133
107
  * `artifacts` map. Returns `null` when the requested artifact isn't present
134
108
  * or doesn't carry a usable URL.
135
109
  */
136
- function resolveDeclaredUrl(artifacts, kind, index) {
110
+ function resolveDeclaredArtifact(artifacts, kind, index) {
137
111
  if (!artifacts || typeof artifacts !== "object") return null;
138
112
  const map = artifacts;
139
- if (kind === "icon") return declaredArtifactUrl(map.icon);
140
- if (kind === "banner") return declaredArtifactUrl(map.banner);
113
+ if (kind === "icon") return declaredArtifact(map.icon);
114
+ if (kind === "banner") return declaredArtifact(map.banner);
141
115
  const screenshots = map.screenshots;
142
116
  if (!Array.isArray(screenshots)) return null;
143
117
  if (index < 0 || index >= screenshots.length) return null;
144
- return declaredArtifactUrl(screenshots[index]);
118
+ return declaredArtifact(screenshots[index]);
119
+ }
120
+ function objectProperty(value, key) {
121
+ if (!value || typeof value !== "object") return void 0;
122
+ return Object.getOwnPropertyDescriptor(value, key)?.value;
145
123
  }
146
124
  const GET = async ({ url, locals }) => {
147
125
  const { emdash, user } = locals;
@@ -150,12 +128,14 @@ const GET = async ({ url, locals }) => {
150
128
  if (denied) return denied;
151
129
  const did = url.searchParams.get("did");
152
130
  const slug = url.searchParams.get("slug");
131
+ const cid = url.searchParams.get("cid");
153
132
  const kind = url.searchParams.get("kind");
154
133
  const versionParam = url.searchParams.get("version");
155
134
  const indexParam = url.searchParams.get("index");
156
- if (!did || !slug || !kind) return apiError("INVALID_REQUEST", "Missing did, slug, or kind", 400);
135
+ if (!did || !slug || !cid || !kind) return apiError("INVALID_REQUEST", "Missing did, slug, cid, or kind", 400);
157
136
  if (did.length > 256 || !DID_PATTERN.test(did)) return apiError("INVALID_REQUEST", "Invalid did", 400);
158
137
  if (slug.length > 64 || !SLUG_PATTERN.test(slug)) return apiError("INVALID_REQUEST", "Invalid slug", 400);
138
+ if (cid.length > 256 || !CID_PATTERN.test(cid)) return apiError("INVALID_REQUEST", "Invalid release CID", 400);
159
139
  if (!ALLOWED_KINDS.has(kind)) return apiError("INVALID_REQUEST", "Invalid kind", 400);
160
140
  let index = 0;
161
141
  if (kind === "screenshot") {
@@ -176,51 +156,43 @@ const GET = async ({ url, locals }) => {
176
156
  } catch {
177
157
  return apiError("REGISTRY_NOT_CONFIGURED", "Registry aggregator URL is invalid", 500);
178
158
  }
179
- let declaredUrl;
159
+ let resolvedArtifact;
180
160
  try {
181
- const resolved = await resolveArtifactUrl(registryConfig, did, slug, version, kind, index);
161
+ const resolved = await resolveArtifact(registryConfig, did, slug, version, cid, kind, index);
182
162
  if (resolved === null) return apiError("ARTIFACT_NOT_FOUND", "Artifact not found", 404);
183
- declaredUrl = resolved;
163
+ resolvedArtifact = resolved;
184
164
  } catch {
185
165
  return apiError("ARTIFACT_RESOLVE_FAILED", "Failed to resolve artifact", 502);
186
166
  }
187
167
  const controller = new AbortController();
188
168
  const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
189
169
  try {
190
- let current;
191
- try {
192
- current = await assertSafeArtifactUrl(declaredUrl);
193
- } catch {
194
- return apiError("ARTIFACT_URL_REJECTED", "Artifact URL is not allowed", 400);
195
- }
196
- let response;
197
- for (let hop = 0;; hop++) {
198
- response = await fetch(current.href, {
199
- redirect: "manual",
200
- signal: controller.signal
201
- });
202
- if (response.status < 300 || response.status >= 400) break;
203
- const location = response.headers.get("location");
204
- if (!location) break;
205
- if (hop === MAX_REDIRECTS) return apiError("ARTIFACT_URL_REJECTED", "Too many redirects", 502);
206
- let next;
207
- try {
208
- next = await assertSafeArtifactUrl(new URL(location, current).href);
209
- } catch {
210
- return apiError("ARTIFACT_URL_REJECTED", "Redirect target is not allowed", 400);
170
+ const fetchOptions = proxyFetchOptions(controller.signal);
171
+ let bytes;
172
+ let headers;
173
+ let checksumValid;
174
+ if (resolvedArtifact.imageCacheUrl) {
175
+ const transformed = await fetchVerifiedResource(resolvedArtifact.imageCacheUrl, fetchOptions);
176
+ if (transformed.success) {
177
+ bytes = transformed.value.bytes;
178
+ headers = transformed.value.headers;
211
179
  }
212
- current = next;
213
180
  }
214
- if (!response.ok) return apiError("ARTIFACT_FETCH_FAILED", "Failed to fetch artifact", 502);
215
- const contentType = (response.headers.get("content-type") ?? "").split(";", 1)[0].trim().toLowerCase();
181
+ if (!bytes || !headers) {
182
+ const raw = await fetchRawArtifact(resolvedArtifact, fetchOptions);
183
+ if (!raw.success) return artifactFetchError(raw.code);
184
+ bytes = raw.bytes;
185
+ headers = raw.headers;
186
+ checksumValid = raw.checksumValid;
187
+ }
188
+ const contentType = (headers.get("content-type") ?? "").split(";", 1)[0].trim().toLowerCase();
216
189
  if (!ALLOWED_IMAGE_TYPES.has(contentType)) return apiError("ARTIFACT_NOT_IMAGE", "Artifact is not an allowed image type", 415);
217
- const declaredLength = response.headers.get("content-length");
190
+ const declaredLength = headers.get("content-length");
218
191
  if (declaredLength) {
219
192
  const declared = Number(declaredLength);
220
193
  if (Number.isFinite(declared) && declared > MAX_IMAGE_BYTES) return apiError("ARTIFACT_TOO_LARGE", "Artifact exceeds size limit", 413);
221
194
  }
222
- const bytes = await readCapped(response, MAX_IMAGE_BYTES);
223
- if (bytes === null) return apiError("ARTIFACT_TOO_LARGE", "Artifact exceeds size limit", 413);
195
+ if (checksumValid === false) return artifactFetchError("CHECKSUM_MISMATCH");
224
196
  return new Response(bytes, { headers: {
225
197
  "Content-Type": contentType,
226
198
  "Cache-Control": "private, no-store",
@@ -243,12 +215,13 @@ const GET = async ({ url, locals }) => {
243
215
  * left untouched, so a small amount of resolution-pattern duplication is
244
216
  * accepted here.
245
217
  */
246
- async function resolveArtifactUrl(registryConfig, did, slug, version, kind, index) {
247
- const { DiscoveryClient } = await import("@emdash-cms/registry-client/discovery");
218
+ async function resolveArtifact(registryConfig, did, slug, version, cid, kind, index) {
219
+ const { DiscoveryClient, registryLabelerPolicy } = await import("@emdash-cms/registry-client/discovery");
248
220
  const aggregatorDeadline = Date.now() + AGGREGATOR_TOTAL_BUDGET_MS;
249
221
  const discovery = new DiscoveryClient({
250
222
  aggregatorUrl: registryConfig.aggregatorUrl,
251
223
  acceptLabelers: registryConfig.acceptLabelers,
224
+ labelerPolicy: registryLabelerPolicy(registryConfig.acceptLabelers),
252
225
  fetch: timedFetch(aggregatorDeadline)
253
226
  });
254
227
  const publisherDid = did;
@@ -275,42 +248,109 @@ async function resolveArtifactUrl(registryConfig, did, slug, version, kind, inde
275
248
  cursor = result.cursor;
276
249
  }
277
250
  })();
278
- if (!releaseView?.release) return null;
279
- return resolveDeclaredUrl(releaseView.release.artifacts, kind, index);
251
+ if (!releaseView?.release || releaseView.cid !== cid || releaseView.did !== publisherDid || releaseView.package !== slug || version !== void 0 && releaseView.version !== version || releaseView.release.package !== slug || releaseView.release.version !== releaseView.version) return null;
252
+ if (evaluateRegistryReleaseWithdrawal(releaseView, discovery.labelerPolicy).withdrawn) return null;
253
+ const descriptor = resolveDeclaredArtifact(releaseView.release.artifacts, kind, index);
254
+ if (!descriptor || descriptor.requiresAuth || releaseView.release.auth !== void 0) return null;
255
+ const blobCid = descriptor.blob?.ref.$link;
256
+ let imageCacheUrl;
257
+ if (blobCid) {
258
+ const expected = multihashFromBlobCid(blobCid);
259
+ if (!expected.success || expected.value !== descriptor.checksum) return null;
260
+ const rkey = `${slug}:${releaseView.version}`;
261
+ const serviceEndpoint = releaseView.artifactCaches.map(recordScopedCacheEndpoint).find((value) => value !== null);
262
+ if (serviceEndpoint) {
263
+ const cacheUrl = recordScopedImageCacheUrl(serviceEndpoint, kind === "icon" ? "avatar" : kind === "banner" ? "banner" : "feed_thumbnail", {
264
+ did,
265
+ collection: NSID.packageRelease,
266
+ rkey,
267
+ cid: releaseView.cid
268
+ }, blobCid);
269
+ if (!cacheUrl.success) return null;
270
+ imageCacheUrl = cacheUrl.value;
271
+ }
272
+ }
273
+ return {
274
+ artifact: descriptor,
275
+ record: {
276
+ did,
277
+ collection: NSID.packageRelease,
278
+ rkey: `${slug}:${releaseView.version}`,
279
+ cid: releaseView.cid
280
+ },
281
+ ...imageCacheUrl ? { imageCacheUrl } : {}
282
+ };
280
283
  }
281
- /**
282
- * Read a response body into memory, aborting once it exceeds `limit`. Returns
283
- * `null` when the cap is breached (the streamed body lied about / omitted
284
- * Content-Length). The cap is the real defence against an unbounded body.
285
- */
286
- async function readCapped(response, limit) {
287
- const body = response.body;
288
- if (!body) {
289
- const buf = new Uint8Array(await response.arrayBuffer());
290
- return buf.length > limit ? null : buf;
284
+ function recordScopedCacheEndpoint(value) {
285
+ if (objectProperty(value, "$type") !== RECORD_SCOPED_BLOB_CACHE_TYPE) return null;
286
+ const endpoint = objectProperty(value, "serviceEndpoint");
287
+ return typeof endpoint === "string" ? endpoint : null;
288
+ }
289
+ /** Build bounded, SSRF-validated fetch options for cache, PDS, and URL sources. */
290
+ function proxyFetchOptions(signal) {
291
+ return {
292
+ fetch: async (url, init) => fetchRegistryArtifactUrl(url.href, {
293
+ signal: init.signal instanceof AbortSignal ? init.signal : signal,
294
+ maxResponseBytes: MAX_IMAGE_BYTES
295
+ }),
296
+ resolveHostname: async (hostname) => (await resolveAndValidateExternalUrlTarget(`https://${hostname}/`)).addresses,
297
+ allowHttpLocalhost: import.meta.env.DEV,
298
+ maxBytes: MAX_IMAGE_BYTES,
299
+ maxRedirects: MAX_REDIRECTS,
300
+ totalTimeoutMs: FETCH_TIMEOUT_MS
301
+ };
302
+ }
303
+ async function fetchRawArtifact(resolved, options) {
304
+ const urls = [];
305
+ const blobCid = resolved.artifact.blob?.ref.$link;
306
+ let lastCode = "FETCH_FAILED";
307
+ let checksumMismatch;
308
+ if (blobCid) {
309
+ const pds = await resolvePublisherPdsEndpoint(resolved.record.did, options);
310
+ if (pds.success) {
311
+ const url = new URL("/xrpc/com.atproto.sync.getBlob", pds.value);
312
+ url.searchParams.set("did", resolved.record.did);
313
+ url.searchParams.set("cid", blobCid);
314
+ urls.push(url);
315
+ } else lastCode = pds.error.code;
291
316
  }
292
- const reader = body.getReader();
293
- const chunks = [];
294
- let total = 0;
295
- while (true) {
296
- const { done, value } = await reader.read();
297
- if (done) break;
298
- if (value) {
299
- total += value.length;
300
- if (total > limit) {
301
- await reader.cancel();
302
- return null;
303
- }
304
- chunks.push(value);
317
+ if (resolved.artifact.url) urls.push(new URL(resolved.artifact.url));
318
+ for (const url of urls) {
319
+ const fetched = await fetchVerifiedResource(url, options);
320
+ if (!fetched.success) {
321
+ lastCode = fetched.error.code;
322
+ continue;
305
323
  }
324
+ if (!await verifyRegistryArtifactChecksum(fetched.value.bytes, resolved.artifact.checksum)) {
325
+ lastCode = "CHECKSUM_MISMATCH";
326
+ checksumMismatch = {
327
+ bytes: fetched.value.bytes,
328
+ headers: fetched.value.headers
329
+ };
330
+ continue;
331
+ }
332
+ return {
333
+ success: true,
334
+ bytes: fetched.value.bytes,
335
+ headers: fetched.value.headers,
336
+ checksumValid: true
337
+ };
306
338
  }
307
- const combined = new Uint8Array(total);
308
- let offset = 0;
309
- for (const chunk of chunks) {
310
- combined.set(chunk, offset);
311
- offset += chunk.length;
312
- }
313
- return combined;
339
+ if (checksumMismatch) return {
340
+ success: true,
341
+ ...checksumMismatch,
342
+ checksumValid: false
343
+ };
344
+ return {
345
+ success: false,
346
+ code: lastCode
347
+ };
348
+ }
349
+ function artifactFetchError(code) {
350
+ if (code === "CHECKSUM_MISMATCH") return apiError("ARTIFACT_CHECKSUM_MISMATCH", "Artifact bytes do not match the approved release record", 502);
351
+ if (code === "RESOURCE_SIZE_EXCEEDED") return apiError("ARTIFACT_TOO_LARGE", "Artifact exceeds size limit", 413);
352
+ if (code === "HOST_REJECTED" || code === "INVALID_URL") return apiError("ARTIFACT_URL_REJECTED", "Artifact URL is not allowed", 400);
353
+ return apiError("ARTIFACT_FETCH_FAILED", "Failed to fetch artifact", 502);
314
354
  }
315
355
 
316
356
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"artifact.mjs","names":[],"sources":["../../../../../../../src/astro/routes/api/admin/plugins/registry/artifact.ts"],"sourcesContent":["/**\n * Registry artifact proxy\n *\n * GET /_emdash/api/admin/plugins/registry/artifact?did=&slug=&version=&kind=&index=\n *\n * Proxies an icon / screenshot / banner image referenced by a registry\n * release record so the admin UI can display it without cross-origin\n * requests to arbitrary publisher hosting.\n *\n * Trust model (CRITICAL): the proxy never accepts an artifact URL from the\n * client. The caller addresses an artifact by its coordinates\n * `(did, slug, version, kind, index)`; the server resolves the *declared*\n * URL from the validated release record fetched from the configured\n * aggregator. The proxy can therefore only ever fetch a URL the publisher\n * declared in their signed release — not an arbitrary caller-supplied URL.\n *\n * The publisher-declared URL is still untrusted (an attacker who controls a\n * publisher record, or the aggregator, can point it anywhere), so the\n * resolved URL passes through the SSRF defences (`assertSafeArtifactUrl`,\n * re-validated on every redirect hop) before any fetch, and only allowlisted\n * image content types are served back.\n */\n\nimport type { Did } from \"@atcute/lexicons\";\nimport type { APIRoute } from \"astro\";\n\nimport { requirePerm } from \"#api/authorize.js\";\nimport { apiError } from \"#api/error.js\";\nimport { assertSafeArtifactUrl } from \"#api/index.js\";\n\nimport { coerceRegistryConfig, validateAggregatorUrl } from \"../../../../../../registry/config.js\";\n\nexport const prerender = false;\n\n/**\n * Image content types the proxy will pass through. Anything else is rejected.\n *\n * SVG is deliberately excluded: it is active content (an `<svg><script>`\n * executes when navigated to as a top-level document), and the publisher\n * supplies the bytes. Rather than serve it behind mitigations, we refuse it\n * end-to-end — the publish CLI rejects SVG artifacts too, so a conforming\n * release never references one. AVIF is included.\n */\nconst ALLOWED_IMAGE_TYPES = new Set([\n\t\"image/png\",\n\t\"image/jpeg\",\n\t\"image/webp\",\n\t\"image/gif\",\n\t\"image/avif\",\n]);\n\n/** Artifact kinds the proxy can resolve. `screenshot` additionally needs `index`. */\nconst ALLOWED_KINDS = new Set([\"icon\", \"banner\", \"screenshot\"]);\n\n/** Loose DID shape (`did:method:id`); the aggregator lexicon is authoritative. */\nconst DID_PATTERN = /^did:[a-z]+:.+/;\n/** Slug grammar: ASCII letter then letters / digits / `-` / `_`. Mirrors the install route. */\nconst SLUG_PATTERN = /^[a-zA-Z][a-zA-Z0-9_-]*$/;\n/** Non-negative integer, for the screenshot index param. */\nconst INDEX_PATTERN = /^\\d+$/;\n\n/** Cap proxied images so a hostile host can't stream an unbounded body. */\nconst MAX_IMAGE_BYTES = 5 * 1024 * 1024;\n\n/** Redirect hops to follow, re-validating each target against SSRF rules. */\nconst MAX_REDIRECTS = 5;\n\n/** Wall-clock budget covering connect + headers + body for the artifact fetch. */\nconst FETCH_TIMEOUT_MS = 15_000;\n\n/** Per-aggregator-request timeout and overall budget for release resolution. */\nconst AGGREGATOR_REQUEST_TIMEOUT_MS = 15_000;\nconst AGGREGATOR_TOTAL_BUDGET_MS = 30_000;\n\n/** Bound the version search: 20 pages * 50 per page = 1000 releases worth. */\nconst MAX_LIST_PAGES = 20;\n\n/** Build a fetch that enforces a per-request and per-budget timeout. Mirrors the install handler. */\nfunction timedFetch(totalDeadline: number): typeof fetch {\n\treturn (input: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]) => {\n\t\tconst now = Date.now();\n\t\tconst remaining = Math.max(0, totalDeadline - now);\n\t\tif (remaining === 0) {\n\t\t\treturn Promise.reject(new Error(\"Aggregator request budget exhausted\"));\n\t\t}\n\t\tconst timeout = Math.min(AGGREGATOR_REQUEST_TIMEOUT_MS, remaining);\n\t\tconst controller = new AbortController();\n\t\tconst timer = setTimeout(() => controller.abort(), timeout);\n\t\tconst callerSignal = init?.signal;\n\t\tif (callerSignal) {\n\t\t\tif (callerSignal.aborted) controller.abort(callerSignal.reason);\n\t\t\telse callerSignal.addEventListener(\"abort\", () => controller.abort(callerSignal.reason));\n\t\t}\n\t\treturn fetch(input, { ...init, signal: controller.signal }).finally(() => {\n\t\t\tclearTimeout(timer);\n\t\t});\n\t};\n}\n\n/**\n * Narrow one entry of a release's `artifacts` map to a usable image URL.\n *\n * The embedded `release` record is lexicon-validated at the DiscoveryClient\n * boundary, but `artifacts` is an aggregator pass-through typed `unknown`, so\n * the entry's shape is not guaranteed. Returns the `url` string only when the\n * value is an object carrying a non-empty string `url`; everything else\n * (missing key, wrong type, no `url`) yields `null`.\n */\nfunction declaredArtifactUrl(value: unknown): string | null {\n\tif (!value || typeof value !== \"object\") return null;\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- narrowed to non-null object above; url checked below\n\tconst entry = value as Record<string, unknown>;\n\tconst url = entry.url;\n\tif (typeof url !== \"string\" || url.length === 0) return null;\n\treturn url;\n}\n\n/**\n * Resolve the declared artifact URL for `(kind, index)` from a release's\n * `artifacts` map. Returns `null` when the requested artifact isn't present\n * or doesn't carry a usable URL.\n */\nfunction resolveDeclaredUrl(artifacts: unknown, kind: string, index: number): string | null {\n\tif (!artifacts || typeof artifacts !== \"object\") return null;\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- narrowed to non-null object above; each entry shape-narrowed by declaredArtifactUrl\n\tconst map = artifacts as Record<string, unknown>;\n\n\tif (kind === \"icon\") return declaredArtifactUrl(map.icon);\n\tif (kind === \"banner\") return declaredArtifactUrl(map.banner);\n\t// kind === \"screenshot\"\n\tconst screenshots = map.screenshots;\n\tif (!Array.isArray(screenshots)) return null;\n\tif (index < 0 || index >= screenshots.length) return null;\n\treturn declaredArtifactUrl(screenshots[index]);\n}\n\nexport const GET: APIRoute = async ({ url, locals }) => {\n\tconst { emdash, user } = locals;\n\n\tif (!emdash?.db) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\n\tconst denied = requirePerm(user, \"plugins:read\");\n\tif (denied) return denied;\n\n\tconst did = url.searchParams.get(\"did\");\n\tconst slug = url.searchParams.get(\"slug\");\n\tconst kind = url.searchParams.get(\"kind\");\n\tconst versionParam = url.searchParams.get(\"version\");\n\tconst indexParam = url.searchParams.get(\"index\");\n\n\tif (!did || !slug || !kind) {\n\t\treturn apiError(\"INVALID_REQUEST\", \"Missing did, slug, or kind\", 400);\n\t}\n\tif (did.length > 256 || !DID_PATTERN.test(did)) {\n\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid did\", 400);\n\t}\n\tif (slug.length > 64 || !SLUG_PATTERN.test(slug)) {\n\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid slug\", 400);\n\t}\n\tif (!ALLOWED_KINDS.has(kind)) {\n\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid kind\", 400);\n\t}\n\n\tlet index = 0;\n\tif (kind === \"screenshot\") {\n\t\tif (indexParam === null) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Missing index for screenshot\", 400);\n\t\t}\n\t\tif (!INDEX_PATTERN.test(indexParam)) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid index\", 400);\n\t\t}\n\t\tindex = Number(indexParam);\n\t\tif (!Number.isSafeInteger(index)) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid index\", 400);\n\t\t}\n\t}\n\n\tlet version: string | undefined;\n\tif (versionParam !== null && versionParam.length > 0) {\n\t\tif (versionParam.length > 64) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid version\", 400);\n\t\t}\n\t\tversion = versionParam;\n\t}\n\n\tconst registryConfig = coerceRegistryConfig(emdash.config.experimental?.registry);\n\tif (!registryConfig) {\n\t\treturn apiError(\"REGISTRY_NOT_CONFIGURED\", \"Registry is not configured\", 400);\n\t}\n\ttry {\n\t\tvalidateAggregatorUrl(registryConfig.aggregatorUrl);\n\t} catch {\n\t\treturn apiError(\"REGISTRY_NOT_CONFIGURED\", \"Registry aggregator URL is invalid\", 500);\n\t}\n\n\t// Resolve the publisher-declared artifact URL from the release record.\n\tlet declaredUrl: string;\n\ttry {\n\t\tconst resolved = await resolveArtifactUrl(registryConfig, did, slug, version, kind, index);\n\t\tif (resolved === null) {\n\t\t\treturn apiError(\"ARTIFACT_NOT_FOUND\", \"Artifact not found\", 404);\n\t\t}\n\t\tdeclaredUrl = resolved;\n\t} catch {\n\t\treturn apiError(\"ARTIFACT_RESOLVE_FAILED\", \"Failed to resolve artifact\", 502);\n\t}\n\n\tconst controller = new AbortController();\n\tconst timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n\ttry {\n\t\t// `assertSafeArtifactUrl` validates scheme / credentials / loopback +\n\t\t// resolves the hostname and rejects private / link-local / metadata\n\t\t// targets (DNS-rebinding defence). It throws a plain Error on any\n\t\t// block, so a rejection here means the URL is unsafe.\n\t\tlet current: URL;\n\t\ttry {\n\t\t\tcurrent = await assertSafeArtifactUrl(declaredUrl);\n\t\t} catch {\n\t\t\treturn apiError(\"ARTIFACT_URL_REJECTED\", \"Artifact URL is not allowed\", 400);\n\t\t}\n\n\t\tlet response: Response;\n\t\tfor (let hop = 0; ; hop++) {\n\t\t\tresponse = await fetch(current.href, { redirect: \"manual\", signal: controller.signal });\n\t\t\tif (response.status < 300 || response.status >= 400) break;\n\t\t\tconst location = response.headers.get(\"location\");\n\t\t\tif (!location) break;\n\t\t\tif (hop === MAX_REDIRECTS) {\n\t\t\t\treturn apiError(\"ARTIFACT_URL_REJECTED\", \"Too many redirects\", 502);\n\t\t\t}\n\t\t\tlet next: URL;\n\t\t\ttry {\n\t\t\t\tnext = await assertSafeArtifactUrl(new URL(location, current).href);\n\t\t\t} catch {\n\t\t\t\treturn apiError(\"ARTIFACT_URL_REJECTED\", \"Redirect target is not allowed\", 400);\n\t\t\t}\n\t\t\tcurrent = next;\n\t\t}\n\n\t\tif (!response.ok) {\n\t\t\treturn apiError(\"ARTIFACT_FETCH_FAILED\", \"Failed to fetch artifact\", 502);\n\t\t}\n\n\t\t// Content-Type allowlist: only image types are proxied. A non-image\n\t\t// (HTML error page, JSON, octet-stream) is rejected so the admin\n\t\t// never renders publisher-controlled markup from the EmDash origin.\n\t\tconst rawType = response.headers.get(\"content-type\") ?? \"\";\n\t\tconst contentType = rawType.split(\";\", 1)[0]!.trim().toLowerCase();\n\t\tif (!ALLOWED_IMAGE_TYPES.has(contentType)) {\n\t\t\treturn apiError(\"ARTIFACT_NOT_IMAGE\", \"Artifact is not an allowed image type\", 415);\n\t\t}\n\n\t\tconst declaredLength = response.headers.get(\"content-length\");\n\t\tif (declaredLength) {\n\t\t\tconst declared = Number(declaredLength);\n\t\t\tif (Number.isFinite(declared) && declared > MAX_IMAGE_BYTES) {\n\t\t\t\treturn apiError(\"ARTIFACT_TOO_LARGE\", \"Artifact exceeds size limit\", 413);\n\t\t\t}\n\t\t}\n\n\t\tconst bytes = await readCapped(response, MAX_IMAGE_BYTES);\n\t\tif (bytes === null) {\n\t\t\treturn apiError(\"ARTIFACT_TOO_LARGE\", \"Artifact exceeds size limit\", 413);\n\t\t}\n\n\t\t// Only the allowlisted Content-Type is forwarded — never copy other\n\t\t// upstream headers. `private, no-store` keeps publisher images out of\n\t\t// shared caches in the authenticated admin origin.\n\t\t//\n\t\t// SVG is not in the allowlist, so active-content bytes never reach\n\t\t// here. `Content-Disposition: attachment`, the sandbox CSP, and\n\t\t// `nosniff` remain as defence-in-depth: they force a download and\n\t\t// neutralise script/plugins for any image type if a client navigates\n\t\t// directly to the proxy URL.\n\t\treturn new Response(bytes, {\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": contentType,\n\t\t\t\t\"Cache-Control\": \"private, no-store\",\n\t\t\t\t\"X-Content-Type-Options\": \"nosniff\",\n\t\t\t\t\"Content-Disposition\": \"attachment\",\n\t\t\t\t\"Content-Security-Policy\": \"default-src 'none'; sandbox\",\n\t\t\t},\n\t\t});\n\t} catch {\n\t\treturn apiError(\"ARTIFACT_FETCH_FAILED\", \"Failed to fetch artifact\", 502);\n\t} finally {\n\t\tclearTimeout(timer);\n\t}\n};\n\n/**\n * Resolve the declared artifact URL for `(did, slug, version, kind, index)`\n * from the aggregator's release record. Mirrors the install handler's release\n * lookup. Returns `null` when the package/release/artifact isn't found.\n *\n * Self-contained to this route: the install/update handlers are intentionally\n * left untouched, so a small amount of resolution-pattern duplication is\n * accepted here.\n */\nasync function resolveArtifactUrl(\n\tregistryConfig: { aggregatorUrl: string; acceptLabelers?: string },\n\tdid: string,\n\tslug: string,\n\tversion: string | undefined,\n\tkind: string,\n\tindex: number,\n): Promise<string | null> {\n\t// Lazy-load the discovery client so the `@atcute/client` dependency only\n\t// loads when the registry path is exercised.\n\tconst { DiscoveryClient } = await import(\"@emdash-cms/registry-client/discovery\");\n\n\tconst aggregatorDeadline = Date.now() + AGGREGATOR_TOTAL_BUDGET_MS;\n\tconst discovery = new DiscoveryClient({\n\t\taggregatorUrl: registryConfig.aggregatorUrl,\n\t\tacceptLabelers: registryConfig.acceptLabelers,\n\t\tfetch: timedFetch(aggregatorDeadline),\n\t});\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- DID shape validated by the route before this call\n\tconst publisherDid = did as Did;\n\n\tconst releaseView = await (async () => {\n\t\tif (!version) {\n\t\t\treturn discovery.getLatestRelease({ did: publisherDid, package: slug });\n\t\t}\n\t\tlet cursor: string | undefined;\n\t\tconst seenCursors = new Set<string>();\n\t\tfor (let page = 0; page < MAX_LIST_PAGES; page++) {\n\t\t\tif (cursor !== undefined) {\n\t\t\t\tif (seenCursors.has(cursor)) break;\n\t\t\t\tseenCursors.add(cursor);\n\t\t\t}\n\t\t\tconst result = await discovery.listReleases({\n\t\t\t\tdid: publisherDid,\n\t\t\t\tpackage: slug,\n\t\t\t\tcursor,\n\t\t\t\tlimit: 50,\n\t\t\t});\n\t\t\tfor (const r of result.releases) {\n\t\t\t\tif (r.version === version) return r;\n\t\t\t}\n\t\t\tif (!result.cursor) break;\n\t\t\tcursor = result.cursor;\n\t\t}\n\t\treturn undefined;\n\t})();\n\n\tif (!releaseView?.release) return null;\n\n\treturn resolveDeclaredUrl(releaseView.release.artifacts, kind, index);\n}\n\n/**\n * Read a response body into memory, aborting once it exceeds `limit`. Returns\n * `null` when the cap is breached (the streamed body lied about / omitted\n * Content-Length). The cap is the real defence against an unbounded body.\n */\nasync function readCapped(response: Response, limit: number): Promise<Uint8Array | null> {\n\tconst body = response.body;\n\tif (!body) {\n\t\tconst buf = new Uint8Array(await response.arrayBuffer());\n\t\treturn buf.length > limit ? null : buf;\n\t}\n\tconst reader = body.getReader();\n\tconst chunks: Uint8Array[] = [];\n\tlet total = 0;\n\twhile (true) {\n\t\tconst { done, value } = await reader.read();\n\t\tif (done) break;\n\t\tif (value) {\n\t\t\ttotal += value.length;\n\t\t\tif (total > limit) {\n\t\t\t\tawait reader.cancel();\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tchunks.push(value);\n\t\t}\n\t}\n\tconst combined = new Uint8Array(total);\n\tlet offset = 0;\n\tfor (const chunk of chunks) {\n\t\tcombined.set(chunk, offset);\n\t\toffset += chunk.length;\n\t}\n\treturn combined;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"artifact.mjs","names":[],"sources":["../../../../../../../src/registry/artifact-checksum.ts","../../../../../../../src/astro/routes/api/admin/plugins/registry/artifact.ts"],"sourcesContent":["import { verifyMultihash } from \"@emdash-cms/registry-verification/checksum\";\n\nconst SHA256_HEX_PATTERN = /^[0-9a-fA-F]{64}$/;\n\nexport async function verifyRegistryArtifactChecksum(\n\tbytes: Uint8Array,\n\tchecksum: string,\n): Promise<boolean> {\n\tif (SHA256_HEX_PATTERN.test(checksum)) {\n\t\tconst digest = new Uint8Array(await crypto.subtle.digest(\"SHA-256\", Uint8Array.from(bytes)));\n\t\tconst actual = Array.from(digest, (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n\t\treturn actual === checksum.toLowerCase();\n\t}\n\treturn (await verifyMultihash(bytes, checksum)).success;\n}\n","/**\n * Registry artifact proxy\n *\n * GET /_emdash/api/admin/plugins/registry/artifact?did=&slug=&version=&kind=&index=\n *\n * Proxies an icon / screenshot / banner image referenced by a registry\n * release record so the admin UI can display it without cross-origin\n * requests to arbitrary publisher hosting.\n *\n * Trust model (CRITICAL): the proxy never accepts an artifact URL from the\n * client. The caller addresses an artifact by its coordinates\n * `(did, slug, version, kind, index)`; the server resolves the *declared*\n * artifact source from the validated release record fetched from the\n * configured aggregator. Blob-backed images resolve to the record-scoped\n * Cumulus deployment; URL artifacts retain the external fallback.\n *\n * The publisher-declared URL is still untrusted (an attacker who controls a\n * publisher record, or the aggregator, can point it anywhere), so the\n * resolved URL passes through the SSRF defences (`assertSafeArtifactUrl`,\n * re-validated on every redirect hop) before any fetch, and only allowlisted\n * image content types are served back.\n */\n\nimport type { Did } from \"@atcute/lexicons\";\nimport { evaluateRegistryReleaseWithdrawal } from \"@emdash-cms/registry-client/withdrawal\";\nimport { NSID, RECORD_SCOPED_BLOB_CACHE_TYPE } from \"@emdash-cms/registry-lexicons\";\nimport {\n\trecordScopedImageCacheUrl,\n\tresolvePublisherPdsEndpoint,\n\ttype ReleaseArtifactReference,\n} from \"@emdash-cms/registry-verification/artifact\";\nimport { multihashFromBlobCid } from \"@emdash-cms/registry-verification/checksum\";\nimport { fetchVerifiedResource } from \"@emdash-cms/registry-verification/fetch\";\nimport type { APIRoute } from \"astro\";\n\nimport { requirePerm } from \"#api/authorize.js\";\nimport { apiError } from \"#api/error.js\";\n\nimport { verifyRegistryArtifactChecksum } from \"../../../../../../registry/artifact-checksum.js\";\nimport { fetchRegistryArtifactUrl } from \"../../../../../../registry/artifact-fetch.js\";\nimport { coerceRegistryConfig, validateAggregatorUrl } from \"../../../../../../registry/config.js\";\nimport { resolveAndValidateExternalUrlTarget } from \"../../../../../../security/ssrf.js\";\n\nexport const prerender = false;\n\n/**\n * Image content types the proxy will pass through. Anything else is rejected.\n *\n * SVG is deliberately excluded: it is active content (an `<svg><script>`\n * executes when navigated to as a top-level document), and the publisher\n * supplies the bytes. Rather than serve it behind mitigations, we refuse it\n * end-to-end — the publish CLI rejects SVG artifacts too, so a conforming\n * release never references one.\n */\nconst ALLOWED_IMAGE_TYPES = new Set([\"image/png\", \"image/jpeg\", \"image/webp\"]);\n\n/** Artifact kinds the proxy can resolve. `screenshot` additionally needs `index`. */\nconst ALLOWED_KINDS = new Set([\"icon\", \"banner\", \"screenshot\"]);\n\n/** Loose DID shape (`did:method:id`); the aggregator lexicon is authoritative. */\nconst DID_PATTERN = /^did:[a-z]+:.+/;\n/** Slug grammar: ASCII letter then letters / digits / `-` / `_`. Mirrors the install route. */\nconst SLUG_PATTERN = /^[a-zA-Z][a-zA-Z0-9_-]*$/;\nconst CID_PATTERN = /^b[a-z2-7]+$/;\n/** Non-negative integer, for the screenshot index param. */\nconst INDEX_PATTERN = /^\\d+$/;\n\n/** Cap proxied images so a hostile host can't stream an unbounded body. */\nconst MAX_IMAGE_BYTES = 1024 * 1024;\n\n/** Redirect hops to follow, re-validating each target against SSRF rules. */\nconst MAX_REDIRECTS = 5;\n\n/** Wall-clock budget covering connect + headers + body for the artifact fetch. */\nconst FETCH_TIMEOUT_MS = 15_000;\n\n/** Per-aggregator-request timeout and overall budget for release resolution. */\nconst AGGREGATOR_REQUEST_TIMEOUT_MS = 15_000;\nconst AGGREGATOR_TOTAL_BUDGET_MS = 30_000;\n\n/** Bound the version search: 20 pages * 50 per page = 1000 releases worth. */\nconst MAX_LIST_PAGES = 20;\n\n/** Build a fetch that enforces a per-request and per-budget timeout. Mirrors the install handler. */\nfunction timedFetch(totalDeadline: number): typeof fetch {\n\treturn (input: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]) => {\n\t\tconst now = Date.now();\n\t\tconst remaining = Math.max(0, totalDeadline - now);\n\t\tif (remaining === 0) {\n\t\t\treturn Promise.reject(new Error(\"Aggregator request budget exhausted\"));\n\t\t}\n\t\tconst timeout = Math.min(AGGREGATOR_REQUEST_TIMEOUT_MS, remaining);\n\t\tconst controller = new AbortController();\n\t\tconst timer = setTimeout(() => controller.abort(), timeout);\n\t\tconst callerSignal = init?.signal;\n\t\tif (callerSignal) {\n\t\t\tif (callerSignal.aborted) controller.abort(callerSignal.reason);\n\t\t\telse callerSignal.addEventListener(\"abort\", () => controller.abort(callerSignal.reason));\n\t\t}\n\t\treturn fetch(input, { ...init, signal: controller.signal }).finally(() => {\n\t\t\tclearTimeout(timer);\n\t\t});\n\t};\n}\n\n/**\n * Narrow one entry of a release's `artifacts` map to a usable image source.\n *\n * The embedded `release` record is lexicon-validated at the DiscoveryClient\n * boundary, but `artifacts` is an aggregator pass-through typed `unknown`, so\n * the entry's shape is not guaranteed.\n */\ntype DeclaredArtifact = ReleaseArtifactReference & { requiresAuth: boolean };\n\ninterface ResolvedArtifact {\n\tartifact: DeclaredArtifact;\n\trecord: {\n\t\tdid: string;\n\t\tcollection: string;\n\t\trkey: string;\n\t\tcid: string;\n\t};\n\timageCacheUrl?: URL;\n}\n\nfunction declaredArtifact(value: unknown): DeclaredArtifact | null {\n\tif (!value || typeof value !== \"object\") return null;\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- narrowed to non-null object above; fields checked below\n\tconst entry = value as Record<string, unknown>;\n\tconst url = entry.url;\n\tconst blob = entry.blob;\n\tconst checksum = entry.checksum;\n\tconst ref = objectProperty(blob, \"ref\");\n\tconst blobCid = objectProperty(ref, \"$link\");\n\tconst blobMimeType = objectProperty(blob, \"mimeType\");\n\tconst blobSize = objectProperty(blob, \"size\");\n\tconst hasUrl = typeof url === \"string\" && url.length > 0;\n\tconst hasBlob =\n\t\ttypeof blobCid === \"string\" &&\n\t\tblobCid.length > 0 &&\n\t\ttypeof blobMimeType === \"string\" &&\n\t\tNumber.isSafeInteger(blobSize) &&\n\t\tNumber(blobSize) >= 0;\n\tif ((!hasUrl && !hasBlob) || typeof checksum !== \"string\" || checksum.length === 0) {\n\t\treturn null;\n\t}\n\treturn {\n\t\t...(hasUrl ? { url } : {}),\n\t\t...(hasBlob\n\t\t\t? {\n\t\t\t\t\tblob: {\n\t\t\t\t\t\t$type: \"blob\" as const,\n\t\t\t\t\t\tref: { $link: blobCid },\n\t\t\t\t\t\tmimeType: blobMimeType,\n\t\t\t\t\t\tsize: Number(blobSize),\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {}),\n\t\tchecksum,\n\t\trequiresAuth: entry.requiresAuth === true,\n\t};\n}\n\n/**\n * Resolve the declared artifact source for `(kind, index)` from a release's\n * `artifacts` map. Returns `null` when the requested artifact isn't present\n * or doesn't carry a usable URL.\n */\nfunction resolveDeclaredArtifact(\n\tartifacts: unknown,\n\tkind: string,\n\tindex: number,\n): DeclaredArtifact | null {\n\tif (!artifacts || typeof artifacts !== \"object\") return null;\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- narrowed to non-null object above; each entry shape-narrowed by declaredArtifactUrl\n\tconst map = artifacts as Record<string, unknown>;\n\n\tif (kind === \"icon\") return declaredArtifact(map.icon);\n\tif (kind === \"banner\") return declaredArtifact(map.banner);\n\t// kind === \"screenshot\"\n\tconst screenshots = map.screenshots;\n\tif (!Array.isArray(screenshots)) return null;\n\tif (index < 0 || index >= screenshots.length) return null;\n\treturn declaredArtifact(screenshots[index]);\n}\n\nfunction objectProperty(value: unknown, key: string): unknown {\n\tif (!value || typeof value !== \"object\") return undefined;\n\treturn Object.getOwnPropertyDescriptor(value, key)?.value;\n}\n\nexport const GET: APIRoute = async ({ url, locals }) => {\n\tconst { emdash, user } = locals;\n\n\tif (!emdash?.db) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\n\tconst denied = requirePerm(user, \"plugins:read\");\n\tif (denied) return denied;\n\n\tconst did = url.searchParams.get(\"did\");\n\tconst slug = url.searchParams.get(\"slug\");\n\tconst cid = url.searchParams.get(\"cid\");\n\tconst kind = url.searchParams.get(\"kind\");\n\tconst versionParam = url.searchParams.get(\"version\");\n\tconst indexParam = url.searchParams.get(\"index\");\n\n\tif (!did || !slug || !cid || !kind) {\n\t\treturn apiError(\"INVALID_REQUEST\", \"Missing did, slug, cid, or kind\", 400);\n\t}\n\tif (did.length > 256 || !DID_PATTERN.test(did)) {\n\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid did\", 400);\n\t}\n\tif (slug.length > 64 || !SLUG_PATTERN.test(slug)) {\n\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid slug\", 400);\n\t}\n\tif (cid.length > 256 || !CID_PATTERN.test(cid)) {\n\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid release CID\", 400);\n\t}\n\tif (!ALLOWED_KINDS.has(kind)) {\n\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid kind\", 400);\n\t}\n\n\tlet index = 0;\n\tif (kind === \"screenshot\") {\n\t\tif (indexParam === null) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Missing index for screenshot\", 400);\n\t\t}\n\t\tif (!INDEX_PATTERN.test(indexParam)) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid index\", 400);\n\t\t}\n\t\tindex = Number(indexParam);\n\t\tif (!Number.isSafeInteger(index)) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid index\", 400);\n\t\t}\n\t}\n\n\tlet version: string | undefined;\n\tif (versionParam !== null && versionParam.length > 0) {\n\t\tif (versionParam.length > 64) {\n\t\t\treturn apiError(\"INVALID_REQUEST\", \"Invalid version\", 400);\n\t\t}\n\t\tversion = versionParam;\n\t}\n\n\tconst registryConfig = coerceRegistryConfig(emdash.config.experimental?.registry);\n\tif (!registryConfig) {\n\t\treturn apiError(\"REGISTRY_NOT_CONFIGURED\", \"Registry is not configured\", 400);\n\t}\n\ttry {\n\t\tvalidateAggregatorUrl(registryConfig.aggregatorUrl);\n\t} catch {\n\t\treturn apiError(\"REGISTRY_NOT_CONFIGURED\", \"Registry aggregator URL is invalid\", 500);\n\t}\n\n\t// Resolve the publisher-declared artifact URL from the release record.\n\tlet resolvedArtifact: ResolvedArtifact;\n\ttry {\n\t\tconst resolved = await resolveArtifact(registryConfig, did, slug, version, cid, kind, index);\n\t\tif (resolved === null) {\n\t\t\treturn apiError(\"ARTIFACT_NOT_FOUND\", \"Artifact not found\", 404);\n\t\t}\n\t\tresolvedArtifact = resolved;\n\t} catch {\n\t\treturn apiError(\"ARTIFACT_RESOLVE_FAILED\", \"Failed to resolve artifact\", 502);\n\t}\n\tconst controller = new AbortController();\n\tconst timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n\ttry {\n\t\tconst fetchOptions = proxyFetchOptions(controller.signal);\n\t\tlet bytes: Uint8Array | undefined;\n\t\tlet headers: Headers | undefined;\n\t\tlet checksumValid: boolean | undefined;\n\t\tif (resolvedArtifact.imageCacheUrl) {\n\t\t\tconst transformed = await fetchVerifiedResource(resolvedArtifact.imageCacheUrl, fetchOptions);\n\t\t\tif (transformed.success) {\n\t\t\t\tbytes = transformed.value.bytes;\n\t\t\t\theaders = transformed.value.headers;\n\t\t\t}\n\t\t}\n\t\tif (!bytes || !headers) {\n\t\t\tconst raw = await fetchRawArtifact(resolvedArtifact, fetchOptions);\n\t\t\tif (!raw.success) return artifactFetchError(raw.code);\n\t\t\tbytes = raw.bytes;\n\t\t\theaders = raw.headers;\n\t\t\tchecksumValid = raw.checksumValid;\n\t\t}\n\n\t\t// Content-Type allowlist: only image types are proxied. A non-image\n\t\t// (HTML error page, JSON, octet-stream) is rejected so the admin\n\t\t// never renders publisher-controlled markup from the EmDash origin.\n\t\tconst rawType = headers.get(\"content-type\") ?? \"\";\n\t\tconst contentType = rawType.split(\";\", 1)[0]!.trim().toLowerCase();\n\t\tif (!ALLOWED_IMAGE_TYPES.has(contentType)) {\n\t\t\treturn apiError(\"ARTIFACT_NOT_IMAGE\", \"Artifact is not an allowed image type\", 415);\n\t\t}\n\n\t\tconst declaredLength = headers.get(\"content-length\");\n\t\tif (declaredLength) {\n\t\t\tconst declared = Number(declaredLength);\n\t\t\tif (Number.isFinite(declared) && declared > MAX_IMAGE_BYTES) {\n\t\t\t\treturn apiError(\"ARTIFACT_TOO_LARGE\", \"Artifact exceeds size limit\", 413);\n\t\t\t}\n\t\t}\n\t\tif (checksumValid === false) {\n\t\t\treturn artifactFetchError(\"CHECKSUM_MISMATCH\");\n\t\t}\n\n\t\t// Only the allowlisted Content-Type is forwarded — never copy other\n\t\t// upstream headers. `private, no-store` keeps publisher images out of\n\t\t// shared caches in the authenticated admin origin.\n\t\t//\n\t\t// SVG is not in the allowlist, so active-content bytes never reach\n\t\t// here. `Content-Disposition: attachment`, the sandbox CSP, and\n\t\t// `nosniff` remain as defence-in-depth: they force a download and\n\t\t// neutralise script/plugins for any image type if a client navigates\n\t\t// directly to the proxy URL.\n\t\treturn new Response(bytes, {\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": contentType,\n\t\t\t\t\"Cache-Control\": \"private, no-store\",\n\t\t\t\t\"X-Content-Type-Options\": \"nosniff\",\n\t\t\t\t\"Content-Disposition\": \"attachment\",\n\t\t\t\t\"Content-Security-Policy\": \"default-src 'none'; sandbox\",\n\t\t\t},\n\t\t});\n\t} catch {\n\t\treturn apiError(\"ARTIFACT_FETCH_FAILED\", \"Failed to fetch artifact\", 502);\n\t} finally {\n\t\tclearTimeout(timer);\n\t}\n};\n\n/**\n * Resolve the declared artifact URL for `(did, slug, version, kind, index)`\n * from the aggregator's release record. Mirrors the install handler's release\n * lookup. Returns `null` when the package/release/artifact isn't found.\n *\n * Self-contained to this route: the install/update handlers are intentionally\n * left untouched, so a small amount of resolution-pattern duplication is\n * accepted here.\n */\nasync function resolveArtifact(\n\tregistryConfig: { aggregatorUrl: string; acceptLabelers?: string },\n\tdid: string,\n\tslug: string,\n\tversion: string | undefined,\n\tcid: string,\n\tkind: string,\n\tindex: number,\n): Promise<ResolvedArtifact | null> {\n\t// Lazy-load the discovery client so the `@atcute/client` dependency only\n\t// loads when the registry path is exercised.\n\tconst { DiscoveryClient, registryLabelerPolicy } =\n\t\tawait import(\"@emdash-cms/registry-client/discovery\");\n\n\tconst aggregatorDeadline = Date.now() + AGGREGATOR_TOTAL_BUDGET_MS;\n\tconst discovery = new DiscoveryClient({\n\t\taggregatorUrl: registryConfig.aggregatorUrl,\n\t\tacceptLabelers: registryConfig.acceptLabelers,\n\t\tlabelerPolicy: registryLabelerPolicy(registryConfig.acceptLabelers),\n\t\tfetch: timedFetch(aggregatorDeadline),\n\t});\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- DID shape validated by the route before this call\n\tconst publisherDid = did as Did;\n\n\tconst releaseView = await (async () => {\n\t\tif (!version) {\n\t\t\treturn discovery.getLatestRelease({ did: publisherDid, package: slug });\n\t\t}\n\t\tlet cursor: string | undefined;\n\t\tconst seenCursors = new Set<string>();\n\t\tfor (let page = 0; page < MAX_LIST_PAGES; page++) {\n\t\t\tif (cursor !== undefined) {\n\t\t\t\tif (seenCursors.has(cursor)) break;\n\t\t\t\tseenCursors.add(cursor);\n\t\t\t}\n\t\t\tconst result = await discovery.listReleases({\n\t\t\t\tdid: publisherDid,\n\t\t\t\tpackage: slug,\n\t\t\t\tcursor,\n\t\t\t\tlimit: 50,\n\t\t\t});\n\t\t\tfor (const r of result.releases) {\n\t\t\t\tif (r.version === version) return r;\n\t\t\t}\n\t\t\tif (!result.cursor) break;\n\t\t\tcursor = result.cursor;\n\t\t}\n\t\treturn undefined;\n\t})();\n\n\tif (\n\t\t!releaseView?.release ||\n\t\treleaseView.cid !== cid ||\n\t\treleaseView.did !== publisherDid ||\n\t\treleaseView.package !== slug ||\n\t\t(version !== undefined && releaseView.version !== version) ||\n\t\treleaseView.release.package !== slug ||\n\t\treleaseView.release.version !== releaseView.version\n\t) {\n\t\treturn null;\n\t}\n\tif (evaluateRegistryReleaseWithdrawal(releaseView, discovery.labelerPolicy).withdrawn) {\n\t\treturn null;\n\t}\n\n\tconst descriptor = resolveDeclaredArtifact(releaseView.release.artifacts, kind, index);\n\tif (!descriptor || descriptor.requiresAuth || releaseView.release.auth !== undefined) return null;\n\tconst blobCid = descriptor.blob?.ref.$link;\n\tlet imageCacheUrl: URL | undefined;\n\tif (blobCid) {\n\t\tconst expected = multihashFromBlobCid(blobCid);\n\t\tif (!expected.success || expected.value !== descriptor.checksum) return null;\n\t\tconst rkey = `${slug}:${releaseView.version}`;\n\t\tconst serviceEndpoint = releaseView.artifactCaches\n\t\t\t.map(recordScopedCacheEndpoint)\n\t\t\t.find((value) => value !== null);\n\t\tif (serviceEndpoint) {\n\t\t\tconst preset = kind === \"icon\" ? \"avatar\" : kind === \"banner\" ? \"banner\" : \"feed_thumbnail\";\n\t\t\tconst cacheUrl = recordScopedImageCacheUrl(\n\t\t\t\tserviceEndpoint,\n\t\t\t\tpreset,\n\t\t\t\t{\n\t\t\t\t\tdid,\n\t\t\t\t\tcollection: NSID.packageRelease,\n\t\t\t\t\trkey,\n\t\t\t\t\tcid: releaseView.cid,\n\t\t\t\t},\n\t\t\t\tblobCid,\n\t\t\t);\n\t\t\tif (!cacheUrl.success) return null;\n\t\t\timageCacheUrl = cacheUrl.value;\n\t\t}\n\t}\n\treturn {\n\t\tartifact: descriptor,\n\t\trecord: {\n\t\t\tdid,\n\t\t\tcollection: NSID.packageRelease,\n\t\t\trkey: `${slug}:${releaseView.version}`,\n\t\t\tcid: releaseView.cid,\n\t\t},\n\t\t...(imageCacheUrl ? { imageCacheUrl } : {}),\n\t};\n}\n\nfunction recordScopedCacheEndpoint(value: unknown): string | null {\n\tif (objectProperty(value, \"$type\") !== RECORD_SCOPED_BLOB_CACHE_TYPE) return null;\n\tconst endpoint = objectProperty(value, \"serviceEndpoint\");\n\treturn typeof endpoint === \"string\" ? endpoint : null;\n}\n\n/** Build bounded, SSRF-validated fetch options for cache, PDS, and URL sources. */\nfunction proxyFetchOptions(signal: AbortSignal) {\n\treturn {\n\t\tfetch: async (url: URL, init: RequestInit) =>\n\t\t\tfetchRegistryArtifactUrl(url.href, {\n\t\t\t\tsignal: init.signal instanceof AbortSignal ? init.signal : signal,\n\t\t\t\tmaxResponseBytes: MAX_IMAGE_BYTES,\n\t\t\t}),\n\t\tresolveHostname: async (hostname: string) =>\n\t\t\t(await resolveAndValidateExternalUrlTarget(`https://${hostname}/`)).addresses,\n\t\tallowHttpLocalhost: import.meta.env.DEV,\n\t\tmaxBytes: MAX_IMAGE_BYTES,\n\t\tmaxRedirects: MAX_REDIRECTS,\n\t\ttotalTimeoutMs: FETCH_TIMEOUT_MS,\n\t};\n}\n\nasync function fetchRawArtifact(\n\tresolved: ResolvedArtifact,\n\toptions: ReturnType<typeof proxyFetchOptions>,\n): Promise<\n\t| { success: true; bytes: Uint8Array; headers: Headers; checksumValid: boolean }\n\t| { success: false; code: string }\n> {\n\tconst urls: URL[] = [];\n\tconst blobCid = resolved.artifact.blob?.ref.$link;\n\tlet lastCode = \"FETCH_FAILED\";\n\tlet checksumMismatch: { bytes: Uint8Array; headers: Headers } | undefined;\n\tif (blobCid) {\n\t\tconst pds = await resolvePublisherPdsEndpoint(resolved.record.did, options);\n\t\tif (pds.success) {\n\t\t\tconst url = new URL(\"/xrpc/com.atproto.sync.getBlob\", pds.value);\n\t\t\turl.searchParams.set(\"did\", resolved.record.did);\n\t\t\turl.searchParams.set(\"cid\", blobCid);\n\t\t\turls.push(url);\n\t\t} else {\n\t\t\tlastCode = pds.error.code;\n\t\t}\n\t}\n\tif (resolved.artifact.url) urls.push(new URL(resolved.artifact.url));\n\n\tfor (const url of urls) {\n\t\tconst fetched = await fetchVerifiedResource(url, options);\n\t\tif (!fetched.success) {\n\t\t\tlastCode = fetched.error.code;\n\t\t\tcontinue;\n\t\t}\n\t\tif (!(await verifyRegistryArtifactChecksum(fetched.value.bytes, resolved.artifact.checksum))) {\n\t\t\tlastCode = \"CHECKSUM_MISMATCH\";\n\t\t\tchecksumMismatch = { bytes: fetched.value.bytes, headers: fetched.value.headers };\n\t\t\tcontinue;\n\t\t}\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tbytes: fetched.value.bytes,\n\t\t\theaders: fetched.value.headers,\n\t\t\tchecksumValid: true,\n\t\t};\n\t}\n\tif (checksumMismatch) return { success: true, ...checksumMismatch, checksumValid: false };\n\treturn { success: false, code: lastCode };\n}\n\nfunction artifactFetchError(code: string): Response {\n\tif (code === \"CHECKSUM_MISMATCH\") {\n\t\treturn apiError(\n\t\t\t\"ARTIFACT_CHECKSUM_MISMATCH\",\n\t\t\t\"Artifact bytes do not match the approved release record\",\n\t\t\t502,\n\t\t);\n\t}\n\tif (code === \"RESOURCE_SIZE_EXCEEDED\") {\n\t\treturn apiError(\"ARTIFACT_TOO_LARGE\", \"Artifact exceeds size limit\", 413);\n\t}\n\tif (code === \"HOST_REJECTED\" || code === \"INVALID_URL\") {\n\t\treturn apiError(\"ARTIFACT_URL_REJECTED\", \"Artifact URL is not allowed\", 400);\n\t}\n\treturn apiError(\"ARTIFACT_FETCH_FAILED\", \"Failed to fetch artifact\", 502);\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.mts","names":[],"sources":["../../../../../../../src/astro/routes/api/admin/plugins/registry/install.ts"],"mappings":";;;cA0Ba,SAAA;AAAA,cAqCA,IAAA,EAAM,QAAA"}
1
+ {"version":3,"file":"install.d.mts","names":[],"sources":["../../../../../../../src/astro/routes/api/admin/plugins/registry/install.ts"],"mappings":";;;cA0Ba,SAAA;AAAA,cAuCA,IAAA,EAAM,QAAA"}