emdash 0.13.0 → 0.15.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 (605) hide show
  1. package/dist/{adapters-9DybjTO6.d.mts → adapters-C4yd_UJR.d.mts} +1 -1
  2. package/dist/{adapters-9DybjTO6.d.mts.map → adapters-C4yd_UJR.d.mts.map} +1 -1
  3. package/dist/{allowed-origins-CDdG-4Gd.mjs → allowed-origins-D0fFk9a6.mjs} +2 -2
  4. package/dist/{allowed-origins-CDdG-4Gd.mjs.map → allowed-origins-D0fFk9a6.mjs.map} +1 -1
  5. package/dist/api/route-utils.d.mts +3 -3
  6. package/dist/api/route-utils.mjs +15 -15
  7. package/dist/api/schemas/index.d.mts +2 -2
  8. package/dist/api/schemas/index.mjs +3 -3
  9. package/dist/{api-ayIQ7rIe.mjs → api-CLwG_3dh.mjs} +523 -59
  10. package/dist/api-CLwG_3dh.mjs.map +1 -0
  11. package/dist/{api-tokens-eYymBhIT.mjs → api-tokens-ucpcNXDt.mjs} +2 -2
  12. package/dist/{api-tokens-eYymBhIT.mjs.map → api-tokens-ucpcNXDt.mjs.map} +1 -1
  13. package/dist/{apply-v4DBgjPw.mjs → apply-wJhM_bwU.mjs} +17 -17
  14. package/dist/{apply-v4DBgjPw.mjs.map → apply-wJhM_bwU.mjs.map} +1 -1
  15. package/dist/astro/index.d.mts +10 -10
  16. package/dist/astro/index.mjs +21 -5
  17. package/dist/astro/index.mjs.map +1 -1
  18. package/dist/astro/middleware/auth.d.mts +9 -9
  19. package/dist/astro/middleware/auth.mjs +6 -6
  20. package/dist/astro/middleware/auth.mjs.map +1 -1
  21. package/dist/astro/middleware/redirect.mjs +4 -4
  22. package/dist/astro/middleware/request-context.mjs +2 -2
  23. package/dist/astro/middleware/request-context.mjs.map +1 -1
  24. package/dist/astro/middleware/setup.mjs +1 -1
  25. package/dist/astro/middleware.d.mts.map +1 -1
  26. package/dist/astro/middleware.mjs +353 -71
  27. package/dist/astro/middleware.mjs.map +1 -1
  28. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +5 -5
  29. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +5 -5
  30. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +4 -4
  31. package/dist/astro/routes/api/admin/api-tokens/index.mjs +5 -5
  32. package/dist/astro/routes/api/admin/bylines/_id_/index.d.mts.map +1 -1
  33. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +14 -17
  34. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
  35. package/dist/astro/routes/api/admin/bylines/_id_/translations.d.mts +9 -0
  36. package/dist/astro/routes/api/admin/bylines/_id_/translations.d.mts.map +1 -0
  37. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +70 -0
  38. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -0
  39. package/dist/astro/routes/api/admin/bylines/index.d.mts.map +1 -1
  40. package/dist/astro/routes/api/admin/bylines/index.mjs +25 -16
  41. package/dist/astro/routes/api/admin/bylines/index.mjs.map +1 -1
  42. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +10 -10
  43. package/dist/astro/routes/api/admin/comments/_id_.mjs +5 -5
  44. package/dist/astro/routes/api/admin/comments/bulk.mjs +8 -8
  45. package/dist/astro/routes/api/admin/comments/counts.mjs +5 -5
  46. package/dist/astro/routes/api/admin/comments/index.mjs +8 -8
  47. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +4 -4
  48. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
  49. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +4 -4
  50. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +4 -4
  51. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +32 -31
  52. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  53. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +32 -31
  54. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  55. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +31 -30
  56. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  57. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +31 -30
  58. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  59. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +33 -31
  60. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  61. package/dist/astro/routes/api/admin/plugins/index.mjs +31 -30
  62. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  63. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +3 -3
  64. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +31 -30
  65. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  66. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +33 -31
  67. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  68. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +31 -30
  69. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  70. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.d.mts +8 -0
  71. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.d.mts.map +1 -0
  72. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +59 -0
  73. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -0
  74. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.d.mts +8 -0
  75. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.d.mts.map +1 -0
  76. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +72 -0
  77. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -0
  78. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +31 -30
  79. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  80. package/dist/astro/routes/api/admin/plugins/updates.d.mts.map +1 -1
  81. package/dist/astro/routes/api/admin/plugins/updates.mjs +44 -31
  82. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  83. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +31 -30
  84. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  85. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +3 -3
  86. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +31 -30
  87. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  88. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +2 -2
  89. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +2 -2
  90. package/dist/astro/routes/api/admin/users/_id_/index.mjs +5 -5
  91. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +3 -3
  92. package/dist/astro/routes/api/admin/users/index.mjs +5 -5
  93. package/dist/astro/routes/api/auth/dev-bypass.mjs +5 -5
  94. package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
  95. package/dist/astro/routes/api/auth/invite/complete.mjs +9 -9
  96. package/dist/astro/routes/api/auth/invite/index.mjs +6 -6
  97. package/dist/astro/routes/api/auth/invite/register-options.mjs +8 -8
  98. package/dist/astro/routes/api/auth/logout.mjs +3 -3
  99. package/dist/astro/routes/api/auth/magic-link/send.mjs +8 -8
  100. package/dist/astro/routes/api/auth/magic-link/verify.mjs +3 -3
  101. package/dist/astro/routes/api/auth/me.mjs +5 -5
  102. package/dist/astro/routes/api/auth/mode.mjs +1 -1
  103. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +3 -3
  104. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs.map +1 -1
  105. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  106. package/dist/astro/routes/api/auth/oauth/_provider_.mjs.map +1 -1
  107. package/dist/astro/routes/api/auth/passkey/_id_.mjs +5 -5
  108. package/dist/astro/routes/api/auth/passkey/index.mjs +2 -2
  109. package/dist/astro/routes/api/auth/passkey/options.mjs +10 -10
  110. package/dist/astro/routes/api/auth/passkey/register/options.mjs +8 -8
  111. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +9 -9
  112. package/dist/astro/routes/api/auth/passkey/verify.mjs +9 -9
  113. package/dist/astro/routes/api/auth/signup/complete.mjs +9 -9
  114. package/dist/astro/routes/api/auth/signup/request.mjs +8 -8
  115. package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
  116. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +11 -11
  117. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +3 -3
  118. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +3 -3
  119. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs.map +1 -1
  120. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
  121. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs.map +1 -1
  122. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +3 -3
  123. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +9 -9
  124. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +6 -6
  125. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
  126. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
  127. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs.map +1 -1
  128. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +3 -3
  129. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +6 -6
  130. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
  131. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +10 -9
  132. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  133. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +3 -3
  134. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs.map +1 -1
  135. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +3 -3
  136. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs.map +1 -1
  137. package/dist/astro/routes/api/content/_collection_/_id_.mjs +6 -6
  138. package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
  139. package/dist/astro/routes/api/content/_collection_/index.mjs +6 -6
  140. package/dist/astro/routes/api/content/_collection_/trash.mjs +6 -6
  141. package/dist/astro/routes/api/dashboard.mjs +7 -7
  142. package/dist/astro/routes/api/dev/emails.mjs +3 -3
  143. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  144. package/dist/astro/routes/api/import/probe.mjs +10 -10
  145. package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
  146. package/dist/astro/routes/api/import/wordpress/execute.d.mts +9 -9
  147. package/dist/astro/routes/api/import/wordpress/execute.mjs +9 -8
  148. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  149. package/dist/astro/routes/api/import/wordpress/media.mjs +8 -8
  150. package/dist/astro/routes/api/import/wordpress/prepare.mjs +8 -8
  151. package/dist/astro/routes/api/import/wordpress/prepare.mjs.map +1 -1
  152. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +7 -7
  153. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
  154. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  155. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +10 -10
  156. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +1 -1
  157. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +11 -11
  158. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  159. package/dist/astro/routes/api/manifest.mjs +4 -4
  160. package/dist/astro/routes/api/mcp.mjs +29 -29
  161. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  162. package/dist/astro/routes/api/media/_id_/confirm.mjs +6 -6
  163. package/dist/astro/routes/api/media/_id_.mjs +6 -6
  164. package/dist/astro/routes/api/media/file/_...key_.mjs +2 -2
  165. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +3 -3
  166. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +3 -3
  167. package/dist/astro/routes/api/media/providers/index.mjs +3 -3
  168. package/dist/astro/routes/api/media/upload-url.mjs +7 -7
  169. package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
  170. package/dist/astro/routes/api/media.mjs +8 -8
  171. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +7 -7
  172. package/dist/astro/routes/api/menus/_name_/items.mjs +7 -7
  173. package/dist/astro/routes/api/menus/_name_/reorder.mjs +7 -7
  174. package/dist/astro/routes/api/menus/_name_/translations.mjs +7 -7
  175. package/dist/astro/routes/api/menus/_name_.mjs +7 -7
  176. package/dist/astro/routes/api/menus/index.mjs +7 -7
  177. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  178. package/dist/astro/routes/api/oauth/device/authorize.mjs +6 -6
  179. package/dist/astro/routes/api/oauth/device/code.mjs +9 -9
  180. package/dist/astro/routes/api/oauth/device/token.mjs +8 -8
  181. package/dist/astro/routes/api/oauth/register.mjs +3 -3
  182. package/dist/astro/routes/api/oauth/token/refresh.mjs +6 -6
  183. package/dist/astro/routes/api/oauth/token/revoke.mjs +6 -6
  184. package/dist/astro/routes/api/oauth/token.mjs +6 -6
  185. package/dist/astro/routes/api/openapi.json.mjs +3 -3
  186. package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
  187. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +4 -4
  188. package/dist/astro/routes/api/redirects/404s/index.mjs +8 -8
  189. package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
  190. package/dist/astro/routes/api/redirects/404s/summary.mjs +8 -8
  191. package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
  192. package/dist/astro/routes/api/redirects/_id_.mjs +9 -9
  193. package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
  194. package/dist/astro/routes/api/redirects/index.mjs +9 -9
  195. package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
  196. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +3 -3
  197. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
  198. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +31 -30
  199. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  200. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +31 -30
  201. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  202. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +31 -30
  203. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  204. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +31 -30
  205. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  206. package/dist/astro/routes/api/schema/collections/index.mjs +31 -30
  207. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  208. package/dist/astro/routes/api/schema/index.mjs +6 -6
  209. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  210. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +31 -30
  211. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  212. package/dist/astro/routes/api/schema/orphans/index.mjs +31 -30
  213. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  214. package/dist/astro/routes/api/search/enable.mjs +9 -9
  215. package/dist/astro/routes/api/search/index.mjs +8 -8
  216. package/dist/astro/routes/api/search/rebuild.mjs +9 -9
  217. package/dist/astro/routes/api/search/stats.mjs +6 -6
  218. package/dist/astro/routes/api/search/suggest.mjs +8 -8
  219. package/dist/astro/routes/api/sections/_slug_.mjs +8 -8
  220. package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
  221. package/dist/astro/routes/api/sections/index.mjs +8 -8
  222. package/dist/astro/routes/api/sections/index.mjs.map +1 -1
  223. package/dist/astro/routes/api/settings/email.mjs +4 -4
  224. package/dist/astro/routes/api/settings.mjs +10 -10
  225. package/dist/astro/routes/api/setup/admin-verify.mjs +10 -10
  226. package/dist/astro/routes/api/setup/admin.mjs +9 -9
  227. package/dist/astro/routes/api/setup/dev-bypass.mjs +22 -22
  228. package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
  229. package/dist/astro/routes/api/setup/index.mjs +22 -22
  230. package/dist/astro/routes/api/setup/status.mjs +4 -4
  231. package/dist/astro/routes/api/snapshot.mjs +5 -5
  232. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +11 -10
  233. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
  234. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +11 -10
  235. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
  236. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +11 -10
  237. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
  238. package/dist/astro/routes/api/taxonomies/index.mjs +11 -10
  239. package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
  240. package/dist/astro/routes/api/themes/preview.mjs +5 -5
  241. package/dist/astro/routes/api/typegen.mjs +5 -5
  242. package/dist/astro/routes/api/well-known/auth.mjs +1 -1
  243. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  244. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  245. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +6 -6
  246. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +8 -8
  247. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +8 -8
  248. package/dist/astro/routes/api/widget-areas/_name_.mjs +5 -5
  249. package/dist/astro/routes/api/widget-areas/index.mjs +8 -8
  250. package/dist/astro/routes/api/widget-components.mjs +3 -3
  251. package/dist/astro/routes/robots.txt.mjs +5 -5
  252. package/dist/astro/routes/sitemap-_collection_.xml.mjs +4 -4
  253. package/dist/astro/routes/sitemap.xml.mjs +5 -5
  254. package/dist/astro/types.d.mts +13 -12
  255. package/dist/astro/types.d.mts.map +1 -1
  256. package/dist/auth/providers/github.d.mts +1 -1
  257. package/dist/auth/providers/google.d.mts +1 -1
  258. package/dist/{authorize-BlyCH-96.mjs → authorize-Bkwe8kuL.mjs} +2 -2
  259. package/dist/{authorize-BlyCH-96.mjs.map → authorize-Bkwe8kuL.mjs.map} +1 -1
  260. package/dist/byline-CTaWkMh5.mjs +404 -0
  261. package/dist/byline-CTaWkMh5.mjs.map +1 -0
  262. package/dist/bylines-BYHWU3T7.mjs +174 -0
  263. package/dist/bylines-BYHWU3T7.mjs.map +1 -0
  264. package/dist/{bylines-C6eYUWlZ.d.mts → bylines-DtDRNF1n.d.mts} +63 -18
  265. package/dist/bylines-DtDRNF1n.d.mts.map +1 -0
  266. package/dist/bylines-H0Xh5TMy.mjs +118 -0
  267. package/dist/bylines-H0Xh5TMy.mjs.map +1 -0
  268. package/dist/{cache-CXCpjWiL.mjs → cache-CNk1jIxp.mjs} +2 -2
  269. package/dist/{cache-CXCpjWiL.mjs.map → cache-CNk1jIxp.mjs.map} +1 -1
  270. package/dist/{challenge-store-CJ0OOHOr.mjs → challenge-store-Dng1SxKT.mjs} +1 -1
  271. package/dist/{challenge-store-CJ0OOHOr.mjs.map → challenge-store-Dng1SxKT.mjs.map} +1 -1
  272. package/dist/{chunks-DyGtu1Bv.mjs → chunks-BkfVdD-3.mjs} +2 -2
  273. package/dist/{chunks-DyGtu1Bv.mjs.map → chunks-BkfVdD-3.mjs.map} +1 -1
  274. package/dist/cli/index.mjs +21 -29
  275. package/dist/cli/index.mjs.map +1 -1
  276. package/dist/client/cf-access.d.mts +1 -1
  277. package/dist/client/index.d.mts +1 -1
  278. package/dist/client/index.mjs +1 -1
  279. package/dist/client/index.mjs.map +1 -1
  280. package/dist/{comment-Dd9MI82-.mjs → comment-_yzlBYPx.mjs} +2 -2
  281. package/dist/{comment-Dd9MI82-.mjs.map → comment-_yzlBYPx.mjs.map} +1 -1
  282. package/dist/{comments-koGI0FrK.mjs → comments-DxID-rsd.mjs} +3 -3
  283. package/dist/{comments-koGI0FrK.mjs.map → comments-DxID-rsd.mjs.map} +1 -1
  284. package/dist/{components-mZem7pbe.mjs → components-Dx3DM0gg.mjs} +1 -1
  285. package/dist/{components-mZem7pbe.mjs.map → components-Dx3DM0gg.mjs.map} +1 -1
  286. package/dist/config-CVssduLe.mjs.map +1 -1
  287. package/dist/{content-D6YG26WG.mjs → content-C0ooIs-f.mjs} +3 -3
  288. package/dist/{content-D6YG26WG.mjs.map → content-C0ooIs-f.mjs.map} +1 -1
  289. package/dist/{context-qF8d3IPR.mjs → context-sAnCaUIR.mjs} +10 -10
  290. package/dist/context-sAnCaUIR.mjs.map +1 -0
  291. package/dist/{cron-H8eJ46dv.mjs → cron-Bd3b3iuj.mjs} +1 -1
  292. package/dist/{cron-H8eJ46dv.mjs.map → cron-Bd3b3iuj.mjs.map} +1 -1
  293. package/dist/{dashboard-BmWSIUwY.mjs → dashboard-Cqw3ay2X.mjs} +4 -4
  294. package/dist/{dashboard-BmWSIUwY.mjs.map → dashboard-Cqw3ay2X.mjs.map} +1 -1
  295. package/dist/db/index.d.mts +3 -3
  296. package/dist/db/index.mjs +1 -1
  297. package/dist/db/libsql.d.mts +1 -1
  298. package/dist/db/postgres.d.mts +1 -1
  299. package/dist/db/sqlite.d.mts +1 -1
  300. package/dist/{default-Dbs22Gg4.mjs → default-BvTAYCzx.mjs} +1 -1
  301. package/dist/{default-Dbs22Gg4.mjs.map → default-BvTAYCzx.mjs.map} +1 -1
  302. package/dist/{device-flow-BqJRxa0Q.mjs → device-flow-B9oG8PwP.mjs} +4 -4
  303. package/dist/{device-flow-BqJRxa0Q.mjs.map → device-flow-B9oG8PwP.mjs.map} +1 -1
  304. package/dist/{email-console-Dmp5Q-P2.mjs → email-console-CubRll9q.mjs} +1 -1
  305. package/dist/email-console-CubRll9q.mjs.map +1 -0
  306. package/dist/{error-tSQWIl5U.mjs → error-CPh_8eLq.mjs} +16 -8
  307. package/dist/error-CPh_8eLq.mjs.map +1 -0
  308. package/dist/{escape-B8bdIryO.mjs → escape-Cg6kMELH.mjs} +1 -1
  309. package/dist/{escape-B8bdIryO.mjs.map → escape-Cg6kMELH.mjs.map} +1 -1
  310. package/dist/{fts-manager-B633C-kQ.mjs → fts-manager-Mnrtn-r2.mjs} +2 -2
  311. package/dist/{fts-manager-B633C-kQ.mjs.map → fts-manager-Mnrtn-r2.mjs.map} +1 -1
  312. package/dist/{import-CNfLOgDE.mjs → import-DG80rC_I.mjs} +3 -3
  313. package/dist/{import-CNfLOgDE.mjs.map → import-DG80rC_I.mjs.map} +1 -1
  314. package/dist/{index-UmOMt9T-.d.mts → index-Bv1Wf1zB.d.mts} +235 -18
  315. package/dist/index-Bv1Wf1zB.d.mts.map +1 -0
  316. package/dist/{index-D2gvztOP.d.mts → index-CC42STEm.d.mts} +3 -3
  317. package/dist/{index-D2gvztOP.d.mts.map → index-CC42STEm.d.mts.map} +1 -1
  318. package/dist/index.d.mts +17 -17
  319. package/dist/index.mjs +50 -49
  320. package/dist/{load-QzYRpVN3.mjs → load-DmXNVhst.mjs} +2 -2
  321. package/dist/{load-QzYRpVN3.mjs.map → load-DmXNVhst.mjs.map} +1 -1
  322. package/dist/{loader-Cs6-Bqe6.mjs → loader-Chm5h7Gr.mjs} +3 -3
  323. package/dist/loader-Chm5h7Gr.mjs.map +1 -0
  324. package/dist/{manifest-schema-HCtSh4Jq.mjs → manifest-schema-Czqf0TLu.mjs} +1 -1
  325. package/dist/{manifest-schema-HCtSh4Jq.mjs.map → manifest-schema-Czqf0TLu.mjs.map} +1 -1
  326. package/dist/media/index.d.mts +1 -1
  327. package/dist/media/local-runtime.d.mts +11 -11
  328. package/dist/media/local-runtime.mjs +4 -4
  329. package/dist/{media-allowlist-B8EX01DH.mjs → media-allowlist-BNloC69x.mjs} +1 -1
  330. package/dist/{media-allowlist-B8EX01DH.mjs.map → media-allowlist-BNloC69x.mjs.map} +1 -1
  331. package/dist/{media-Dg7he9uK.mjs → media-oqRcNiQf.mjs} +2 -2
  332. package/dist/media-oqRcNiQf.mjs.map +1 -0
  333. package/dist/{menus-DOzIecHi.mjs → menus-Bjf5R1Qq.mjs} +2 -2
  334. package/dist/menus-Bjf5R1Qq.mjs.map +1 -0
  335. package/dist/{menus-X4Z-eBA1.mjs → menus-C75SSmRy.mjs} +30 -11
  336. package/dist/menus-C75SSmRy.mjs.map +1 -0
  337. package/dist/mime-KV5TqkMN.mjs.map +1 -1
  338. package/dist/{mode-DPRPvJYm.mjs → mode-CaaiebZI.mjs} +1 -1
  339. package/dist/{mode-DPRPvJYm.mjs.map → mode-CaaiebZI.mjs.map} +1 -1
  340. package/dist/{oauth-authorization-62GmpGIH.mjs → oauth-authorization-CTMeVfvj.mjs} +4 -4
  341. package/dist/{oauth-authorization-62GmpGIH.mjs.map → oauth-authorization-CTMeVfvj.mjs.map} +1 -1
  342. package/dist/{oauth-clients-D_B0_-Bz.mjs → oauth-clients-eJCbkVSG.mjs} +1 -1
  343. package/dist/oauth-clients-eJCbkVSG.mjs.map +1 -0
  344. package/dist/{oauth-state-store-DpsZViTu.mjs → oauth-state-store-vOSdOeGe.mjs} +1 -1
  345. package/dist/{oauth-state-store-DpsZViTu.mjs.map → oauth-state-store-vOSdOeGe.mjs.map} +1 -1
  346. package/dist/{oauth-user-lookup-meyS2oB1.mjs → oauth-user-lookup-3JwsVw6N.mjs} +1 -1
  347. package/dist/{oauth-user-lookup-meyS2oB1.mjs.map → oauth-user-lookup-3JwsVw6N.mjs.map} +1 -1
  348. package/dist/options-BL4X94qY.mjs.map +1 -1
  349. package/dist/{options-Cq64Wx0O.d.mts → options-DhV-gwJb.d.mts} +4 -4
  350. package/dist/options-DhV-gwJb.d.mts.map +1 -0
  351. package/dist/page/index.d.mts +2 -2
  352. package/dist/{parse-BFTPon-J.mjs → parse-3-caTKgt.mjs} +2 -2
  353. package/dist/{parse-BFTPon-J.mjs.map → parse-3-caTKgt.mjs.map} +1 -1
  354. package/dist/{passkey-config-Cg86_ISa.mjs → passkey-config-BloQOT3y.mjs} +1 -1
  355. package/dist/{passkey-config-Cg86_ISa.mjs.map → passkey-config-BloQOT3y.mjs.map} +1 -1
  356. package/dist/{placeholder-D3cFCU9y.d.mts → placeholder-KCkkCtgQ.d.mts} +1 -1
  357. package/dist/{placeholder-D3cFCU9y.d.mts.map → placeholder-KCkkCtgQ.d.mts.map} +1 -1
  358. package/dist/plugin-types.d.mts +1 -1
  359. package/dist/plugins/adapt-sandbox-entry.d.mts +9 -9
  360. package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
  361. package/dist/plugins/adapt-sandbox-entry.mjs +26 -15
  362. package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
  363. package/dist/{preview-C1LOEbWZ.mjs → preview-D4z0WONU.mjs} +2 -2
  364. package/dist/{preview-C1LOEbWZ.mjs.map → preview-D4z0WONU.mjs.map} +1 -1
  365. package/dist/{public-url-CseXl9Fv.mjs → public-url-CUWWFME2.mjs} +1 -1
  366. package/dist/{public-url-CseXl9Fv.mjs.map → public-url-CUWWFME2.mjs.map} +1 -1
  367. package/dist/{query-axZmO6Tn.mjs → query-BJn8TOPk.mjs} +16 -13
  368. package/dist/{query-axZmO6Tn.mjs.map → query-BJn8TOPk.mjs.map} +1 -1
  369. package/dist/{rate-limit-t5CVjCO6.mjs → rate-limit-D_-gAeJ0.mjs} +2 -2
  370. package/dist/{rate-limit-t5CVjCO6.mjs.map → rate-limit-D_-gAeJ0.mjs.map} +1 -1
  371. package/dist/{redirect-DGRsLO2I.mjs → redirect-BINiRYq4.mjs} +1 -1
  372. package/dist/{redirect-DGRsLO2I.mjs.map → redirect-BINiRYq4.mjs.map} +1 -1
  373. package/dist/{redirect-DkaDxq8e.mjs → redirect-CNv4mHX2.mjs} +2 -2
  374. package/dist/{redirect-DkaDxq8e.mjs.map → redirect-CNv4mHX2.mjs.map} +1 -1
  375. package/dist/{redirects-D1fdd68T.mjs → redirects-B-CUZ1Xh.mjs} +3 -3
  376. package/dist/{redirects-D1fdd68T.mjs.map → redirects-B-CUZ1Xh.mjs.map} +1 -1
  377. package/dist/{redirects-Dmj6KRU3.mjs → redirects-COMLwsV5.mjs} +19 -5
  378. package/dist/redirects-COMLwsV5.mjs.map +1 -0
  379. package/dist/{registry-BnCeHYsf.mjs → registry-DqrAQDXH.mjs} +4 -4
  380. package/dist/{registry-BnCeHYsf.mjs.map → registry-DqrAQDXH.mjs.map} +1 -1
  381. package/dist/request-cache-dzCt8TZB.mjs.map +1 -1
  382. package/dist/request-context.mjs.map +1 -1
  383. package/dist/{request-meta-CLCwSQOS.mjs → request-meta-C_Cjii-T.mjs} +2 -2
  384. package/dist/{request-meta-CLCwSQOS.mjs.map → request-meta-C_Cjii-T.mjs.map} +1 -1
  385. package/dist/resolve-Cj98DuqN.mjs +39 -0
  386. package/dist/resolve-Cj98DuqN.mjs.map +1 -0
  387. package/dist/{runner-DdnQIwz_.mjs → runner-CGlojznK.mjs} +472 -165
  388. package/dist/runner-CGlojznK.mjs.map +1 -0
  389. package/dist/{runner-DcfZewkO.d.mts → runner-CNHRo1mT.d.mts} +2 -2
  390. package/dist/{runner-DcfZewkO.d.mts.map → runner-CNHRo1mT.d.mts.map} +1 -1
  391. package/dist/runtime.d.mts +10 -10
  392. package/dist/runtime.mjs +2 -2
  393. package/dist/{schema-BmqagCwG.mjs → schema-Djdlfi5G.mjs} +4 -4
  394. package/dist/{schema-BmqagCwG.mjs.map → schema-Djdlfi5G.mjs.map} +1 -1
  395. package/dist/{search-CPrvO5u8.mjs → search-By-NN3da.mjs} +4 -4
  396. package/dist/{search-CPrvO5u8.mjs.map → search-By-NN3da.mjs.map} +1 -1
  397. package/dist/{secrets-6pgZyq0K.mjs → secrets-rPdhEBkD.mjs} +1 -1
  398. package/dist/{secrets-6pgZyq0K.mjs.map → secrets-rPdhEBkD.mjs.map} +1 -1
  399. package/dist/{sections-Cm-zb-gZ.mjs → sections-DcBIlOq1.mjs} +3 -3
  400. package/dist/{sections-Cm-zb-gZ.mjs.map → sections-DcBIlOq1.mjs.map} +1 -1
  401. package/dist/seed/index.d.mts +2 -2
  402. package/dist/seed/index.mjs +16 -16
  403. package/dist/seo/index.d.mts +1 -1
  404. package/dist/{seo-DRq9-EPP.mjs → seo-bjDoq9Eg.mjs} +2 -2
  405. package/dist/{seo-DRq9-EPP.mjs.map → seo-bjDoq9Eg.mjs.map} +1 -1
  406. package/dist/{service-vByySp-2.mjs → service-BuuTdGAT.mjs} +3 -3
  407. package/dist/{service-vByySp-2.mjs.map → service-BuuTdGAT.mjs.map} +1 -1
  408. package/dist/{settings-CBBj7HUd.mjs → settings-CJnKiWuR.mjs} +3 -3
  409. package/dist/{settings-CBBj7HUd.mjs.map → settings-CJnKiWuR.mjs.map} +1 -1
  410. package/dist/{settings-xQKsWnzQ.mjs → settings-hcubRfkr.mjs} +3 -3
  411. package/dist/settings-hcubRfkr.mjs.map +1 -0
  412. package/dist/{setup-BGAJ2uXs.mjs → setup-Cf_TyOv5.mjs} +2 -2
  413. package/dist/{setup-BGAJ2uXs.mjs.map → setup-Cf_TyOv5.mjs.map} +1 -1
  414. package/dist/{setup-complete-C6ZCLhKo.mjs → setup-complete-MzzN9u0b.mjs} +1 -1
  415. package/dist/{setup-complete-C6ZCLhKo.mjs.map → setup-complete-MzzN9u0b.mjs.map} +1 -1
  416. package/dist/{setup-nonce-CY1gQiAU.mjs → setup-nonce-DXuriHsg.mjs} +1 -1
  417. package/dist/{setup-nonce-CY1gQiAU.mjs.map → setup-nonce-DXuriHsg.mjs.map} +1 -1
  418. package/dist/{site-url-D-M4Fd8O.mjs → site-url-xkhw1tcz.mjs} +1 -1
  419. package/dist/{site-url-D-M4Fd8O.mjs.map → site-url-xkhw1tcz.mjs.map} +1 -1
  420. package/dist/{ssrf-DzFN_qV-.mjs → ssrf-MZ-zrG6-.mjs} +1 -1
  421. package/dist/{ssrf-DzFN_qV-.mjs.map → ssrf-MZ-zrG6-.mjs.map} +1 -1
  422. package/dist/storage/local.d.mts +1 -1
  423. package/dist/storage/local.mjs +1 -1
  424. package/dist/storage/local.mjs.map +1 -1
  425. package/dist/storage/s3.d.mts +1 -1
  426. package/dist/storage/s3.mjs +1 -1
  427. package/dist/storage/s3.mjs.map +1 -1
  428. package/dist/{taxonomies-Dc0mzlms.mjs → taxonomies-CLs9HPE2.mjs} +4 -4
  429. package/dist/{taxonomies-Dc0mzlms.mjs.map → taxonomies-CLs9HPE2.mjs.map} +1 -1
  430. package/dist/{taxonomies-Cn9UpaR2.mjs → taxonomies-WamPVA2x.mjs} +7 -42
  431. package/dist/taxonomies-WamPVA2x.mjs.map +1 -0
  432. package/dist/{taxonomy-wPfusMK9.mjs → taxonomy-D4Uc2LsZ.mjs} +3 -3
  433. package/dist/{taxonomy-wPfusMK9.mjs.map → taxonomy-D4Uc2LsZ.mjs.map} +1 -1
  434. package/dist/{tokens-DILYNZMi.mjs → tokens-N8otWMmj.mjs} +1 -1
  435. package/dist/{tokens-DILYNZMi.mjs.map → tokens-N8otWMmj.mjs.map} +1 -1
  436. package/dist/{transport-fw-mKJzT.mjs → transport-B6CHddbu.mjs} +1 -1
  437. package/dist/{transport-fw-mKJzT.mjs.map → transport-B6CHddbu.mjs.map} +1 -1
  438. package/dist/{transport-GeXlLscf.d.mts → transport-DOxLfUir.d.mts} +1 -1
  439. package/dist/{transport-GeXlLscf.d.mts.map → transport-DOxLfUir.d.mts.map} +1 -1
  440. package/dist/{trusted-proxy-CJhQIk65.mjs → trusted-proxy-97pajC2f.mjs} +1 -1
  441. package/dist/{trusted-proxy-CJhQIk65.mjs.map → trusted-proxy-97pajC2f.mjs.map} +1 -1
  442. package/dist/{types-CwXMEPRr.mjs → types-ByV5sgsv.mjs} +2 -2
  443. package/dist/types-ByV5sgsv.mjs.map +1 -0
  444. package/dist/{types-Dz9CGX_d.mjs → types-Cd9UCu3t.mjs} +1 -1
  445. package/dist/{types-Dz9CGX_d.mjs.map → types-Cd9UCu3t.mjs.map} +1 -1
  446. package/dist/{types-DmxPPXGf.d.mts → types-CkDSF81F.d.mts} +1 -1
  447. package/dist/{types-DmxPPXGf.d.mts.map → types-CkDSF81F.d.mts.map} +1 -1
  448. package/dist/{types-BWhaSS7U.d.mts → types-CpUuGcd5.d.mts} +1 -1
  449. package/dist/{types-BWhaSS7U.d.mts.map → types-CpUuGcd5.d.mts.map} +1 -1
  450. package/dist/{types-DFowNO60.d.mts → types-D599-ruj.d.mts} +1 -1
  451. package/dist/{types-DFowNO60.d.mts.map → types-D599-ruj.d.mts.map} +1 -1
  452. package/dist/{types-B05e2naf.d.mts → types-DGHWRQgr.d.mts} +3 -3
  453. package/dist/{types-B05e2naf.d.mts.map → types-DGHWRQgr.d.mts.map} +1 -1
  454. package/dist/{types-CzvJd1ND.d.mts → types-DaYDYW6g.d.mts} +14 -1
  455. package/dist/types-DaYDYW6g.d.mts.map +1 -0
  456. package/dist/{types-C1KKK4VP.d.mts → types-DaqNzqVt.d.mts} +16 -1
  457. package/dist/{types-C1KKK4VP.d.mts.map → types-DaqNzqVt.d.mts.map} +1 -1
  458. package/dist/{types-DW1l0gCv.d.mts → types-Dgo6y-Ut.d.mts} +1 -1
  459. package/dist/{types-DW1l0gCv.d.mts.map → types-Dgo6y-Ut.d.mts.map} +1 -1
  460. package/dist/{types-Cb2UCDJg.d.mts → types-bYmRn_Uy.d.mts} +1 -1
  461. package/dist/{types-Cb2UCDJg.d.mts.map → types-bYmRn_Uy.d.mts.map} +1 -1
  462. package/dist/{user-Dr1bOCqS.mjs → user-D3BD5zdT.mjs} +2 -2
  463. package/dist/{user-Dr1bOCqS.mjs.map → user-D3BD5zdT.mjs.map} +1 -1
  464. package/dist/{utils-_F-rWBTN.mjs → utils-C3wTAP-P.mjs} +1 -1
  465. package/dist/{utils-_F-rWBTN.mjs.map → utils-C3wTAP-P.mjs.map} +1 -1
  466. package/dist/{validate-BpQGsmd7.d.mts → validate-DQtHw9NT.d.mts} +5 -5
  467. package/dist/{validate-BpQGsmd7.d.mts.map → validate-DQtHw9NT.d.mts.map} +1 -1
  468. package/dist/{validate-DlFxcVVK.mjs → validate-mz87i8_1.mjs} +2 -2
  469. package/dist/{validate-DlFxcVVK.mjs.map → validate-mz87i8_1.mjs.map} +1 -1
  470. package/dist/{validation-BiFJqUp5.mjs → validation-DKHhXjPr.mjs} +5 -5
  471. package/dist/{validation-BiFJqUp5.mjs.map → validation-DKHhXjPr.mjs.map} +1 -1
  472. package/dist/version-Ct7C6RSo.mjs +7 -0
  473. package/dist/{version-Dw7Z5PVU.mjs.map → version-Ct7C6RSo.mjs.map} +1 -1
  474. package/dist/{widgets-B9j_yzlk.mjs → widgets-lShIQXU5.mjs} +3 -3
  475. package/dist/widgets-lShIQXU5.mjs.map +1 -0
  476. package/dist/{zod-generator-DSyz01KE.mjs → zod-generator-dvxgmd1M.mjs} +2 -2
  477. package/dist/{zod-generator-DSyz01KE.mjs.map → zod-generator-dvxgmd1M.mjs.map} +1 -1
  478. package/package.json +10 -8
  479. package/src/api/error.ts +18 -3
  480. package/src/api/errors.ts +6 -0
  481. package/src/api/handlers/bylines.ts +161 -0
  482. package/src/api/handlers/content.ts +125 -43
  483. package/src/api/handlers/index.ts +6 -0
  484. package/src/api/handlers/marketplace.ts +27 -5
  485. package/src/api/handlers/oauth-clients.ts +1 -1
  486. package/src/api/handlers/registry.ts +568 -22
  487. package/src/api/openapi/document.ts +1 -1
  488. package/src/api/schemas/bylines.ts +46 -0
  489. package/src/astro/integration/index.ts +1 -1
  490. package/src/astro/integration/routes.ts +5 -0
  491. package/src/astro/integration/runtime.ts +12 -1
  492. package/src/astro/integration/virtual-modules.ts +19 -2
  493. package/src/astro/integration/vite-config.ts +2 -2
  494. package/src/astro/middleware/auth.ts +7 -7
  495. package/src/astro/middleware/request-context.ts +1 -1
  496. package/src/astro/middleware.ts +31 -20
  497. package/src/astro/routes/api/admin/bylines/[id]/index.ts +3 -12
  498. package/src/astro/routes/api/admin/bylines/[id]/translations.ts +99 -0
  499. package/src/astro/routes/api/admin/bylines/index.ts +22 -11
  500. package/src/astro/routes/api/admin/plugins/[id]/update.ts +1 -0
  501. package/src/astro/routes/api/admin/plugins/marketplace/[id]/install.ts +6 -1
  502. package/src/astro/routes/api/admin/plugins/registry/[id]/uninstall.ts +51 -0
  503. package/src/astro/routes/api/admin/plugins/registry/[id]/update.ts +79 -0
  504. package/src/astro/routes/api/admin/plugins/updates.ts +43 -6
  505. package/src/astro/routes/api/admin/themes/marketplace/index.ts +1 -1
  506. package/src/astro/routes/api/auth/oauth/[provider]/callback.ts +2 -2
  507. package/src/astro/routes/api/auth/oauth/[provider].ts +2 -2
  508. package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +2 -2
  509. package/src/astro/routes/api/content/[collection]/[id]/duplicate.ts +2 -2
  510. package/src/astro/routes/api/content/[collection]/[id]/publish.ts +2 -2
  511. package/src/astro/routes/api/content/[collection]/[id]/restore.ts +2 -2
  512. package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +2 -2
  513. package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +6 -6
  514. package/src/astro/routes/api/content/[collection]/[id]/translations.ts +1 -1
  515. package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +2 -2
  516. package/src/astro/routes/api/content/[collection]/[id].ts +6 -6
  517. package/src/astro/routes/api/import/wordpress/execute.ts +1 -1
  518. package/src/astro/routes/api/import/wordpress/prepare.ts +2 -2
  519. package/src/astro/routes/api/import/wordpress/rewrite-urls.ts +3 -3
  520. package/src/astro/routes/api/import/wordpress-plugin/execute.ts +2 -2
  521. package/src/astro/routes/api/media/upload-url.ts +1 -1
  522. package/src/astro/routes/api/redirects/404s/index.ts +3 -3
  523. package/src/astro/routes/api/redirects/404s/summary.ts +1 -1
  524. package/src/astro/routes/api/redirects/[id].ts +3 -3
  525. package/src/astro/routes/api/redirects/index.ts +2 -2
  526. package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +4 -4
  527. package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +2 -6
  528. package/src/astro/routes/api/schema/collections/[slug]/fields/reorder.ts +1 -1
  529. package/src/astro/routes/api/schema/collections/[slug]/index.ts +6 -6
  530. package/src/astro/routes/api/schema/collections/index.ts +4 -4
  531. package/src/astro/routes/api/schema/index.ts +1 -1
  532. package/src/astro/routes/api/schema/orphans/[slug].ts +1 -1
  533. package/src/astro/routes/api/schema/orphans/index.ts +1 -1
  534. package/src/astro/routes/api/sections/[slug].ts +3 -3
  535. package/src/astro/routes/api/sections/index.ts +2 -2
  536. package/src/astro/types.ts +4 -0
  537. package/src/auth/rate-limit.ts +1 -1
  538. package/src/auth/trusted-proxy.ts +1 -1
  539. package/src/bylines/index.ts +154 -55
  540. package/src/cli/commands/init.ts +4 -8
  541. package/src/client/index.ts +1 -1
  542. package/src/components/InlinePortableTextEditor.tsx +5 -1
  543. package/src/components/inline-code-block.tsx +343 -0
  544. package/src/config/secrets.ts +3 -3
  545. package/src/database/migrations/006_taxonomy_defs.ts +1 -1
  546. package/src/database/migrations/014_draft_revisions.ts +6 -6
  547. package/src/database/migrations/040_byline_i18n.ts +497 -0
  548. package/src/database/migrations/runner.ts +4 -1
  549. package/src/database/repositories/audit.ts +2 -2
  550. package/src/database/repositories/byline.ts +320 -50
  551. package/src/database/repositories/media.ts +2 -2
  552. package/src/database/repositories/menu.ts +1 -1
  553. package/src/database/repositories/options.ts +3 -3
  554. package/src/database/repositories/plugin-storage.ts +3 -3
  555. package/src/database/repositories/types.ts +13 -0
  556. package/src/database/types.ts +15 -0
  557. package/src/emdash-runtime.ts +492 -20
  558. package/src/i18n/config.ts +1 -1
  559. package/src/index.ts +7 -0
  560. package/src/loader.ts +1 -1
  561. package/src/mcp/server.ts +3 -3
  562. package/src/media/mime.ts +1 -1
  563. package/src/page/absolute-url.ts +1 -1
  564. package/src/plugins/adapt-sandbox-entry.ts +45 -40
  565. package/src/plugins/email-console.ts +1 -1
  566. package/src/plugins/index.ts +1 -0
  567. package/src/plugins/marketplace.ts +1 -1
  568. package/src/plugins/sandbox/index.ts +1 -0
  569. package/src/plugins/sandbox/noop.ts +11 -3
  570. package/src/plugins/sandbox/types.ts +28 -0
  571. package/src/query.ts +17 -2
  572. package/src/registry/config.ts +1 -1
  573. package/src/request-cache.ts +3 -3
  574. package/src/request-context.ts +1 -1
  575. package/src/settings/index.ts +4 -4
  576. package/src/storage/local.ts +1 -1
  577. package/src/storage/s3.ts +3 -3
  578. package/src/widgets/index.ts +1 -1
  579. package/dist/api-ayIQ7rIe.mjs.map +0 -1
  580. package/dist/byline-D09BaS4j.mjs +0 -220
  581. package/dist/byline-D09BaS4j.mjs.map +0 -1
  582. package/dist/bylines-BTM2xtP8.mjs +0 -113
  583. package/dist/bylines-BTM2xtP8.mjs.map +0 -1
  584. package/dist/bylines-C6eYUWlZ.d.mts.map +0 -1
  585. package/dist/context-qF8d3IPR.mjs.map +0 -1
  586. package/dist/email-console-Dmp5Q-P2.mjs.map +0 -1
  587. package/dist/error-tSQWIl5U.mjs.map +0 -1
  588. package/dist/index-UmOMt9T-.d.mts.map +0 -1
  589. package/dist/loader-Cs6-Bqe6.mjs.map +0 -1
  590. package/dist/media-Dg7he9uK.mjs.map +0 -1
  591. package/dist/menus-DOzIecHi.mjs.map +0 -1
  592. package/dist/menus-X4Z-eBA1.mjs.map +0 -1
  593. package/dist/oauth-clients-D_B0_-Bz.mjs.map +0 -1
  594. package/dist/options-Cq64Wx0O.d.mts.map +0 -1
  595. package/dist/redirects-Dmj6KRU3.mjs.map +0 -1
  596. package/dist/runner-DdnQIwz_.mjs.map +0 -1
  597. package/dist/settings-xQKsWnzQ.mjs.map +0 -1
  598. package/dist/taxonomies-Cn9UpaR2.mjs.map +0 -1
  599. package/dist/types-CwXMEPRr.mjs.map +0 -1
  600. package/dist/types-CzvJd1ND.d.mts.map +0 -1
  601. package/dist/version-Dw7Z5PVU.mjs +0 -7
  602. package/dist/widgets-B9j_yzlk.mjs.map +0 -1
  603. /package/dist/{api-tokens-D3C9v02m.mjs → api-tokens-iPIHAY8N.mjs} +0 -0
  604. /package/dist/{ssrf-CTul4uQi.mjs → ssrf-BIcd-aXW.mjs} +0 -0
  605. /package/dist/{types-Db67HHlU.mjs → types-1NNkmTIn.mjs} +0 -0
@@ -38,6 +38,7 @@
38
38
  * mitigated by the artifact checksum but not detected.
39
39
  */
40
40
 
41
+ import { ClientResponseError, ClientValidationError } from "@atcute/client";
41
42
  import type { Did } from "@atcute/lexicons";
42
43
  import type { Kysely } from "kysely";
43
44
 
@@ -59,7 +60,13 @@ import { resolveAndValidateExternalUrl, SsrfError } from "../../security/ssrf.js
59
60
  import { EmDashStorageError } from "../../storage/types.js";
60
61
  import type { Storage } from "../../storage/types.js";
61
62
  import type { ApiResult } from "../types.js";
62
- import { deleteBundleFromR2, storeBundleInR2 } from "./marketplace.js";
63
+ import {
64
+ deleteBundleFromR2,
65
+ diffCapabilities,
66
+ diffRouteVisibility,
67
+ loadBundleFromR2,
68
+ storeBundleInR2,
69
+ } from "./marketplace.js";
63
70
 
64
71
  // ── Types ──────────────────────────────────────────────────────────
65
72
 
@@ -162,7 +169,7 @@ async function sha256MultibaseMultihash(bytes: Uint8Array): Promise<string> {
162
169
  * Hash functions other than sha2-256 are out of scope for this
163
170
  * initial release; the install fails closed.
164
171
  */
165
- async function verifyChecksum(bytes: Uint8Array, checksum: string): Promise<boolean> {
172
+ export async function verifyChecksum(bytes: Uint8Array, checksum: string): Promise<boolean> {
166
173
  if (SHA256_HEX_PATTERN.test(checksum)) {
167
174
  const actual = await sha256Hex(bytes);
168
175
  return checksum.toLowerCase() === actual;
@@ -314,7 +321,7 @@ function isLocalhostHostname(hostname: string): boolean {
314
321
  * `import.meta.env.DEV` is a Vite/Astro compile-time constant, so
315
322
  * production bundles cannot enable the dev escape hatch at runtime.
316
323
  */
317
- async function assertSafeArtifactUrl(urlString: string): Promise<URL> {
324
+ export async function assertSafeArtifactUrl(urlString: string): Promise<URL> {
318
325
  let url: URL;
319
326
  try {
320
327
  url = new URL(urlString);
@@ -364,7 +371,7 @@ async function assertSafeArtifactUrl(urlString: string): Promise<URL> {
364
371
  return await resolveAndValidateExternalUrl(url.href);
365
372
  } catch (err) {
366
373
  if (err instanceof SsrfError) {
367
- throw new Error(`Artifact URL rejected: ${err.message}`);
374
+ throw new Error(`Artifact URL rejected: ${err.message}`, { cause: err });
368
375
  }
369
376
  throw err;
370
377
  }
@@ -679,10 +686,10 @@ export async function handleRegistryInstall(
679
686
  // publisher's record. Checksum verification only proves the bytes
680
687
  // match the *returned* record, not that the record belongs to
681
688
  // the package we requested.
682
- const signedRelease = releaseView.release as
683
- | { package?: unknown; version?: unknown }
684
- | null
685
- | undefined;
689
+ // `releaseView.release` is validated against the release lexicon by
690
+ // DiscoveryClient (or `null` if it didn't conform). A `null` here makes
691
+ // the identity checks below fail closed, which is the desired outcome.
692
+ const signedRelease = releaseView.release;
686
693
  if (packageView.did !== publisherDid || packageView.slug !== slug) {
687
694
  return {
688
695
  success: false,
@@ -848,17 +855,13 @@ export async function handleRegistryInstall(
848
855
  }
849
856
 
850
857
  // Step 4: fetch the artifact bytes.
851
- // The signed release record is `releaseView.release`; the lexicon
852
- // types it as `unknown` so we extract the package artifact via
853
- // duck-typed access. Mirrors come from the envelope (aggregator
854
- // operational data, not part of the signed record).
855
- const release = releaseView.release as {
856
- artifacts?: {
857
- package?: { url?: string; checksum?: string };
858
- };
859
- };
860
- const declaredUrl = release.artifacts?.package?.url;
861
- const declaredChecksum = release.artifacts?.package?.checksum;
858
+ // `releaseView.release` is lexicon-validated by DiscoveryClient (or
859
+ // `null`); a missing url/checksum (incl. the `null` case) fails closed
860
+ // below. Mirrors come from the envelope (aggregator operational data,
861
+ // not part of the signed record).
862
+ const release = releaseView.release;
863
+ const declaredUrl = release?.artifacts?.package?.url;
864
+ const declaredChecksum = release?.artifacts?.package?.checksum;
862
865
 
863
866
  if (!declaredUrl || !declaredChecksum) {
864
867
  return {
@@ -1021,12 +1024,13 @@ export async function handleRegistryInstall(
1021
1024
  // Cleanup is best-effort; if it also fails, the row failure
1022
1025
  // still surfaces to the caller and the orphan R2 bundle costs
1023
1026
  // only the storage of a single checksum-verified zip.
1024
- const profile = packageView.profile as { name?: string; description?: string };
1027
+ // `packageView.profile` is lexicon-validated by DiscoveryClient (or null).
1028
+ const profile = packageView.profile;
1025
1029
  try {
1026
1030
  await stateRepo.upsert(pluginId, version, "active", {
1027
1031
  source: "registry",
1028
- displayName: profile.name ?? slug,
1029
- description: profile.description ?? undefined,
1032
+ displayName: profile?.name ?? slug,
1033
+ description: profile?.description ?? undefined,
1030
1034
  registryPublisherDid: publisherDid,
1031
1035
  registrySlug: slug,
1032
1036
  });
@@ -1065,6 +1069,24 @@ export async function handleRegistryInstall(
1065
1069
  },
1066
1070
  };
1067
1071
  } catch (err) {
1072
+ if (err instanceof ClientValidationError) {
1073
+ return {
1074
+ success: false,
1075
+ error: {
1076
+ code: "AGGREGATOR_RESPONSE_INVALID",
1077
+ message: `Aggregator returned a response that does not conform to its lexicon (${err.target})`,
1078
+ },
1079
+ };
1080
+ }
1081
+ if (err instanceof ClientResponseError) {
1082
+ return {
1083
+ success: false,
1084
+ error: {
1085
+ code: err.status === 404 ? "AGGREGATOR_NOT_FOUND" : "AGGREGATOR_HTTP_ERROR",
1086
+ message: `Aggregator returned ${err.status}: ${err.error}`,
1087
+ },
1088
+ };
1089
+ }
1068
1090
  if (err instanceof EmDashStorageError) {
1069
1091
  return {
1070
1092
  success: false,
@@ -1084,3 +1106,527 @@ export async function handleRegistryInstall(
1084
1106
  };
1085
1107
  }
1086
1108
  }
1109
+
1110
+ // ── Uninstall ──────────────────────────────────────────────────────
1111
+
1112
+ export interface RegistryUninstallResult {
1113
+ pluginId: string;
1114
+ /** True when `_plugin_storage` rows were also deleted (opts.deleteData). */
1115
+ dataDeleted: boolean;
1116
+ }
1117
+
1118
+ /**
1119
+ * Uninstall a registry-source plugin. Deletes the R2 bundle under
1120
+ * `registry/<pluginId>/<version>/`, optionally drops the plugin's
1121
+ * `_plugin_storage` rows, and removes the `_plugin_state` row. The
1122
+ * sandbox runtime is reconciled by the route's `syncRegistryPlugins`
1123
+ * call after this returns.
1124
+ *
1125
+ * Refuses to uninstall plugins whose `source` is not `"registry"` to
1126
+ * avoid trashing a marketplace/config plugin that happens to share the
1127
+ * pluginId namespace.
1128
+ */
1129
+ export async function handleRegistryUninstall(
1130
+ db: Kysely<Database>,
1131
+ storage: Storage | null,
1132
+ pluginId: string,
1133
+ opts?: { deleteData?: boolean },
1134
+ ): Promise<ApiResult<RegistryUninstallResult>> {
1135
+ try {
1136
+ const stateRepo = new PluginStateRepository(db);
1137
+ const existing = await stateRepo.get(pluginId);
1138
+ if (!existing || existing.source !== "registry") {
1139
+ return {
1140
+ success: false,
1141
+ error: {
1142
+ code: "NOT_FOUND",
1143
+ message: `No registry plugin found: ${pluginId}`,
1144
+ },
1145
+ };
1146
+ }
1147
+
1148
+ // `_plugin_state.version` carries the installed version directly for
1149
+ // registry-source rows (there's no shadow column like marketplace's
1150
+ // `marketplaceVersion`). Use it verbatim for the R2 prefix.
1151
+ const version = existing.version;
1152
+
1153
+ // Order: optional storage cleanup → bundle delete → state row delete.
1154
+ // The most failure-prone step runs first so a transient DB error
1155
+ // (deadlock, contention) cascades to the outer catch with the state
1156
+ // row and bundle intact — admin retries safely. Bundle delete is
1157
+ // idempotent on misses.
1158
+ let dataDeleted = false;
1159
+ if (opts?.deleteData) {
1160
+ await db.deleteFrom("_plugin_storage").where("plugin_id", "=", pluginId).execute();
1161
+ dataDeleted = true;
1162
+ }
1163
+
1164
+ if (storage) {
1165
+ await deleteBundleFromR2(storage, pluginId, version, "registry");
1166
+ }
1167
+
1168
+ await stateRepo.delete(pluginId);
1169
+
1170
+ return { success: true, data: { pluginId, dataDeleted } };
1171
+ } catch (err) {
1172
+ console.error("[registry-uninstall] Failed:", err);
1173
+ return {
1174
+ success: false,
1175
+ error: {
1176
+ code: "UNINSTALL_FAILED",
1177
+ message: "Failed to uninstall plugin",
1178
+ },
1179
+ };
1180
+ }
1181
+ }
1182
+
1183
+ // ── Update ─────────────────────────────────────────────────────────
1184
+
1185
+ export interface RegistryUpdateResult {
1186
+ pluginId: string;
1187
+ oldVersion: string;
1188
+ newVersion: string;
1189
+ capabilityChanges: { added: string[]; removed: string[] };
1190
+ /** Set only when `newlyPublic` is non-empty, mirroring marketplace. */
1191
+ routeVisibilityChanges?: { newlyPublic: string[] };
1192
+ }
1193
+
1194
+ /**
1195
+ * Update a registry-source plugin to a newer release. Mirrors
1196
+ * `handleMarketplaceUpdate`: resolves the target version via the aggregator,
1197
+ * re-runs the artifact fetch / checksum / extract pipeline, diffs capabilities
1198
+ * and route visibility against the currently installed bundle, and gates
1199
+ * escalations behind `confirmCapabilityChanges` / `confirmRouteVisibilityChanges`
1200
+ * so the admin re-consents to widened permissions.
1201
+ *
1202
+ * Refuses non-registry sources. Refuses when the stored state row is missing
1203
+ * the `(publisherDid, slug)` it needs to resolve against the aggregator.
1204
+ */
1205
+ export async function handleRegistryUpdate(
1206
+ db: Kysely<Database>,
1207
+ storage: Storage | null,
1208
+ sandboxRunner: SandboxRunner | null,
1209
+ registryConfigInput: RegistryConfigInput | undefined,
1210
+ pluginId: string,
1211
+ opts?: {
1212
+ version?: string;
1213
+ confirmCapabilityChanges?: boolean;
1214
+ confirmRouteVisibilityChanges?: boolean;
1215
+ },
1216
+ ): Promise<ApiResult<RegistryUpdateResult>> {
1217
+ const registryConfig = coerceRegistryConfig(registryConfigInput);
1218
+ if (!registryConfig) {
1219
+ return {
1220
+ success: false,
1221
+ error: { code: "REGISTRY_NOT_CONFIGURED", message: "Registry is not configured" },
1222
+ };
1223
+ }
1224
+ if (!storage) {
1225
+ return {
1226
+ success: false,
1227
+ error: {
1228
+ code: "STORAGE_NOT_CONFIGURED",
1229
+ message: "Storage is required for registry plugin updates",
1230
+ },
1231
+ };
1232
+ }
1233
+ if (!sandboxRunner || !sandboxRunner.isAvailable()) {
1234
+ return {
1235
+ success: false,
1236
+ error: { code: "SANDBOX_NOT_AVAILABLE", message: "Sandbox runner is required" },
1237
+ };
1238
+ }
1239
+ try {
1240
+ validateAggregatorUrl(registryConfig.aggregatorUrl);
1241
+ } catch (err) {
1242
+ return {
1243
+ success: false,
1244
+ error: {
1245
+ code: "REGISTRY_NOT_CONFIGURED",
1246
+ message: err instanceof Error ? err.message : "Invalid aggregator URL",
1247
+ },
1248
+ };
1249
+ }
1250
+
1251
+ try {
1252
+ const stateRepo = new PluginStateRepository(db);
1253
+ const existing = await stateRepo.get(pluginId);
1254
+ if (!existing || existing.source !== "registry") {
1255
+ return {
1256
+ success: false,
1257
+ error: { code: "NOT_FOUND", message: `No registry plugin found: ${pluginId}` },
1258
+ };
1259
+ }
1260
+ if (!existing.registryPublisherDid || !existing.registrySlug) {
1261
+ return {
1262
+ success: false,
1263
+ error: {
1264
+ code: "INVALID_STATE",
1265
+ message: `Registry plugin ${pluginId} is missing publisher DID or slug in state`,
1266
+ },
1267
+ };
1268
+ }
1269
+ const oldVersion = existing.version;
1270
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- existing.registryPublisherDid is a DID string written by the install handler
1271
+ const publisherDid = existing.registryPublisherDid as Did;
1272
+ const slug = existing.registrySlug;
1273
+
1274
+ const { DiscoveryClient } = await import("@emdash-cms/registry-client/discovery");
1275
+ const aggregatorDeadline = Date.now() + AGGREGATOR_TOTAL_BUDGET_MS;
1276
+ const discovery = new DiscoveryClient({
1277
+ aggregatorUrl: registryConfig.aggregatorUrl,
1278
+ acceptLabelers: registryConfig.acceptLabelers,
1279
+ fetch: timedFetch(aggregatorDeadline),
1280
+ });
1281
+
1282
+ // Resolve target release. Explicit version → paginate listReleases;
1283
+ // otherwise getLatestRelease (aggregator applies its own filters).
1284
+ const MAX_LIST_PAGES = 20;
1285
+ const releaseView = await (async () => {
1286
+ if (!opts?.version) {
1287
+ return discovery.getLatestRelease({ did: publisherDid, package: slug });
1288
+ }
1289
+ let cursor: string | undefined;
1290
+ const seenCursors = new Set<string>();
1291
+ for (let page = 0; page < MAX_LIST_PAGES; page++) {
1292
+ if (cursor !== undefined) {
1293
+ if (seenCursors.has(cursor)) break;
1294
+ seenCursors.add(cursor);
1295
+ }
1296
+ const result = await discovery.listReleases({
1297
+ did: publisherDid,
1298
+ package: slug,
1299
+ cursor,
1300
+ limit: 50,
1301
+ });
1302
+ for (const r of result.releases) {
1303
+ if (r.version === opts.version) return r;
1304
+ }
1305
+ if (!result.cursor) break;
1306
+ cursor = result.cursor;
1307
+ }
1308
+ return undefined;
1309
+ })();
1310
+
1311
+ if (!releaseView) {
1312
+ return {
1313
+ success: false,
1314
+ error: {
1315
+ code: "NO_VERSION",
1316
+ message: opts?.version
1317
+ ? `Version ${opts.version} not found for ${publisherDid}/${slug}`
1318
+ : `No installable release found for ${publisherDid}/${slug}`,
1319
+ },
1320
+ };
1321
+ }
1322
+
1323
+ // Identity cross-check. A buggy/compromised aggregator must not
1324
+ // trick us into installing a record signed for a different
1325
+ // (did, slug, version) under this plugin's pluginId.
1326
+ const signedRelease = releaseView.release;
1327
+ if (
1328
+ releaseView.did !== publisherDid ||
1329
+ releaseView.package !== slug ||
1330
+ signedRelease?.package !== slug ||
1331
+ (opts?.version !== undefined && releaseView.version !== opts.version) ||
1332
+ signedRelease?.version !== releaseView.version
1333
+ ) {
1334
+ return {
1335
+ success: false,
1336
+ error: {
1337
+ code: "AGGREGATOR_IDENTITY_MISMATCH",
1338
+ message:
1339
+ "Aggregator returned a release view that does not match the requested package or version.",
1340
+ },
1341
+ };
1342
+ }
1343
+
1344
+ const newVersion = releaseView.version;
1345
+ if (newVersion === oldVersion) {
1346
+ return {
1347
+ success: false,
1348
+ error: {
1349
+ code: "ALREADY_UP_TO_DATE",
1350
+ message: "Plugin is already at the requested version",
1351
+ },
1352
+ };
1353
+ }
1354
+
1355
+ // Yanked label check (mirrors install).
1356
+ const releaseYanked = (releaseView.labels ?? []).some(
1357
+ (l: { val?: string }) => l.val === "security:yanked",
1358
+ );
1359
+ if (releaseYanked) {
1360
+ return {
1361
+ success: false,
1362
+ error: { code: "YANKED", message: "Release has been yanked by a trusted labeller" },
1363
+ };
1364
+ }
1365
+
1366
+ const declaredUrl = signedRelease.artifacts?.package?.url;
1367
+ const declaredChecksum = signedRelease.artifacts?.package?.checksum;
1368
+ if (!declaredUrl || !declaredChecksum) {
1369
+ return {
1370
+ success: false,
1371
+ error: {
1372
+ code: "INVALID_RELEASE",
1373
+ message: "Release record is missing artifact url or checksum",
1374
+ },
1375
+ };
1376
+ }
1377
+
1378
+ // SSRF check on declared URL + each mirror.
1379
+ await assertSafeArtifactUrl(declaredUrl);
1380
+ const rawMirrors = releaseView.mirrors ?? [];
1381
+ const mirrors = rawMirrors.slice(0, MAX_MIRRORS);
1382
+ for (const mirror of mirrors) {
1383
+ await assertSafeArtifactUrl(mirror);
1384
+ }
1385
+
1386
+ // `fetchArtifact` derives its own per-call deadline internally.
1387
+ const artifactBytes = await fetchArtifact(mirrors, declaredUrl);
1388
+ if (!(await verifyChecksum(artifactBytes, declaredChecksum))) {
1389
+ return {
1390
+ success: false,
1391
+ error: {
1392
+ code: "CHECKSUM_MISMATCH",
1393
+ message: "Artifact bytes do not match the release's published checksum",
1394
+ },
1395
+ };
1396
+ }
1397
+
1398
+ const bundle: PluginBundle = await extractBundle(artifactBytes);
1399
+
1400
+ if (bundle.manifest.version !== newVersion) {
1401
+ return {
1402
+ success: false,
1403
+ error: {
1404
+ code: "BUNDLE_VERSION_MISMATCH",
1405
+ message: `Bundle manifest version (${bundle.manifest.version}) does not match release version (${newVersion})`,
1406
+ },
1407
+ };
1408
+ }
1409
+ if (bundle.manifest.id !== slug) {
1410
+ return {
1411
+ success: false,
1412
+ error: {
1413
+ code: "BUNDLE_IDENTITY_MISMATCH",
1414
+ message: `Bundle manifest id (${bundle.manifest.id}) does not match registry slug (${slug})`,
1415
+ },
1416
+ };
1417
+ }
1418
+
1419
+ // Rewrite manifest.id to the opaque pluginId so the sandbox loader
1420
+ // and R2 layout stay in sync across install and update.
1421
+ bundle.manifest = { ...bundle.manifest, id: pluginId };
1422
+
1423
+ // Diff capabilities + route visibility against the currently
1424
+ // installed bundle. Loading from R2 keeps us honest: the diff is
1425
+ // against the bytes the sandbox is actually running, not whatever
1426
+ // the state row claims.
1427
+ const oldBundle = await loadBundleFromR2(storage, pluginId, oldVersion, "registry");
1428
+ const oldCaps = oldBundle?.manifest.capabilities ?? [];
1429
+ const capabilityChanges = diffCapabilities(oldCaps, bundle.manifest.capabilities);
1430
+ const hasEscalation = capabilityChanges.added.length > 0;
1431
+ if (hasEscalation && !opts?.confirmCapabilityChanges) {
1432
+ return {
1433
+ success: false,
1434
+ error: {
1435
+ code: "CAPABILITY_ESCALATION",
1436
+ message: "Plugin update requires new capabilities",
1437
+ details: { capabilityChanges },
1438
+ },
1439
+ };
1440
+ }
1441
+
1442
+ const routeVisibilityChanges = diffRouteVisibility(oldBundle?.manifest, bundle.manifest);
1443
+ const hasNewPublicRoutes = routeVisibilityChanges.newlyPublic.length > 0;
1444
+ if (hasNewPublicRoutes && !opts?.confirmRouteVisibilityChanges) {
1445
+ return {
1446
+ success: false,
1447
+ error: {
1448
+ code: "ROUTE_VISIBILITY_ESCALATION",
1449
+ message: "Plugin update exposes new public (unauthenticated) routes",
1450
+ details: { routeVisibilityChanges, capabilityChanges },
1451
+ },
1452
+ };
1453
+ }
1454
+
1455
+ // Store new bundle. R2 prefix is deterministic per (pluginId, version),
1456
+ // so a retry of the same update is idempotent.
1457
+ await storeBundleInR2(storage, pluginId, newVersion, bundle, "registry");
1458
+
1459
+ // Update state. Preserve publisher/slug; refresh displayName /
1460
+ // description from the install handler's seeded values (we don't
1461
+ // re-fetch the profile here — that's a separate `getPackage` round
1462
+ // trip and the install-time values are still authoritative for
1463
+ // the same package identity).
1464
+ await stateRepo.upsert(pluginId, newVersion, "active", {
1465
+ source: "registry",
1466
+ registryPublisherDid: publisherDid,
1467
+ registrySlug: slug,
1468
+ displayName: existing.displayName ?? slug,
1469
+ description: existing.description ?? undefined,
1470
+ });
1471
+
1472
+ // Best-effort cleanup of the old bundle. Failures here don't roll
1473
+ // back the upgrade (the new bundle is already stored and committed
1474
+ // in the state row); the orphan is just storage we'll pay for.
1475
+ deleteBundleFromR2(storage, pluginId, oldVersion, "registry").catch(() => {});
1476
+
1477
+ return {
1478
+ success: true,
1479
+ data: {
1480
+ pluginId,
1481
+ oldVersion,
1482
+ newVersion,
1483
+ capabilityChanges,
1484
+ routeVisibilityChanges: hasNewPublicRoutes ? routeVisibilityChanges : undefined,
1485
+ },
1486
+ };
1487
+ } catch (err) {
1488
+ if (err instanceof ClientValidationError) {
1489
+ return {
1490
+ success: false,
1491
+ error: {
1492
+ code: "AGGREGATOR_RESPONSE_INVALID",
1493
+ message: `Aggregator returned a response that does not conform to its lexicon (${err.target})`,
1494
+ },
1495
+ };
1496
+ }
1497
+ if (err instanceof ClientResponseError) {
1498
+ return {
1499
+ success: false,
1500
+ error: {
1501
+ code: err.status === 404 ? "AGGREGATOR_NOT_FOUND" : "AGGREGATOR_HTTP_ERROR",
1502
+ message: `Aggregator returned ${err.status}: ${err.error}`,
1503
+ },
1504
+ };
1505
+ }
1506
+ if (err instanceof EmDashStorageError) {
1507
+ return {
1508
+ success: false,
1509
+ error: {
1510
+ code: err.code ?? "STORAGE_ERROR",
1511
+ message: "Storage error while updating plugin",
1512
+ },
1513
+ };
1514
+ }
1515
+ console.error("[registry-update] Failed:", err);
1516
+ return {
1517
+ success: false,
1518
+ error: {
1519
+ code: "UPDATE_FAILED",
1520
+ message: err instanceof Error ? err.message : "Failed to update plugin",
1521
+ },
1522
+ };
1523
+ }
1524
+ }
1525
+
1526
+ // ── Update check ───────────────────────────────────────────────────
1527
+
1528
+ export interface RegistryUpdateCheck {
1529
+ pluginId: string;
1530
+ installed: string;
1531
+ latest: string;
1532
+ hasUpdate: boolean;
1533
+ /**
1534
+ * Both diff fields are `false` here by design: computing them at
1535
+ * update-check time would require downloading both bundles (or
1536
+ * extracting from the signed release extension and the installed
1537
+ * R2 bundle), which is too expensive for a bulk preview. The actual
1538
+ * escalation gate runs at update time in `handleRegistryUpdate`.
1539
+ * Mirrors marketplace's `hasRouteVisibilityChanges: false`.
1540
+ */
1541
+ hasCapabilityChanges: boolean;
1542
+ hasRouteVisibilityChanges: boolean;
1543
+ }
1544
+
1545
+ /**
1546
+ * Bulk update check across every installed registry plugin. Queries the
1547
+ * aggregator for each plugin's latest release and reports `hasUpdate`
1548
+ * based on the version comparison. Plugins whose aggregator lookup fails
1549
+ * (unreachable, delisted, malformed) are skipped silently — one bad
1550
+ * publisher must not blank the whole admin Updates list.
1551
+ */
1552
+ export async function handleRegistryUpdateCheck(
1553
+ db: Kysely<Database>,
1554
+ registryConfigInput: RegistryConfigInput | undefined,
1555
+ ): Promise<ApiResult<{ items: RegistryUpdateCheck[] }>> {
1556
+ const registryConfig = coerceRegistryConfig(registryConfigInput);
1557
+ if (!registryConfig) {
1558
+ return {
1559
+ success: false,
1560
+ error: { code: "REGISTRY_NOT_CONFIGURED", message: "Registry is not configured" },
1561
+ };
1562
+ }
1563
+
1564
+ try {
1565
+ const stateRepo = new PluginStateRepository(db);
1566
+ const registryPlugins = await stateRepo.getRegistryPlugins();
1567
+ if (registryPlugins.length === 0) {
1568
+ return { success: true, data: { items: [] } };
1569
+ }
1570
+
1571
+ const { DiscoveryClient } = await import("@emdash-cms/registry-client/discovery");
1572
+ const aggregatorDeadline = Date.now() + AGGREGATOR_TOTAL_BUDGET_MS;
1573
+ const discovery = new DiscoveryClient({
1574
+ aggregatorUrl: registryConfig.aggregatorUrl,
1575
+ acceptLabelers: registryConfig.acceptLabelers,
1576
+ fetch: timedFetch(aggregatorDeadline),
1577
+ });
1578
+
1579
+ const items: RegistryUpdateCheck[] = [];
1580
+ for (const plugin of registryPlugins) {
1581
+ if (!plugin.registryPublisherDid || !plugin.registrySlug) continue;
1582
+ try {
1583
+ const releaseView = await discovery.getLatestRelease({
1584
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- DID string was validated by the install handler
1585
+ did: plugin.registryPublisherDid as Did,
1586
+ package: plugin.registrySlug,
1587
+ });
1588
+ const latest = releaseView.version;
1589
+ if (!latest) continue;
1590
+ const installed = plugin.version;
1591
+ items.push({
1592
+ pluginId: plugin.pluginId,
1593
+ installed,
1594
+ latest,
1595
+ hasUpdate: latest !== installed,
1596
+ hasCapabilityChanges: false,
1597
+ hasRouteVisibilityChanges: false,
1598
+ });
1599
+ } catch (err) {
1600
+ // Skip plugins that can't be checked. Don't fail the whole
1601
+ // list because one aggregator query went wrong.
1602
+ console.warn(`[registry-update-check] Skipped ${plugin.pluginId}:`, err);
1603
+ }
1604
+ }
1605
+
1606
+ return { success: true, data: { items } };
1607
+ } catch (err) {
1608
+ if (err instanceof ClientValidationError) {
1609
+ return {
1610
+ success: false,
1611
+ error: {
1612
+ code: "AGGREGATOR_RESPONSE_INVALID",
1613
+ message: `Aggregator returned a response that does not conform to its lexicon (${err.target})`,
1614
+ },
1615
+ };
1616
+ }
1617
+ if (err instanceof ClientResponseError) {
1618
+ return {
1619
+ success: false,
1620
+ error: {
1621
+ code: err.status === 404 ? "AGGREGATOR_NOT_FOUND" : "AGGREGATOR_HTTP_ERROR",
1622
+ message: `Aggregator returned ${err.status}: ${err.error}`,
1623
+ },
1624
+ };
1625
+ }
1626
+ console.error("[registry-update-check] Failed:", err);
1627
+ return {
1628
+ success: false,
1629
+ error: { code: "UPDATE_CHECK_FAILED", message: "Failed to check for registry updates" },
1630
+ };
1631
+ }
1632
+ }
@@ -2379,7 +2379,7 @@ export function generateOpenApiDocument(
2379
2379
  },
2380
2380
  },
2381
2381
  security: [{ session: [] }, { bearer: [] }],
2382
- // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- readonly const paths are compatible at runtime
2382
+ // eslint-disable-next-line typescript/no-unsafe-type-assertion -- readonly const paths are compatible at runtime
2383
2383
  paths: buildAllPaths(maxUploadSize) as unknown as ZodOpenApiPathsObject,
2384
2384
  });
2385
2385
  }