emdash 0.35.0 → 0.36.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 (763) 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-CzL3H752.d.mts} +3 -3
  4. package/dist/{adapters-Bb1vG41D.d.mts.map → adapters-CzL3H752.d.mts.map} +1 -1
  5. package/dist/{allowed-origins-DW7sYyqg.mjs → allowed-origins-maylGaHv.mjs} +2 -2
  6. package/dist/{allowed-origins-DW7sYyqg.mjs.map → allowed-origins-maylGaHv.mjs.map} +1 -1
  7. package/dist/api/route-utils.d.mts +3 -3
  8. package/dist/api/route-utils.mjs +22 -20
  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-B0w3uBiG.mjs +2269 -0
  13. package/dist/api-B0w3uBiG.mjs.map +1 -0
  14. package/dist/{api-tokens-KO24G1Fd.mjs → api-tokens-9YrrCoE6.mjs} +2 -2
  15. package/dist/{api-tokens-KO24G1Fd.mjs.map → api-tokens-9YrrCoE6.mjs.map} +1 -1
  16. package/dist/{apply-kUDt80-G.mjs → apply-B_VMpJ2P.mjs} +34 -35
  17. package/dist/{apply-kUDt80-G.mjs.map → apply-B_VMpJ2P.mjs.map} +1 -1
  18. package/dist/astro/index.d.mts +12 -12
  19. package/dist/astro/index.mjs +26 -15
  20. package/dist/astro/index.mjs.map +1 -1
  21. package/dist/astro/middleware/auth.d.mts +10 -10
  22. package/dist/astro/middleware/auth.d.mts.map +1 -1
  23. package/dist/astro/middleware/auth.mjs +10 -7
  24. package/dist/astro/middleware/auth.mjs.map +1 -1
  25. package/dist/astro/middleware/media-usage-write-fence.mjs +2 -2
  26. package/dist/astro/middleware/redirect.mjs +4 -4
  27. package/dist/astro/middleware/request-context.mjs +3 -3
  28. package/dist/astro/middleware/setup.mjs +1 -1
  29. package/dist/astro/middleware.d.mts +11 -12
  30. package/dist/astro/middleware.d.mts.map +1 -1
  31. package/dist/astro/middleware.mjs +168 -1305
  32. package/dist/astro/middleware.mjs.map +1 -1
  33. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +6 -6
  34. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +6 -6
  35. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +3 -3
  36. package/dist/astro/routes/api/admin/api-tokens/index.mjs +4 -4
  37. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +4 -4
  38. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +9 -9
  39. package/dist/astro/routes/api/admin/byline-fields/index.mjs +9 -9
  40. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +9 -9
  41. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +15 -15
  42. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +15 -15
  43. package/dist/astro/routes/api/admin/bylines/index.mjs +15 -15
  44. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +12 -12
  45. package/dist/astro/routes/api/admin/comments/_id_.mjs +4 -4
  46. package/dist/astro/routes/api/admin/comments/bulk.mjs +9 -9
  47. package/dist/astro/routes/api/admin/comments/counts.mjs +4 -4
  48. package/dist/astro/routes/api/admin/comments/index.mjs +9 -9
  49. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +4 -4
  50. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
  51. package/dist/astro/routes/api/admin/media-usage/activation.d.mts +9 -0
  52. package/dist/astro/routes/api/admin/media-usage/activation.d.mts.map +1 -0
  53. package/dist/astro/routes/api/admin/media-usage/activation.mjs +46 -0
  54. package/dist/astro/routes/api/admin/media-usage/activation.mjs.map +1 -0
  55. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +14 -13
  56. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs.map +1 -1
  57. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +14 -13
  58. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs.map +1 -1
  59. package/dist/astro/routes/api/admin/media-usage/progress.d.mts +9 -0
  60. package/dist/astro/routes/api/admin/media-usage/progress.d.mts.map +1 -0
  61. package/dist/astro/routes/api/admin/media-usage/progress.mjs +44 -0
  62. package/dist/astro/routes/api/admin/media-usage/progress.mjs.map +1 -0
  63. package/dist/astro/routes/api/admin/media-usage/repair.mjs +16 -11
  64. package/dist/astro/routes/api/admin/media-usage/repair.mjs.map +1 -1
  65. package/dist/astro/routes/api/admin/media-usage/work/index.mjs +14 -13
  66. package/dist/astro/routes/api/admin/media-usage/work/index.mjs.map +1 -1
  67. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +14 -13
  68. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs.map +1 -1
  69. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +3 -3
  70. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +3 -3
  71. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +54 -48
  72. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  73. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +54 -48
  74. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  75. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +52 -46
  76. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  77. package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +4 -4
  78. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +52 -46
  79. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
  80. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +53 -47
  81. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  82. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +53 -47
  83. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  84. package/dist/astro/routes/api/admin/plugins/index.mjs +52 -46
  85. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  86. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +2 -2
  87. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +52 -46
  88. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  89. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +53 -47
  90. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  91. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +52 -46
  92. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  93. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +53 -47
  94. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  95. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +54 -48
  96. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  97. package/dist/astro/routes/api/admin/plugins/registry/artifact.d.mts.map +1 -1
  98. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +172 -133
  99. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  100. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +54 -48
  101. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  102. package/dist/astro/routes/api/admin/plugins/updates.mjs +52 -46
  103. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  104. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +52 -46
  105. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  106. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +2 -2
  107. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +52 -46
  108. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  109. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +2 -2
  110. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +1 -1
  111. package/dist/astro/routes/api/admin/users/_id_/index.mjs +7 -7
  112. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +3 -3
  113. package/dist/astro/routes/api/admin/users/index.mjs +6 -6
  114. package/dist/astro/routes/api/auth/dev-bypass.mjs +3 -3
  115. package/dist/astro/routes/api/auth/invite/accept.mjs +1 -1
  116. package/dist/astro/routes/api/auth/invite/complete.mjs +11 -11
  117. package/dist/astro/routes/api/auth/invite/index.mjs +8 -8
  118. package/dist/astro/routes/api/auth/invite/register-options.mjs +10 -10
  119. package/dist/astro/routes/api/auth/logout.mjs +2 -2
  120. package/dist/astro/routes/api/auth/magic-link/send.mjs +10 -10
  121. package/dist/astro/routes/api/auth/magic-link/verify.mjs +2 -2
  122. package/dist/astro/routes/api/auth/me.d.mts.map +1 -1
  123. package/dist/astro/routes/api/auth/me.mjs +19 -9
  124. package/dist/astro/routes/api/auth/me.mjs.map +1 -1
  125. package/dist/astro/routes/api/auth/mode.mjs +2 -2
  126. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
  127. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  128. package/dist/astro/routes/api/auth/passkey/_id_.mjs +6 -6
  129. package/dist/astro/routes/api/auth/passkey/index.mjs +1 -1
  130. package/dist/astro/routes/api/auth/passkey/options.mjs +12 -12
  131. package/dist/astro/routes/api/auth/passkey/register/options.mjs +10 -10
  132. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +11 -11
  133. package/dist/astro/routes/api/auth/passkey/verify.mjs +11 -11
  134. package/dist/astro/routes/api/auth/signup/complete.mjs +11 -11
  135. package/dist/astro/routes/api/auth/signup/request.mjs +10 -10
  136. package/dist/astro/routes/api/auth/signup/verify.mjs +1 -1
  137. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +13 -13
  138. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +12 -12
  139. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +2 -2
  140. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +3 -3
  141. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
  142. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +2 -2
  143. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +11 -11
  144. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +8 -8
  145. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +16 -14
  146. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
  147. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +16 -14
  148. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
  149. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
  150. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +2 -2
  151. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +8 -8
  152. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +13 -13
  153. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +2 -2
  154. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +3 -3
  155. package/dist/astro/routes/api/content/_collection_/_id_.mjs +8 -8
  156. package/dist/astro/routes/api/content/_collection_/authors.mjs +2 -2
  157. package/dist/astro/routes/api/content/_collection_/index.mjs +8 -8
  158. package/dist/astro/routes/api/content/_collection_/trash.mjs +7 -7
  159. package/dist/astro/routes/api/dashboard.mjs +7 -7
  160. package/dist/astro/routes/api/dev/emails.mjs +2 -2
  161. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  162. package/dist/astro/routes/api/import/probe.mjs +16 -16
  163. package/dist/astro/routes/api/import/wordpress/analyze.mjs +2 -2
  164. package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -11
  165. package/dist/astro/routes/api/import/wordpress/execute.mjs +12 -12
  166. package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -10
  167. package/dist/astro/routes/api/import/wordpress/media.mjs +11 -11
  168. package/dist/astro/routes/api/import/wordpress/prepare.mjs +9 -9
  169. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +11 -11
  170. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +12 -10
  171. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
  172. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  173. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +16 -16
  174. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +11 -11
  175. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +26 -26
  176. package/dist/astro/routes/api/manifest.mjs +4 -4
  177. package/dist/astro/routes/api/mcp.mjs +42 -42
  178. package/dist/astro/routes/api/media/_id_/confirm.mjs +11 -11
  179. package/dist/astro/routes/api/media/_id_/upload.mjs +6 -6
  180. package/dist/astro/routes/api/media/_id_/usage.mjs +18 -13
  181. package/dist/astro/routes/api/media/_id_/usage.mjs.map +1 -1
  182. package/dist/astro/routes/api/media/_id_.d.mts.map +1 -1
  183. package/dist/astro/routes/api/media/_id_.mjs +21 -13
  184. package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
  185. package/dist/astro/routes/api/media/file/_...key_.mjs +1 -1
  186. package/dist/astro/routes/api/media/folders/_id_.d.mts +10 -0
  187. package/dist/astro/routes/api/media/folders/_id_.d.mts.map +1 -0
  188. package/dist/astro/routes/api/media/folders/_id_.mjs +52 -0
  189. package/dist/astro/routes/api/media/folders/_id_.mjs.map +1 -0
  190. package/dist/astro/routes/api/media/folders/index.d.mts +9 -0
  191. package/dist/astro/routes/api/media/folders/index.d.mts.map +1 -0
  192. package/dist/astro/routes/api/media/folders/index.mjs +41 -0
  193. package/dist/astro/routes/api/media/folders/index.mjs.map +1 -0
  194. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +2 -2
  195. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +2 -2
  196. package/dist/astro/routes/api/media/providers/index.mjs +2 -2
  197. package/dist/astro/routes/api/media/upload-url.mjs +9 -9
  198. package/dist/astro/routes/api/media.d.mts.map +1 -1
  199. package/dist/astro/routes/api/media.mjs +28 -19
  200. package/dist/astro/routes/api/media.mjs.map +1 -1
  201. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +8 -8
  202. package/dist/astro/routes/api/menus/_name_/items.mjs +8 -8
  203. package/dist/astro/routes/api/menus/_name_/reorder.mjs +8 -8
  204. package/dist/astro/routes/api/menus/_name_/translations.mjs +8 -8
  205. package/dist/astro/routes/api/menus/_name_.mjs +8 -8
  206. package/dist/astro/routes/api/menus/index.mjs +8 -8
  207. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  208. package/dist/astro/routes/api/oauth/device/authorize.mjs +5 -5
  209. package/dist/astro/routes/api/oauth/device/code.mjs +8 -8
  210. package/dist/astro/routes/api/oauth/device/token.mjs +7 -7
  211. package/dist/astro/routes/api/oauth/register.mjs +2 -2
  212. package/dist/astro/routes/api/oauth/token/refresh.mjs +5 -5
  213. package/dist/astro/routes/api/oauth/token/revoke.mjs +5 -5
  214. package/dist/astro/routes/api/oauth/token.mjs +5 -5
  215. package/dist/astro/routes/api/openapi.json.mjs +153 -6
  216. package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
  217. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +4 -4
  218. package/dist/astro/routes/api/redirects/404s/index.mjs +10 -10
  219. package/dist/astro/routes/api/redirects/404s/summary.mjs +10 -10
  220. package/dist/astro/routes/api/redirects/_id_.mjs +11 -11
  221. package/dist/astro/routes/api/redirects/index.mjs +11 -11
  222. package/dist/astro/routes/api/relations/_id_/index.mjs +16 -14
  223. package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
  224. package/dist/astro/routes/api/relations/_id_/translations.mjs +11 -9
  225. package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -1
  226. package/dist/astro/routes/api/relations/index.mjs +16 -14
  227. package/dist/astro/routes/api/relations/index.mjs.map +1 -1
  228. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +2 -2
  229. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
  230. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +52 -46
  231. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  232. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +52 -46
  233. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  234. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +52 -46
  235. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  236. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +52 -46
  237. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  238. package/dist/astro/routes/api/schema/collections/index.mjs +52 -46
  239. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  240. package/dist/astro/routes/api/schema/collections/reorder.mjs +52 -46
  241. package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
  242. package/dist/astro/routes/api/schema/index.mjs +10 -8
  243. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  244. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +52 -46
  245. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  246. package/dist/astro/routes/api/schema/orphans/index.mjs +52 -46
  247. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  248. package/dist/astro/routes/api/search/enable.mjs +10 -10
  249. package/dist/astro/routes/api/search/index.mjs +9 -9
  250. package/dist/astro/routes/api/search/rebuild.mjs +10 -10
  251. package/dist/astro/routes/api/search/stats.mjs +5 -5
  252. package/dist/astro/routes/api/search/suggest.mjs +9 -9
  253. package/dist/astro/routes/api/sections/_slug_.mjs +9 -9
  254. package/dist/astro/routes/api/sections/index.mjs +9 -9
  255. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +6 -6
  256. package/dist/astro/routes/api/settings/backups/archives/index.mjs +5 -5
  257. package/dist/astro/routes/api/settings/backups/export.mjs +6 -6
  258. package/dist/astro/routes/api/settings/backups/index.mjs +7 -7
  259. package/dist/astro/routes/api/settings/email.mjs +4 -4
  260. package/dist/astro/routes/api/settings.mjs +13 -13
  261. package/dist/astro/routes/api/setup/admin-verify.mjs +12 -12
  262. package/dist/astro/routes/api/setup/admin.mjs +11 -11
  263. package/dist/astro/routes/api/setup/dev-bypass.d.mts.map +1 -1
  264. package/dist/astro/routes/api/setup/dev-bypass.mjs +34 -27
  265. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  266. package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
  267. package/dist/astro/routes/api/setup/index.mjs +31 -29
  268. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  269. package/dist/astro/routes/api/setup/status.mjs +3 -3
  270. package/dist/astro/routes/api/snapshot.mjs +7 -7
  271. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +13 -13
  272. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +13 -13
  273. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +13 -13
  274. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +13 -13
  275. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +13 -13
  276. package/dist/astro/routes/api/taxonomies/_name_.mjs +13 -13
  277. package/dist/astro/routes/api/taxonomies/index.mjs +13 -13
  278. package/dist/astro/routes/api/themes/preview.mjs +5 -5
  279. package/dist/astro/routes/api/typegen.mjs +4 -4
  280. package/dist/astro/routes/api/well-known/auth.mjs +2 -2
  281. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  282. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  283. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +7 -7
  284. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +10 -10
  285. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +10 -10
  286. package/dist/astro/routes/api/widget-areas/_name_.mjs +5 -5
  287. package/dist/astro/routes/api/widget-areas/index.mjs +10 -10
  288. package/dist/astro/routes/api/widget-components.mjs +2 -2
  289. package/dist/astro/routes/robots.txt.mjs +6 -6
  290. package/dist/astro/routes/sitemap-_collection_.xml.mjs +9 -9
  291. package/dist/astro/routes/sitemap.xml.mjs +7 -7
  292. package/dist/astro/types.d.mts +19 -14
  293. package/dist/astro/types.d.mts.map +1 -1
  294. package/dist/auth/providers/github.d.mts +1 -1
  295. package/dist/auth/providers/google.d.mts +1 -1
  296. package/dist/{authorize-DUElxgOQ.mjs → authorize-ByYs-Uxs.mjs} +2 -2
  297. package/dist/{authorize-DUElxgOQ.mjs.map → authorize-ByYs-Uxs.mjs.map} +1 -1
  298. package/dist/{backup-DWYpJlLj.mjs → backup-ChyHfIoX.mjs} +5 -5
  299. package/dist/{backup-DWYpJlLj.mjs.map → backup-ChyHfIoX.mjs.map} +1 -1
  300. package/dist/{bundle-vn56sLos.mjs → bundle-DZFhFurR.mjs} +4 -4
  301. package/dist/{bundle-vn56sLos.mjs.map → bundle-DZFhFurR.mjs.map} +1 -1
  302. package/dist/{byline-yjvWq4ip.mjs → byline-Cpnwrje1.mjs} +6 -6
  303. package/dist/{byline-yjvWq4ip.mjs.map → byline-Cpnwrje1.mjs.map} +1 -1
  304. package/dist/{byline-fields-txaLGoME.mjs → byline-fields-CAyA_Umd.mjs} +2 -2
  305. package/dist/{byline-fields-txaLGoME.mjs.map → byline-fields-CAyA_Umd.mjs.map} +1 -1
  306. package/dist/{byline-registry-DDun8sxh.mjs → byline-registry-Bpu9-MVs.mjs} +2 -2
  307. package/dist/{byline-registry-DDun8sxh.mjs.map → byline-registry-Bpu9-MVs.mjs.map} +1 -1
  308. package/dist/{bylines-DjXS5p0P.mjs → bylines-BSo9B9RX.mjs} +7 -7
  309. package/dist/{bylines-DjXS5p0P.mjs.map → bylines-BSo9B9RX.mjs.map} +1 -1
  310. package/dist/{bylines-Bu7pchQ4.mjs → bylines-CHjvehVX.mjs} +3 -3
  311. package/dist/{bylines-Bu7pchQ4.mjs.map → bylines-CHjvehVX.mjs.map} +1 -1
  312. package/dist/{cache-C46-3Irl.mjs → cache-5VirJ2Cn.mjs} +4 -4
  313. package/dist/{cache-C46-3Irl.mjs.map → cache-5VirJ2Cn.mjs.map} +1 -1
  314. package/dist/capture-triggers-CNW1q3HK.mjs +362 -0
  315. package/dist/capture-triggers-CNW1q3HK.mjs.map +1 -0
  316. package/dist/{challenge-store-SIL5DsF2.mjs → challenge-store-D5pSY2S1.mjs} +1 -1
  317. package/dist/{challenge-store-SIL5DsF2.mjs.map → challenge-store-D5pSY2S1.mjs.map} +1 -1
  318. package/dist/{chunks-fiZ8G9RJ.mjs → chunks-bNiX6_DR.mjs} +2 -2
  319. package/dist/{chunks-fiZ8G9RJ.mjs.map → chunks-bNiX6_DR.mjs.map} +1 -1
  320. package/dist/cli/index.mjs +36 -52
  321. package/dist/cli/index.mjs.map +1 -1
  322. package/dist/client/cf-access.d.mts +1 -1
  323. package/dist/client/index.d.mts +74 -4
  324. package/dist/client/index.d.mts.map +1 -1
  325. package/dist/client/index.mjs +54 -2
  326. package/dist/client/index.mjs.map +1 -1
  327. package/dist/{collection-deletion-DQPvMD8R.mjs → collection-deletion-m_oi2c0N.mjs} +13 -356
  328. package/dist/collection-deletion-m_oi2c0N.mjs.map +1 -0
  329. package/dist/{comment-Dxlep6cE.mjs → comment-DhvLEdhQ.mjs} +1 -1
  330. package/dist/{comment-Dxlep6cE.mjs.map → comment-DhvLEdhQ.mjs.map} +1 -1
  331. package/dist/{comment-reaction-D-2J84UE.mjs → comment-reaction-CRuItEjt.mjs} +2 -2
  332. package/dist/{comment-reaction-D-2J84UE.mjs.map → comment-reaction-CRuItEjt.mjs.map} +1 -1
  333. package/dist/{comments-CTfZtLmM.mjs → comments-CLj4bi8I.mjs} +2 -2
  334. package/dist/{comments-CTfZtLmM.mjs.map → comments-CLj4bi8I.mjs.map} +1 -1
  335. package/dist/{components-CQy3lh9x.mjs → components-v4U4DT2y.mjs} +1 -1
  336. package/dist/{components-CQy3lh9x.mjs.map → components-v4U4DT2y.mjs.map} +1 -1
  337. package/dist/{config-COQzTe5Q.d.mts → config-DrfghTPe.d.mts} +1 -1
  338. package/dist/{config-COQzTe5Q.d.mts.map → config-DrfghTPe.d.mts.map} +1 -1
  339. package/dist/{content-ZHCc1ngN.mjs → content-CP-SeXNa.mjs} +5 -4
  340. package/dist/content-CP-SeXNa.mjs.map +1 -0
  341. package/dist/{content-list-query-wJ2WN8Vp.d.mts → content-list-query-BhejKVqb.d.mts} +1 -1
  342. package/dist/{content-list-query-wJ2WN8Vp.d.mts.map → content-list-query-BhejKVqb.d.mts.map} +1 -1
  343. package/dist/{content-refresh-B_8SJzuU.mjs → content-refresh-DLOfIhYc.mjs} +1094 -93
  344. package/dist/content-refresh-DLOfIhYc.mjs.map +1 -0
  345. package/dist/{media-usage-BZCydfvu.mjs → content-repair-BCxzy0r4.mjs} +5 -196
  346. package/dist/content-repair-BCxzy0r4.mjs.map +1 -0
  347. package/dist/{context-ZldbZcle.mjs → context-BR5hRWiK.mjs} +13 -13
  348. package/dist/{context-ZldbZcle.mjs.map → context-BR5hRWiK.mjs.map} +1 -1
  349. package/dist/{cron-Y9aLtgrA.mjs → cron-CWfWrWKG.mjs} +1 -1
  350. package/dist/{cron-Y9aLtgrA.mjs.map → cron-CWfWrWKG.mjs.map} +1 -1
  351. package/dist/{dashboard-DvHbk_cv.mjs → dashboard-CkIV2rnQ.mjs} +5 -5
  352. package/dist/{dashboard-DvHbk_cv.mjs.map → dashboard-CkIV2rnQ.mjs.map} +1 -1
  353. package/dist/db/index.d.mts +3 -3
  354. package/dist/db/index.mjs +3 -3
  355. package/dist/db/index.mjs.map +1 -1
  356. package/dist/db/libsql-migrations.d.mts +1 -1
  357. package/dist/db/libsql-migrations.mjs +4 -4
  358. package/dist/db/libsql.d.mts +1 -1
  359. package/dist/db/postgres-migrations.d.mts +1 -1
  360. package/dist/db/postgres-migrations.mjs +4 -4
  361. package/dist/db/postgres.d.mts +1 -1
  362. package/dist/db/sqlite-migrations.d.mts +1 -1
  363. package/dist/db/sqlite-migrations.mjs +4 -4
  364. package/dist/db/sqlite.d.mts +1 -1
  365. package/dist/db/sqlite.mjs +3 -3
  366. package/dist/db/sqlite.mjs.map +1 -1
  367. package/dist/{default-DdDl3fxv.mjs → default-YMEfcQUx.mjs} +1 -1
  368. package/dist/{default-DdDl3fxv.mjs.map → default-YMEfcQUx.mjs.map} +1 -1
  369. package/dist/{deferred-tasks-SDWxrgzJ.d.mts → deferred-tasks-DfqxH5Xf.d.mts} +1 -1
  370. package/dist/{deferred-tasks-SDWxrgzJ.d.mts.map → deferred-tasks-DfqxH5Xf.d.mts.map} +1 -1
  371. package/dist/{device-flow-C0GdD_z8.mjs → device-flow-CojjSBwb.mjs} +5 -5
  372. package/dist/{device-flow-C0GdD_z8.mjs.map → device-flow-CojjSBwb.mjs.map} +1 -1
  373. package/dist/{direct-executor-CDXeJCSs.mjs → direct-executor-BWeWiRYB.mjs} +3 -3
  374. package/dist/{direct-executor-CDXeJCSs.mjs.map → direct-executor-BWeWiRYB.mjs.map} +1 -1
  375. package/dist/{dist-D_6CKR8z.mjs → dist-89xCrGqi.mjs} +1 -1
  376. package/dist/{dist-D_6CKR8z.mjs.map → dist-89xCrGqi.mjs.map} +1 -1
  377. package/dist/{email-console-BHNjIwiB.mjs → email-console-CEJgR_LB.mjs} +1 -1
  378. package/dist/{email-console-BHNjIwiB.mjs.map → email-console-CEJgR_LB.mjs.map} +1 -1
  379. package/dist/{enrich-_ySMEvEE.mjs → enrich-BX0IDp4z.mjs} +3 -3
  380. package/dist/{enrich-_ySMEvEE.mjs.map → enrich-BX0IDp4z.mjs.map} +1 -1
  381. package/dist/{error-DupyJZE2.mjs → error-D9w94fjV.mjs} +2 -2
  382. package/dist/{error-DupyJZE2.mjs.map → error-D9w94fjV.mjs.map} +1 -1
  383. package/dist/{errors-CLUPm7aD.mjs → errors-n2j49uNf.mjs} +22 -2
  384. package/dist/errors-n2j49uNf.mjs.map +1 -0
  385. package/dist/{escape-DUY2r2Zs.mjs → escape-DN4Qmjsl.mjs} +1 -1
  386. package/dist/{escape-DUY2r2Zs.mjs.map → escape-DN4Qmjsl.mjs.map} +1 -1
  387. package/dist/{field-defs-cache-BzwBlJrR.mjs → field-defs-cache-Bh4q6oar.mjs} +5 -5
  388. package/dist/{field-defs-cache-BzwBlJrR.mjs.map → field-defs-cache-Bh4q6oar.mjs.map} +1 -1
  389. package/dist/focal-point-BeWFo6Xx.mjs +23 -0
  390. package/dist/focal-point-BeWFo6Xx.mjs.map +1 -0
  391. package/dist/{fts-manager-DyZEohZC.mjs → fts-manager-BhOdW0bi.mjs} +3 -3
  392. package/dist/{fts-manager-DyZEohZC.mjs.map → fts-manager-BhOdW0bi.mjs.map} +1 -1
  393. package/dist/{hash-Cg0TXJPV.mjs → hash-CTcngWvj.mjs} +1 -1
  394. package/dist/{hash-Cg0TXJPV.mjs.map → hash-CTcngWvj.mjs.map} +1 -1
  395. package/dist/{hreflang-DwT2E0Sa.d.mts → hreflang-7pTHsLZJ.d.mts} +2 -2
  396. package/dist/{hreflang-DwT2E0Sa.d.mts.map → hreflang-7pTHsLZJ.d.mts.map} +1 -1
  397. package/dist/{hreflang-BBe83kKa.mjs → hreflang-Huc6O5wa.mjs} +7 -7
  398. package/dist/{hreflang-BBe83kKa.mjs.map → hreflang-Huc6O5wa.mjs.map} +1 -1
  399. package/dist/{identity-Ys6Dlc9C.mjs → identity-DXmb4aVp.mjs} +3 -3
  400. package/dist/{identity-Ys6Dlc9C.mjs.map → identity-DXmb4aVp.mjs.map} +1 -1
  401. package/dist/{import-DPkLmeXO.mjs → import-C4_O3KXU.mjs} +5 -5
  402. package/dist/{import-DPkLmeXO.mjs.map → import-C4_O3KXU.mjs.map} +1 -1
  403. package/dist/{index-C9KuQyO-.d.mts → index-6bRee8zb.d.mts} +3 -3
  404. package/dist/{index-C9KuQyO-.d.mts.map → index-6bRee8zb.d.mts.map} +1 -1
  405. package/dist/{index-BVBZj4-7.d.mts → index-DWbJrsAg.d.mts} +128 -52
  406. package/dist/index-DWbJrsAg.d.mts.map +1 -0
  407. package/dist/index.d.mts +21 -21
  408. package/dist/index.mjs +78 -72
  409. package/dist/{init-lock-6b309ZrF.mjs → init-lock-DJkX6Hto.mjs} +1 -1
  410. package/dist/{init-lock-6b309ZrF.mjs.map → init-lock-DJkX6Hto.mjs.map} +1 -1
  411. package/dist/{load-YJ2xl3ra.mjs → load-Bo7fZAbg.mjs} +2 -2
  412. package/dist/{load-YJ2xl3ra.mjs.map → load-Bo7fZAbg.mjs.map} +1 -1
  413. package/dist/{loader-CdG_Ci3H.mjs → loader-ZsjE4paL.mjs} +2 -2
  414. package/dist/{loader-CdG_Ci3H.mjs.map → loader-ZsjE4paL.mjs.map} +1 -1
  415. package/dist/{manifest-builder-B252yQUf.mjs → manifest-builder-QXuqvVMP.mjs} +2 -2
  416. package/dist/{manifest-builder-B252yQUf.mjs.map → manifest-builder-QXuqvVMP.mjs.map} +1 -1
  417. package/dist/{manifest-schema-BXbUAHod.mjs → manifest-schema-CUYPfCEH.mjs} +1 -1
  418. package/dist/{manifest-schema-BXbUAHod.mjs.map → manifest-schema-CUYPfCEH.mjs.map} +1 -1
  419. package/dist/media/image-endpoint.mjs +1 -1
  420. package/dist/media/index.d.mts +1 -1
  421. package/dist/media/index.mjs +13 -3
  422. package/dist/media/index.mjs.map +1 -1
  423. package/dist/media/local-runtime.d.mts +14 -12
  424. package/dist/media/local-runtime.d.mts.map +1 -1
  425. package/dist/media/local-runtime.mjs +11 -5
  426. package/dist/media/local-runtime.mjs.map +1 -1
  427. package/dist/{media-BWWWb8kg.mjs → media-BjwNuLEu.mjs} +100 -6
  428. package/dist/media-BjwNuLEu.mjs.map +1 -0
  429. package/dist/{media-CzhAn2--.mjs → media-D6SeAfBl.mjs} +41 -12
  430. package/dist/media-D6SeAfBl.mjs.map +1 -0
  431. package/dist/{media-allowlist-D6x-Us02.mjs → media-allowlist-D35v7bmL.mjs} +3 -2
  432. package/dist/media-allowlist-D35v7bmL.mjs.map +1 -0
  433. package/dist/media-folders-D-0CmRZj.mjs +210 -0
  434. package/dist/media-folders-D-0CmRZj.mjs.map +1 -0
  435. package/dist/{media-upload-CHBVn6m-.mjs → media-upload-C7bLXGcI.mjs} +9 -9
  436. package/dist/{media-upload-CHBVn6m-.mjs.map → media-upload-C7bLXGcI.mjs.map} +1 -1
  437. package/dist/{media-url-BvoX88FA.mjs → media-url-DH7giMx_.mjs} +1 -1
  438. package/dist/{media-url-BvoX88FA.mjs.map → media-url-DH7giMx_.mjs.map} +1 -1
  439. package/dist/media-usage-BTRJvS6V.mjs +1833 -0
  440. package/dist/media-usage-BTRJvS6V.mjs.map +1 -0
  441. package/dist/media-usage-activation-Dx0kPV6b.mjs +78 -0
  442. package/dist/media-usage-activation-Dx0kPV6b.mjs.map +1 -0
  443. package/dist/{media-usage-work-DrCbqBcl.mjs → media-usage-work-C-fhM30c.mjs} +221 -59
  444. package/dist/media-usage-work-C-fhM30c.mjs.map +1 -0
  445. package/dist/{media-usage-work-CLo_6tct.mjs → media-usage-work-DWb2XPMI.mjs} +4 -4
  446. package/dist/{media-usage-work-CLo_6tct.mjs.map → media-usage-work-DWb2XPMI.mjs.map} +1 -1
  447. package/dist/{media-usage-write-fence-aHEgN1zB.mjs → media-usage-write-fence-BwoJVRDC.mjs} +2 -2
  448. package/dist/{media-usage-write-fence-aHEgN1zB.mjs.map → media-usage-write-fence-BwoJVRDC.mjs.map} +1 -1
  449. package/dist/{menus-TCNSd2vp.mjs → menus-CD7EFLwz.mjs} +3 -3
  450. package/dist/{menus-TCNSd2vp.mjs.map → menus-CD7EFLwz.mjs.map} +1 -1
  451. package/dist/{menus-DSo5QeW0.mjs → menus-CNg0QlDt.mjs} +42 -26
  452. package/dist/menus-CNg0QlDt.mjs.map +1 -0
  453. package/dist/migrations/index.d.mts +1 -1
  454. package/dist/migrations/index.mjs +3 -3
  455. package/dist/{mime-DfIVjNkr.mjs → mime-CUIG6x84.mjs} +1 -1
  456. package/dist/mime-CUIG6x84.mjs.map +1 -0
  457. package/dist/{mode-BDoH_WcF.mjs → mode-DaUM_MB2.mjs} +1 -1
  458. package/dist/{mode-BDoH_WcF.mjs.map → mode-DaUM_MB2.mjs.map} +1 -1
  459. package/dist/node-sqlite-compat-Udb4Y-rs.mjs +46 -0
  460. package/dist/node-sqlite-compat-Udb4Y-rs.mjs.map +1 -0
  461. package/dist/{normalize-Bc-s_r-a.mjs → normalize-CSxdKBVa.mjs} +22 -1
  462. package/dist/normalize-CSxdKBVa.mjs.map +1 -0
  463. package/dist/{oauth-authorization-iOikmrJd.mjs → oauth-authorization-Dpsb-fMJ.mjs} +5 -5
  464. package/dist/{oauth-authorization-iOikmrJd.mjs.map → oauth-authorization-Dpsb-fMJ.mjs.map} +1 -1
  465. package/dist/{oauth-clients-CvI0nHMJ.mjs → oauth-clients-Bxnoe_67.mjs} +1 -1
  466. package/dist/{oauth-clients-CvI0nHMJ.mjs.map → oauth-clients-Bxnoe_67.mjs.map} +1 -1
  467. package/dist/{oauth-state-store-Ba8KZlwW.mjs → oauth-state-store-0C4s0K6w.mjs} +1 -1
  468. package/dist/{oauth-state-store-Ba8KZlwW.mjs.map → oauth-state-store-0C4s0K6w.mjs.map} +1 -1
  469. package/dist/{oauth-user-lookup-C5SQwGYC.mjs → oauth-user-lookup-wlGYSeqX.mjs} +1 -1
  470. package/dist/{oauth-user-lookup-C5SQwGYC.mjs.map → oauth-user-lookup-wlGYSeqX.mjs.map} +1 -1
  471. package/dist/object-cache/memory.d.mts +1 -1
  472. package/dist/{options-CBXIHUoT.mjs → options-BHPeIbBd.mjs} +1 -1
  473. package/dist/{options-CBXIHUoT.mjs.map → options-BHPeIbBd.mjs.map} +1 -1
  474. package/dist/{options--hhz-jZ1.d.mts → options-BhZIeFY1.d.mts} +3 -3
  475. package/dist/{options--hhz-jZ1.d.mts.map → options-BhZIeFY1.d.mts.map} +1 -1
  476. package/dist/page/index.d.mts +2 -2
  477. package/dist/{parse-DFbuc-Fh.mjs → parse-BRJg1kz8.mjs} +2 -2
  478. package/dist/{parse-DFbuc-Fh.mjs.map → parse-BRJg1kz8.mjs.map} +1 -1
  479. package/dist/{passkey-config-DFAmUyuE.mjs → passkey-config-B3P0nHRR.mjs} +1 -1
  480. package/dist/{passkey-config-DFAmUyuE.mjs.map → passkey-config-B3P0nHRR.mjs.map} +1 -1
  481. package/dist/{patterns-CiyXeDgr.mjs → patterns-D9iDO3j8.mjs} +1 -1
  482. package/dist/{patterns-CiyXeDgr.mjs.map → patterns-D9iDO3j8.mjs.map} +1 -1
  483. package/dist/{placeholder-Dp0K3RkD.d.mts → placeholder-BR4ZhVJl.d.mts} +7 -1
  484. package/dist/placeholder-BR4ZhVJl.d.mts.map +1 -0
  485. package/dist/plugin-types.d.mts +1 -1
  486. package/dist/plugin-utils.d.mts +10 -10
  487. package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
  488. package/dist/plugins/adapt-sandbox-entry.mjs +2 -2
  489. package/dist/{policy-TluUIxuu.mjs → policy-BVRganJQ.mjs} +2 -2
  490. package/dist/{policy-TluUIxuu.mjs.map → policy-BVRganJQ.mjs.map} +1 -1
  491. package/dist/{portable-text-imBW5cHK.mjs → portable-text-C8Tvp4_g.mjs} +1 -1
  492. package/dist/{portable-text-imBW5cHK.mjs.map → portable-text-C8Tvp4_g.mjs.map} +1 -1
  493. package/dist/{preview-PW-nOnq4.mjs → preview-dn2dUyM0.mjs} +2 -2
  494. package/dist/{preview-PW-nOnq4.mjs.map → preview-dn2dUyM0.mjs.map} +1 -1
  495. package/dist/{protocol-DjsJHTlK.d.mts → protocol-CuBEsqgE.d.mts} +2 -2
  496. package/dist/{protocol-DjsJHTlK.d.mts.map → protocol-CuBEsqgE.d.mts.map} +1 -1
  497. package/dist/{public-url-CWoFhQT8.mjs → public-url-DRz_AinV.mjs} +1 -1
  498. package/dist/{public-url-CWoFhQT8.mjs.map → public-url-DRz_AinV.mjs.map} +1 -1
  499. package/dist/{query-zTVAR1Sl.mjs → query-D18vTdha.mjs} +14 -14
  500. package/dist/{query-zTVAR1Sl.mjs.map → query-D18vTdha.mjs.map} +1 -1
  501. package/dist/{query-BWs7O5Il.mjs → query-tZDEdtCN.mjs} +4 -4
  502. package/dist/{query-BWs7O5Il.mjs.map → query-tZDEdtCN.mjs.map} +1 -1
  503. package/dist/{rate-limit-Bx4g9m3p.mjs → rate-limit-on7KPo-v.mjs} +2 -2
  504. package/dist/{rate-limit-Bx4g9m3p.mjs.map → rate-limit-on7KPo-v.mjs.map} +1 -1
  505. package/dist/{redirect-COsS6SWJ.mjs → redirect-CZkbozu9.mjs} +2 -2
  506. package/dist/{redirect-COsS6SWJ.mjs.map → redirect-CZkbozu9.mjs.map} +1 -1
  507. package/dist/{redirect-BgAOGHDq.mjs → redirect-DrbEmU9a.mjs} +1 -1
  508. package/dist/{redirect-BgAOGHDq.mjs.map → redirect-DrbEmU9a.mjs.map} +1 -1
  509. package/dist/{redirects-DyChwDkG.mjs → redirects-BahWiu8Z.mjs} +5 -5
  510. package/dist/{redirects-DyChwDkG.mjs.map → redirects-BahWiu8Z.mjs.map} +1 -1
  511. package/dist/{redirects-DTDHWH31.mjs → redirects-CRIM55KH.mjs} +6 -6
  512. package/dist/{redirects-DTDHWH31.mjs.map → redirects-CRIM55KH.mjs.map} +1 -1
  513. package/dist/{api-BeBglVxU.mjs → registry-BiO5WwPq.mjs} +483 -2462
  514. package/dist/registry-BiO5WwPq.mjs.map +1 -0
  515. package/dist/{registry-Cqa2I749.mjs → registry-Cx-jEJOS.mjs} +9 -123
  516. package/dist/registry-Cx-jEJOS.mjs.map +1 -0
  517. package/dist/{relation-BnHB0T4J.mjs → relation-A6wLF_DS.mjs} +2 -2
  518. package/dist/{relation-BnHB0T4J.mjs.map → relation-A6wLF_DS.mjs.map} +1 -1
  519. package/dist/{relations-BBApI4e2.mjs → relations-BTPM2saV.mjs} +2 -2
  520. package/dist/{relations-BBApI4e2.mjs.map → relations-BTPM2saV.mjs.map} +1 -1
  521. package/dist/{relations-BHo5A8Zf.d.mts → relations-C7B46bcU.d.mts} +192 -33
  522. package/dist/relations-C7B46bcU.d.mts.map +1 -0
  523. package/dist/{relations-D5sM5fW0.mjs → relations-Cj5hZ6Zg.mjs} +4 -4
  524. package/dist/{relations-D5sM5fW0.mjs.map → relations-Cj5hZ6Zg.mjs.map} +1 -1
  525. package/dist/{request-cache-BSUptuJR.mjs → request-cache-DH9zdCOD.mjs} +1 -1
  526. package/dist/{request-cache-BSUptuJR.mjs.map → request-cache-DH9zdCOD.mjs.map} +1 -1
  527. package/dist/request-context.d.mts +1 -1
  528. package/dist/{request-meta-DgZJh3zG.mjs → request-meta-DRp5ENd_.mjs} +2 -2
  529. package/dist/{request-meta-DgZJh3zG.mjs.map → request-meta-DRp5ENd_.mjs.map} +1 -1
  530. package/dist/{resolve-DOhVEvty.mjs → resolve-DxUpTMmE.mjs} +1 -1
  531. package/dist/{resolve-DOhVEvty.mjs.map → resolve-DxUpTMmE.mjs.map} +1 -1
  532. package/dist/{runner-C1T11CfC.mjs → runner-77GOZCnH.mjs} +410 -286
  533. package/dist/runner-77GOZCnH.mjs.map +1 -0
  534. package/dist/{runner-BYHZn3Jy.d.mts → runner-zgqA_CqP.d.mts} +2 -2
  535. package/dist/{runner-BYHZn3Jy.d.mts.map → runner-zgqA_CqP.d.mts.map} +1 -1
  536. package/dist/runtime.d.mts +11 -11
  537. package/dist/runtime.mjs +1 -1
  538. package/dist/{schema-DZ5YVVZj.mjs → schema-BY-oVntF.mjs} +3 -3
  539. package/dist/{schema-DZ5YVVZj.mjs.map → schema-BY-oVntF.mjs.map} +1 -1
  540. package/dist/{schema-2AOsSn2v.mjs → schema-Cw9kVK0I.mjs} +35 -5
  541. package/dist/{schema-2AOsSn2v.mjs.map → schema-Cw9kVK0I.mjs.map} +1 -1
  542. package/dist/{scopes-8ClPF2bC.mjs → scopes-vMR1uIbt.mjs} +3 -3
  543. package/dist/{scopes-8ClPF2bC.mjs.map → scopes-vMR1uIbt.mjs.map} +1 -1
  544. package/dist/{search-u1QYdOCG.mjs → search-CfT3KxO5.mjs} +4 -4
  545. package/dist/{search-u1QYdOCG.mjs.map → search-CfT3KxO5.mjs.map} +1 -1
  546. package/dist/{secrets-BEgsAQEU.mjs → secrets-BH2Qow1-.mjs} +3 -3
  547. package/dist/{secrets-BEgsAQEU.mjs.map → secrets-BH2Qow1-.mjs.map} +1 -1
  548. package/dist/{sections-DmHviGyM.mjs → sections-DTfjyf1z.mjs} +2 -2
  549. package/dist/{sections-DmHviGyM.mjs.map → sections-DTfjyf1z.mjs.map} +1 -1
  550. package/dist/seed/index.d.mts +2 -2
  551. package/dist/seed/index.mjs +24 -22
  552. package/dist/seo/index.d.mts +3 -3
  553. package/dist/seo/index.mjs +16 -14
  554. package/dist/seo/index.mjs.map +1 -1
  555. package/dist/{seo-AFpVvTqr.mjs → seo-BSiTIXzd.mjs} +1 -1
  556. package/dist/{seo-AFpVvTqr.mjs.map → seo-BSiTIXzd.mjs.map} +1 -1
  557. package/dist/{seo-Dq4G-RrO.mjs → seo-Cm-dtvgk.mjs} +2 -2
  558. package/dist/{seo-Dq4G-RrO.mjs.map → seo-Cm-dtvgk.mjs.map} +1 -1
  559. package/dist/{service-BpArayPr.mjs → service-DYsDHEKe.mjs} +3 -3
  560. package/dist/{service-BpArayPr.mjs.map → service-DYsDHEKe.mjs.map} +1 -1
  561. package/dist/{session-user-BEorKVT-.mjs → session-user-CNAfvsdw.mjs} +1 -1
  562. package/dist/{session-user-BEorKVT-.mjs.map → session-user-CNAfvsdw.mjs.map} +1 -1
  563. package/dist/{settings-xRdoUZr0.mjs → settings-BgN-0DT-.mjs} +6 -6
  564. package/dist/{settings-xRdoUZr0.mjs.map → settings-BgN-0DT-.mjs.map} +1 -1
  565. package/dist/{settings-DE9xtzqd.mjs → settings-DjtkUo__.mjs} +3 -3
  566. package/dist/{settings-DE9xtzqd.mjs.map → settings-DjtkUo__.mjs.map} +1 -1
  567. package/dist/{setup-complete-BnT8pq_C.mjs → setup-complete-CcpXaPU7.mjs} +2 -2
  568. package/dist/{setup-complete-BnT8pq_C.mjs.map → setup-complete-CcpXaPU7.mjs.map} +1 -1
  569. package/dist/{setup-nonce-CBitf_oQ.mjs → setup-nonce-Reyw30jg.mjs} +1 -1
  570. package/dist/{setup-nonce-CBitf_oQ.mjs.map → setup-nonce-Reyw30jg.mjs.map} +1 -1
  571. package/dist/{single-flight-cache-B0eLKS6K.mjs → single-flight-cache-BPuGPdcN.mjs} +2 -2
  572. package/dist/{single-flight-cache-B0eLKS6K.mjs.map → single-flight-cache-BPuGPdcN.mjs.map} +1 -1
  573. package/dist/{site-url-DjpIXMXJ.mjs → site-url-Cs_V9n3V.mjs} +3 -3
  574. package/dist/{site-url-DjpIXMXJ.mjs.map → site-url-Cs_V9n3V.mjs.map} +1 -1
  575. package/dist/{snapshot-BBlGkb2q.mjs → snapshot-DSB8P7Lm.mjs} +1 -1
  576. package/dist/{snapshot-BBlGkb2q.mjs.map → snapshot-DSB8P7Lm.mjs.map} +1 -1
  577. package/dist/{ssrf-Cpvg_n3A.mjs → ssrf-DqebVE34.mjs} +21 -5
  578. package/dist/{ssrf-Cpvg_n3A.mjs.map → ssrf-DqebVE34.mjs.map} +1 -1
  579. package/dist/{state-DYwPue40.mjs → state-BJfU9Uzw.mjs} +12 -4
  580. package/dist/state-BJfU9Uzw.mjs.map +1 -0
  581. package/dist/{status-CWVYpbD8.mjs → status-DDu8HIQl.mjs} +1 -1
  582. package/dist/{status-CWVYpbD8.mjs.map → status-DDu8HIQl.mjs.map} +1 -1
  583. package/dist/storage/local.d.mts +1 -1
  584. package/dist/storage/local.mjs +1 -1
  585. package/dist/storage/s3.d.mts +1 -1
  586. package/dist/storage/s3.mjs +1 -1
  587. package/dist/{target-DixqqV5i.mjs → target-D0o26Azo.mjs} +1 -1
  588. package/dist/{target-DixqqV5i.mjs.map → target-D0o26Azo.mjs.map} +1 -1
  589. package/dist/{taxonomies-OHUIiIpI.mjs → taxonomies-CPGxo-bn.mjs} +5 -5
  590. package/dist/{taxonomies-OHUIiIpI.mjs.map → taxonomies-CPGxo-bn.mjs.map} +1 -1
  591. package/dist/{taxonomies-BlrncHi9.mjs → taxonomies-kmyudNGP.mjs} +7 -7
  592. package/dist/{taxonomies-BlrncHi9.mjs.map → taxonomies-kmyudNGP.mjs.map} +1 -1
  593. package/dist/{taxonomy-BqCZ1TdU.mjs → taxonomy-8X09dLN5.mjs} +4 -4
  594. package/dist/{taxonomy-BqCZ1TdU.mjs.map → taxonomy-8X09dLN5.mjs.map} +1 -1
  595. package/dist/{tokens-C39klX8R.mjs → tokens-gTS-IVUp.mjs} +1 -1
  596. package/dist/{tokens-C39klX8R.mjs.map → tokens-gTS-IVUp.mjs.map} +1 -1
  597. package/dist/{transaction-NQj4VJ7Z.mjs → transaction-0KOpOyMu.mjs} +2 -1
  598. package/dist/{transaction-NQj4VJ7Z.mjs.map → transaction-0KOpOyMu.mjs.map} +1 -1
  599. package/dist/{transport-RQE36APG.d.mts → transport-_6R1ub7t.d.mts} +1 -1
  600. package/dist/{transport-RQE36APG.d.mts.map → transport-_6R1ub7t.d.mts.map} +1 -1
  601. package/dist/{transport-DBJwa-Si.mjs → transport-fX59xaJz.mjs} +4 -3
  602. package/dist/{transport-DBJwa-Si.mjs.map → transport-fX59xaJz.mjs.map} +1 -1
  603. package/dist/{trusted-proxy-CEVekpby.mjs → trusted-proxy-fe6nEgR4.mjs} +1 -1
  604. package/dist/{trusted-proxy-CEVekpby.mjs.map → trusted-proxy-fe6nEgR4.mjs.map} +1 -1
  605. package/dist/types-75KIqzL9.mjs.map +1 -1
  606. package/dist/{types-BW1syrlw.mjs → types-BXUmsINL.mjs} +1 -1
  607. package/dist/{types-BW1syrlw.mjs.map → types-BXUmsINL.mjs.map} +1 -1
  608. package/dist/{types-BntycPTF.d.mts → types-Blb-MRC3.d.mts} +1 -1
  609. package/dist/{types-BntycPTF.d.mts.map → types-Blb-MRC3.d.mts.map} +1 -1
  610. package/dist/{types-C2pMvO62.d.mts → types-Br-ERaxh.d.mts} +2 -1
  611. package/dist/types-Br-ERaxh.d.mts.map +1 -0
  612. package/dist/{types-DWRhk9xZ.d.mts → types-BzBd3PeX.d.mts} +1 -1
  613. package/dist/{types-DWRhk9xZ.d.mts.map → types-BzBd3PeX.d.mts.map} +1 -1
  614. package/dist/{types-CXnOzDe1.d.mts → types-CLqvnd05.d.mts} +1 -1
  615. package/dist/{types-CXnOzDe1.d.mts.map → types-CLqvnd05.d.mts.map} +1 -1
  616. package/dist/{types-Dfk8KI5R.d.mts → types-D5VVLr7J.d.mts} +1 -1
  617. package/dist/{types-Dfk8KI5R.d.mts.map → types-D5VVLr7J.d.mts.map} +1 -1
  618. package/dist/{types-DQIDRKF2.d.mts → types-DHxzBjbD.d.mts} +10 -1
  619. package/dist/types-DHxzBjbD.d.mts.map +1 -0
  620. package/dist/{types-DN64_zzZ.d.mts → types-DJQxln7q.d.mts} +3 -3
  621. package/dist/{types-DN64_zzZ.d.mts.map → types-DJQxln7q.d.mts.map} +1 -1
  622. package/dist/{types-CtzytVXn.mjs → types-DM3vioBY.mjs} +1 -1
  623. package/dist/{types-CtzytVXn.mjs.map → types-DM3vioBY.mjs.map} +1 -1
  624. package/dist/{types-BcqdcT-r.d.mts → types-D_DWe7k9.d.mts} +1 -1
  625. package/dist/{types-BcqdcT-r.d.mts.map → types-D_DWe7k9.d.mts.map} +1 -1
  626. package/dist/{types-DrJrVCT1.d.mts → types-Vg6f5i3s.d.mts} +3 -3
  627. package/dist/{types-DrJrVCT1.d.mts.map → types-Vg6f5i3s.d.mts.map} +1 -1
  628. package/dist/{upload-attempts-D4FS8LT6.mjs → upload-attempts-CNyGSepg.mjs} +1 -1
  629. package/dist/{upload-attempts-D4FS8LT6.mjs.map → upload-attempts-CNyGSepg.mjs.map} +1 -1
  630. package/dist/{url-pattern-BHS0V5Ng.mjs → url-pattern-K-KdXcSe.mjs} +1 -1
  631. package/dist/{url-pattern-BHS0V5Ng.mjs.map → url-pattern-K-KdXcSe.mjs.map} +1 -1
  632. package/dist/{user-DJZfUJVE.mjs → user-CtYY0tp2.mjs} +2 -2
  633. package/dist/{user-DJZfUJVE.mjs.map → user-CtYY0tp2.mjs.map} +1 -1
  634. package/dist/{utils-D4vD_Y98.mjs → utils-HztC73hq.mjs} +1 -1
  635. package/dist/{utils-D4vD_Y98.mjs.map → utils-HztC73hq.mjs.map} +1 -1
  636. package/dist/{validate-BMLBvxOC.mjs → validate-Dd-IUjnZ.mjs} +2 -2
  637. package/dist/{validate-BMLBvxOC.mjs.map → validate-Dd-IUjnZ.mjs.map} +1 -1
  638. package/dist/{validate-CTqt5nuE.d.mts → validate-DlqdOZXB.d.mts} +5 -5
  639. package/dist/{validate-CTqt5nuE.d.mts.map → validate-DlqdOZXB.d.mts.map} +1 -1
  640. package/dist/{validation-npvENUCB.mjs → validation-D83n7Npi.mjs} +10 -8
  641. package/dist/{validation-npvENUCB.mjs.map → validation-D83n7Npi.mjs.map} +1 -1
  642. package/dist/version-ri-sCyAp.mjs +7 -0
  643. package/dist/{version-DB_fqCSI.mjs.map → version-ri-sCyAp.mjs.map} +1 -1
  644. package/dist/{widgets-BD3ho7Rq.mjs → widgets-CpmZd9Q-.mjs} +4 -4
  645. package/dist/{widgets-BD3ho7Rq.mjs.map → widgets-CpmZd9Q-.mjs.map} +1 -1
  646. package/dist/{wxr-taxonomies-Ca68766D.d.mts → wxr-taxonomies-BFd0y72_.d.mts} +1 -1
  647. package/dist/{wxr-taxonomies-Ca68766D.d.mts.map → wxr-taxonomies-BFd0y72_.d.mts.map} +1 -1
  648. package/dist/{wxr-taxonomies-B1R3vBoD.mjs → wxr-taxonomies-Df4vxWcU.mjs} +4 -4
  649. package/dist/{wxr-taxonomies-B1R3vBoD.mjs.map → wxr-taxonomies-Df4vxWcU.mjs.map} +1 -1
  650. package/dist/{zod-generator-LC-on_Vb.mjs → zod-generator-DylzusHh.mjs} +24 -18
  651. package/dist/zod-generator-DylzusHh.mjs.map +1 -0
  652. package/package.json +16 -8
  653. package/src/api/errors.ts +20 -0
  654. package/src/api/handlers/index.ts +17 -0
  655. package/src/api/handlers/media-allowlist.ts +1 -0
  656. package/src/api/handlers/media-folders.ts +130 -0
  657. package/src/api/handlers/media-usage-activation.ts +102 -0
  658. package/src/api/handlers/media-usage.ts +108 -0
  659. package/src/api/handlers/media.ts +62 -2
  660. package/src/api/handlers/registry.ts +134 -316
  661. package/src/api/openapi/document.ts +192 -2
  662. package/src/api/schemas/media-usage.ts +77 -0
  663. package/src/api/schemas/media.ts +69 -0
  664. package/src/astro/integration/routes.ts +18 -0
  665. package/src/astro/integration/vite-config.ts +2 -7
  666. package/src/astro/middleware/auth.ts +4 -0
  667. package/src/astro/middleware.ts +0 -7
  668. package/src/astro/routes/api/admin/media-usage/activation.ts +42 -0
  669. package/src/astro/routes/api/admin/media-usage/progress.ts +37 -0
  670. package/src/astro/routes/api/admin/plugins/registry/artifact.ts +246 -96
  671. package/src/astro/routes/api/auth/me.ts +14 -2
  672. package/src/astro/routes/api/media/[id].ts +3 -0
  673. package/src/astro/routes/api/media/folders/[id].ts +55 -0
  674. package/src/astro/routes/api/media/folders/index.ts +37 -0
  675. package/src/astro/routes/api/media.ts +12 -2
  676. package/src/astro/routes/api/setup/dev-bypass.ts +12 -0
  677. package/src/astro/types.ts +11 -1
  678. package/src/client/index.ts +140 -2
  679. package/src/client/transport.ts +6 -2
  680. package/src/components/EmDashImage.astro +154 -50
  681. package/src/components/Gallery.astro +7 -0
  682. package/src/components/InlinePortableTextEditor.tsx +130 -1
  683. package/src/components/LiveSearch.astro +23 -0
  684. package/src/components/inline-code-block.tsx +180 -49
  685. package/src/content/converters/gallery.ts +2 -0
  686. package/src/content/converters/types.ts +2 -0
  687. package/src/database/connection.ts +2 -31
  688. package/src/database/index.ts +1 -1
  689. package/src/database/json-recordset.ts +16 -0
  690. package/src/database/migrations/019_i18n.ts +1 -1
  691. package/src/database/migrations/071_restore_content_bylines_table.ts +43 -0
  692. package/src/database/migrations/072_media_folders.ts +72 -0
  693. package/src/database/migrations/073_media_focal_point.ts +57 -0
  694. package/src/database/migrations/runner.ts +8 -2
  695. package/src/database/repositories/content.ts +5 -4
  696. package/src/database/repositories/media-folders.ts +115 -0
  697. package/src/database/repositories/media-usage-work.ts +395 -111
  698. package/src/database/repositories/media-usage.ts +1038 -10
  699. package/src/database/repositories/media.ts +97 -29
  700. package/src/database/transaction.ts +1 -0
  701. package/src/database/types.ts +13 -0
  702. package/src/db/adapters.ts +2 -2
  703. package/src/db/node-sqlite-compat.ts +78 -0
  704. package/src/db/sqlite.ts +3 -3
  705. package/src/emdash-runtime.ts +110 -105
  706. package/src/fields/image.ts +7 -1
  707. package/src/fields/types.ts +6 -2
  708. package/src/index.ts +5 -0
  709. package/src/media/focal-point.ts +37 -0
  710. package/src/media/local-runtime.ts +8 -0
  711. package/src/media/mime.ts +1 -0
  712. package/src/media/normalize.ts +10 -0
  713. package/src/media/types.ts +10 -0
  714. package/src/media/usage/activation.ts +162 -35
  715. package/src/media/usage/capture-triggers.ts +19 -3
  716. package/src/media/usage/collection-deletion-processor.ts +7 -3
  717. package/src/media/usage/collection-deletion.ts +10 -0
  718. package/src/media/usage/content-refresh.ts +258 -39
  719. package/src/media/usage/content-snapshots.ts +128 -31
  720. package/src/media/usage/extractor.ts +32 -13
  721. package/src/media/usage/maintenance-engine.ts +166 -0
  722. package/src/media/usage/reconciliation-processor.ts +106 -29
  723. package/src/media/usage/reconciliation.ts +90 -7
  724. package/src/media/usage/work-processor.ts +342 -101
  725. package/src/plugins/index.ts +1 -0
  726. package/src/plugins/save-rejection.ts +20 -0
  727. package/src/plugins/scheduler/node.ts +1 -13
  728. package/src/plugins/scheduler/types.ts +0 -2
  729. package/src/plugins/state.ts +13 -3
  730. package/src/registry/artifact-fetch.ts +530 -0
  731. package/src/registry/config.ts +24 -6
  732. package/src/registry/types.ts +12 -15
  733. package/src/schema/types.ts +1 -0
  734. package/src/schema/zod-generator.ts +12 -4
  735. package/src/security/ssrf.ts +21 -2
  736. package/src/seed/apply.ts +4 -4
  737. package/src/ui.ts +2 -0
  738. package/dist/api-BeBglVxU.mjs.map +0 -1
  739. package/dist/collection-deletion-DQPvMD8R.mjs.map +0 -1
  740. package/dist/content-ZHCc1ngN.mjs.map +0 -1
  741. package/dist/content-refresh-B_8SJzuU.mjs.map +0 -1
  742. package/dist/errors-CLUPm7aD.mjs.map +0 -1
  743. package/dist/index-BVBZj4-7.d.mts.map +0 -1
  744. package/dist/media-BWWWb8kg.mjs.map +0 -1
  745. package/dist/media-CzhAn2--.mjs.map +0 -1
  746. package/dist/media-allowlist-D6x-Us02.mjs.map +0 -1
  747. package/dist/media-usage-BZCydfvu.mjs.map +0 -1
  748. package/dist/media-usage-work-DrCbqBcl.mjs.map +0 -1
  749. package/dist/menus-DSo5QeW0.mjs.map +0 -1
  750. package/dist/mime-DfIVjNkr.mjs.map +0 -1
  751. package/dist/normalize-Bc-s_r-a.mjs.map +0 -1
  752. package/dist/placeholder-Dp0K3RkD.d.mts.map +0 -1
  753. package/dist/registry-Cqa2I749.mjs.map +0 -1
  754. package/dist/relations-BHo5A8Zf.d.mts.map +0 -1
  755. package/dist/runner-C1T11CfC.mjs.map +0 -1
  756. package/dist/state-DYwPue40.mjs.map +0 -1
  757. package/dist/types-C2pMvO62.d.mts.map +0 -1
  758. package/dist/types-DQIDRKF2.d.mts.map +0 -1
  759. package/dist/version-DB_fqCSI.mjs +0 -7
  760. package/dist/zod-generator-LC-on_Vb.mjs.map +0 -1
  761. /package/dist/{api-tokens-rIXC6LdE.mjs → api-tokens-B5NHLNUN.mjs} +0 -0
  762. /package/dist/{ssrf-DpXgKsna.mjs → ssrf-BPKzkm6O.mjs} +0 -0
  763. /package/dist/{types-CP1CflWf.mjs → types-D6OcIp2P.mjs} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-usage-BTRJvS6V.mjs","names":["retryDelaySeconds","retryDelaySeconds"],"sources":["../src/media/usage/collection-deletion-processor.ts","../src/media/usage/reconciliation.ts","../src/media/usage/reconciliation-processor.ts","../src/media/usage/work-processor.ts","../src/media/usage/maintenance-engine.ts","../src/api/handlers/media-usage.ts"],"sourcesContent":["import { sql, type Kysely, type RawBuilder, type Transaction, type Updateable } from \"kysely\";\n\nimport { isPostgres, tableExists } from \"../../database/dialect-helpers.js\";\nimport { withTransaction } from \"../../database/transaction.js\";\nimport type { Database, MediaUsageCollectionDeletionTable } from \"../../database/types.js\";\nimport {\n\tcollectionDeletionCurrentTimestamp,\n\tdeleteActivatedMediaUsageCollection,\n\tMediaUsageCollectionDeletionRepository,\n\ttype MediaUsageCollectionDeletionRecord,\n} from \"./collection-deletion.js\";\n\nexport const MEDIA_USAGE_COLLECTION_DELETION_LIMITS = Object.freeze({\n\tcandidatesPerTick: 4,\n\trowsPerBatch: 50,\n\tleaseDurationSeconds: 5 * 60,\n\tmaxAttempts: 5,\n\tretryBaseSeconds: 30,\n\tretryMaxSeconds: 15 * 60,\n});\n\nexport interface MediaUsageCollectionDeletionTickResult {\n\tcandidateCount: number;\n\tclaimedCount: number;\n\toutcome: \"idle\" | \"progress\" | \"finalized\" | \"retry\" | \"failed\" | \"claim_lost\";\n}\n\ntype DatabaseExecutor = Kysely<Database> | Transaction<Database>;\n\nexport async function processDueMediaUsageCollectionDeletions(\n\tdb: Kysely<Database>,\n): Promise<MediaUsageCollectionDeletionTickResult> {\n\tconst repository = new MediaUsageCollectionDeletionRepository(db);\n\tconst candidates = await repository.findDue(\n\t\tMEDIA_USAGE_COLLECTION_DELETION_LIMITS.candidatesPerTick,\n\t);\n\tif (candidates.length === 0) {\n\t\treturn {\n\t\t\tcandidateCount: (await repository.hasNonterminal()) ? 1 : 0,\n\t\t\tclaimedCount: 0,\n\t\t\toutcome: \"idle\",\n\t\t};\n\t}\n\n\tlet claim: (MediaUsageCollectionDeletionRecord & { leaseToken: string }) | null = null;\n\tfor (const candidate of candidates) {\n\t\tclaim = await repository.claim({\n\t\t\tcollectionId: candidate.collectionId,\n\t\t\tphase: candidate.phase,\n\t\t\tleaseDurationSeconds: MEDIA_USAGE_COLLECTION_DELETION_LIMITS.leaseDurationSeconds,\n\t\t});\n\t\tif (claim?.leaseToken) break;\n\t}\n\tif (!claim?.leaseToken) {\n\t\treturn { candidateCount: candidates.length, claimedCount: 0, outcome: \"claim_lost\" };\n\t}\n\n\ttry {\n\t\tconst processed = await processClaimedDeletion(db, claim);\n\t\tif (!processed.finalized && !processed.released && !(await repository.release(claim))) {\n\t\t\treturn { candidateCount: candidates.length, claimedCount: 1, outcome: \"claim_lost\" };\n\t\t}\n\t\treturn {\n\t\t\tcandidateCount: candidates.length,\n\t\t\tclaimedCount: 1,\n\t\t\toutcome: processed.finalized ? \"finalized\" : \"progress\",\n\t\t};\n\t} catch (error) {\n\t\tconst terminal = claim.attemptCount + 1 >= MEDIA_USAGE_COLLECTION_DELETION_LIMITS.maxAttempts;\n\t\tconst recorded = await repository.recordFailure({\n\t\t\tcollectionId: claim.collectionId,\n\t\t\tleaseToken: claim.leaseToken,\n\t\t\terrorCode: \"MEDIA_USAGE_COLLECTION_DELETION_FAILED\",\n\t\t\tterminal,\n\t\t\tretryDelaySeconds: retryDelaySeconds(claim.attemptCount),\n\t\t});\n\t\tif (!recorded) {\n\t\t\treturn { candidateCount: candidates.length, claimedCount: 1, outcome: \"claim_lost\" };\n\t\t}\n\t\tconsole.error(\"[media-usage:collection-deletion] Processing failed:\", error);\n\t\treturn {\n\t\t\tcandidateCount: candidates.length,\n\t\t\tclaimedCount: 1,\n\t\t\toutcome: terminal ? \"failed\" : \"retry\",\n\t\t};\n\t}\n}\n\nasync function processClaimedDeletion(\n\tdb: Kysely<Database>,\n\tclaim: MediaUsageCollectionDeletionRecord & { leaseToken: string },\n): Promise<{ finalized: boolean; released: boolean }> {\n\tif (claim.phase === \"fence\" || claim.phase === \"registry\" || claim.phase === \"table\") {\n\t\tawait deleteActivatedMediaUsageCollection(\n\t\t\tdb,\n\t\t\t{\n\t\t\t\tcollectionId: claim.collectionId,\n\t\t\t\tcollectionSlug: claim.collectionSlug,\n\t\t\t\tforceDelete: claim.forceDelete,\n\t\t\t},\n\t\t\t{ frontPhaseLimit: 1, claimed: claim },\n\t\t);\n\t\treturn { finalized: false, released: true };\n\t}\n\tif (claim.phase === \"work\") await processWorkBatch(db, claim);\n\tif (claim.phase === \"sources\") await processSourceBatch(db, claim);\n\tif (claim.phase === \"status\") await processStatus(db, claim);\n\tif (claim.phase === \"finalize\") {\n\t\tawait finalizeDeletion(db, claim);\n\t\treturn { finalized: true, released: true };\n\t}\n\treturn { finalized: false, released: false };\n}\n\nasync function processWorkBatch(\n\tdb: Kysely<Database>,\n\tclaim: MediaUsageCollectionDeletionRecord & { leaseToken: string },\n): Promise<boolean> {\n\tawait withTransaction(db, async (trx) => {\n\t\tconst rows = await trx\n\t\t\t.selectFrom(\"_emdash_media_usage_work\")\n\t\t\t.select(\"content_id\")\n\t\t\t.where(\"collection_id\", \"=\", claim.collectionId)\n\t\t\t.$if(claim.workCursor !== null, (query) => query.where(\"content_id\", \">\", claim.workCursor!))\n\t\t\t.orderBy(\"content_id\", \"asc\")\n\t\t\t.limit(MEDIA_USAGE_COLLECTION_DELETION_LIMITS.rowsPerBatch + 1)\n\t\t\t.execute();\n\t\tconst batch = rows.slice(0, MEDIA_USAGE_COLLECTION_DELETION_LIMITS.rowsPerBatch);\n\t\tif (batch.length > 0) {\n\t\t\tawait trx\n\t\t\t\t.deleteFrom(\"_emdash_media_usage_work\")\n\t\t\t\t.where(\"collection_id\", \"=\", claim.collectionId)\n\t\t\t\t.where(\n\t\t\t\t\t\"content_id\",\n\t\t\t\t\t\"in\",\n\t\t\t\t\tbatch.map((row) => row.content_id),\n\t\t\t\t)\n\t\t\t\t.where(liveLeaseGuard(trx, claim))\n\t\t\t\t.execute();\n\t\t}\n\t\tawait updateDeletion(trx, claim, {\n\t\t\tphase: rows.length > MEDIA_USAGE_COLLECTION_DELETION_LIMITS.rowsPerBatch ? \"work\" : \"sources\",\n\t\t\twork_cursor:\n\t\t\t\trows.length > MEDIA_USAGE_COLLECTION_DELETION_LIMITS.rowsPerBatch\n\t\t\t\t\t? batch.at(-1)!.content_id\n\t\t\t\t\t: null,\n\t\t});\n\t});\n\treturn false;\n}\n\nasync function processSourceBatch(\n\tdb: Kysely<Database>,\n\tclaim: MediaUsageCollectionDeletionRecord & { leaseToken: string },\n): Promise<boolean> {\n\tawait withTransaction(db, async (trx) => {\n\t\tlet sourceKey = claim.sourceKey;\n\t\tif (!sourceKey) {\n\t\t\tconst source = await trx\n\t\t\t\t.selectFrom(\"_emdash_media_usage_sources\")\n\t\t\t\t.select(\"source_key\")\n\t\t\t\t.where(\"source_type\", \"=\", \"content\")\n\t\t\t\t.where(\"collection_id\", \"=\", claim.collectionId)\n\t\t\t\t.orderBy(\"source_key\", \"asc\")\n\t\t\t\t.limit(1)\n\t\t\t\t.executeTakeFirst();\n\t\t\tif (!source) {\n\t\t\t\tawait updateDeletion(trx, claim, {\n\t\t\t\t\tphase: \"status\",\n\t\t\t\t\tsource_key: null,\n\t\t\t\t\toccurrence_cursor: null,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsourceKey = source.source_key;\n\t\t\tawait updateDeletion(trx, claim, { source_key: sourceKey, occurrence_cursor: null });\n\t\t}\n\n\t\tconst occurrences = await trx\n\t\t\t.selectFrom(\"_emdash_media_usage\")\n\t\t\t.select(\"id\")\n\t\t\t.where(\"source_key\", \"=\", sourceKey)\n\t\t\t.$if(claim.occurrenceCursor !== null, (query) =>\n\t\t\t\tquery.where(\"id\", \">\", claim.occurrenceCursor!),\n\t\t\t)\n\t\t\t.orderBy(\"id\", \"asc\")\n\t\t\t.limit(MEDIA_USAGE_COLLECTION_DELETION_LIMITS.rowsPerBatch + 1)\n\t\t\t.execute();\n\t\tconst batch = occurrences.slice(0, MEDIA_USAGE_COLLECTION_DELETION_LIMITS.rowsPerBatch);\n\t\tif (batch.length > 0) {\n\t\t\tawait trx\n\t\t\t\t.deleteFrom(\"_emdash_media_usage\")\n\t\t\t\t.where(\"source_key\", \"=\", sourceKey)\n\t\t\t\t.where(\n\t\t\t\t\t\"id\",\n\t\t\t\t\t\"in\",\n\t\t\t\t\tbatch.map((row) => row.id),\n\t\t\t\t)\n\t\t\t\t.where(liveLeaseGuard(trx, claim))\n\t\t\t\t.execute();\n\t\t}\n\t\tif (occurrences.length > MEDIA_USAGE_COLLECTION_DELETION_LIMITS.rowsPerBatch) {\n\t\t\tawait updateDeletion(trx, claim, {\n\t\t\t\tsource_key: sourceKey,\n\t\t\t\toccurrence_cursor: batch.at(-1)!.id,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tawait trx\n\t\t\t.deleteFrom(\"_emdash_media_usage_sources\")\n\t\t\t.where(\"source_key\", \"=\", sourceKey)\n\t\t\t.where(\"source_type\", \"=\", \"content\")\n\t\t\t.where(\"collection_id\", \"=\", claim.collectionId)\n\t\t\t.where(liveLeaseGuard(trx, claim))\n\t\t\t.execute();\n\t\tawait updateDeletion(trx, claim, { source_key: null, occurrence_cursor: null });\n\t});\n\treturn false;\n}\n\nasync function processStatus(\n\tdb: Kysely<Database>,\n\tclaim: MediaUsageCollectionDeletionRecord & { leaseToken: string },\n): Promise<boolean> {\n\tawait withTransaction(db, async (trx) => {\n\t\tif (await exactCleanupRowsRemain(trx, claim, false)) {\n\t\t\tthrow new Error(\"Collection deletion cleanup is incomplete\");\n\t\t}\n\t\tawait trx\n\t\t\t.deleteFrom(\"_emdash_media_usage_reconciliations\")\n\t\t\t.where(\"collection_id\", \"=\", claim.collectionId)\n\t\t\t.where(\"collection_slug\", \"=\", claim.collectionSlug)\n\t\t\t.where(liveLeaseGuard(trx, claim))\n\t\t\t.execute();\n\t\tawait trx\n\t\t\t.deleteFrom(\"_emdash_media_usage_index_status\")\n\t\t\t.where(\"adapter_id\", \"=\", \"content-media\")\n\t\t\t.where(\"scope_type\", \"=\", \"collection\")\n\t\t\t.where(\"scope_key\", \"=\", claim.collectionSlug)\n\t\t\t.where(\"collection_id\", \"=\", claim.collectionId)\n\t\t\t.where(liveLeaseGuard(trx, claim))\n\t\t\t.execute();\n\t\tawait updateDeletion(trx, claim, { phase: \"finalize\" });\n\t});\n\treturn false;\n}\n\nasync function finalizeDeletion(\n\tdb: Kysely<Database>,\n\tclaim: MediaUsageCollectionDeletionRecord & { leaseToken: string },\n): Promise<boolean> {\n\tif (await tableExists(db, `ec_${claim.collectionSlug}`)) {\n\t\tthrow new Error(\"Collection table still exists during deletion finalization\");\n\t}\n\tif (await exactCleanupRowsRemain(db, claim)) throw new Error(\"Collection deletion is incomplete\");\n\tconst registry = await db\n\t\t.selectFrom(\"_emdash_collections\")\n\t\t.select(\"id\")\n\t\t.where(\"id\", \"=\", claim.collectionId)\n\t\t.where(\"slug\", \"=\", claim.collectionSlug)\n\t\t.executeTakeFirst();\n\tif (registry) throw new Error(\"Collection registry identity still exists\");\n\tconst result = await db\n\t\t.deleteFrom(\"_emdash_media_usage_collection_deletions\")\n\t\t.where(\"collection_id\", \"=\", claim.collectionId)\n\t\t.where(\"collection_slug\", \"=\", claim.collectionSlug)\n\t\t.where(\"state\", \"=\", \"leased\")\n\t\t.where(\"phase\", \"=\", \"finalize\")\n\t\t.where(\"lease_token\", \"=\", claim.leaseToken)\n\t\t.where(liveLeaseGuard(db, claim))\n\t\t.executeTakeFirst();\n\tif (Number(result.numDeletedRows ?? 0) !== 1)\n\t\tthrow new Error(\"Collection deletion lost finalization\");\n\treturn true;\n}\n\nasync function exactCleanupRowsRemain(\n\tdb: DatabaseExecutor,\n\tclaim: Pick<MediaUsageCollectionDeletionRecord, \"collectionId\" | \"collectionSlug\">,\n\tincludeStatus = true,\n): Promise<boolean> {\n\tconst result = await sql<{\n\t\twork_present: boolean | number;\n\t\tsource_present: boolean | number;\n\t\tstatus_present: boolean | number;\n\t}>`\n\t\tSELECT\n\t\t\tEXISTS (\n\t\t\t\tSELECT 1 FROM _emdash_media_usage_work\n\t\t\t\tWHERE collection_id = ${claim.collectionId}\n\t\t\t) AS work_present,\n\t\t\tEXISTS (\n\t\t\t\tSELECT 1 FROM _emdash_media_usage_sources\n\t\t\t\tWHERE source_type = 'content' AND collection_id = ${claim.collectionId}\n\t\t\t) AS source_present,\n\t\t\tEXISTS (\n\t\t\t\tSELECT 1 FROM _emdash_media_usage_index_status\n\t\t\t\tWHERE adapter_id = 'content-media'\n\t\t\t\t\tAND scope_type = 'collection'\n\t\t\t\t\tAND scope_key = ${claim.collectionSlug}\n\t\t\t\t\tAND collection_id = ${claim.collectionId}\n\t\t\t) AS status_present\n\t`.execute(db);\n\tconst row = result.rows[0];\n\treturn (\n\t\tBoolean(row?.work_present) ||\n\t\tBoolean(row?.source_present) ||\n\t\t(includeStatus && Boolean(row?.status_present))\n\t);\n}\n\nasync function updateDeletion(\n\tdb: DatabaseExecutor,\n\tclaim: MediaUsageCollectionDeletionRecord & { leaseToken: string },\n\tvalues: Updateable<MediaUsageCollectionDeletionTable>,\n): Promise<void> {\n\tconst result = await db\n\t\t.updateTable(\"_emdash_media_usage_collection_deletions\")\n\t\t.set({\n\t\t\t...values,\n\t\t\tattempt_count: 0,\n\t\t\tlast_error_code: null,\n\t\t\tupdated_at: collectionDeletionCurrentTimestamp(db),\n\t\t})\n\t\t.where(\"collection_id\", \"=\", claim.collectionId)\n\t\t.where(\"state\", \"=\", \"leased\")\n\t\t.where(\"lease_token\", \"=\", claim.leaseToken)\n\t\t.where(liveLeaseGuard(db, claim))\n\t\t.executeTakeFirst();\n\tif (Number(result.numUpdatedRows ?? 0) !== 1)\n\t\tthrow new Error(\"Collection deletion lease was lost\");\n}\n\nfunction liveLeaseGuard(\n\tdb: DatabaseExecutor,\n\tclaim: Pick<MediaUsageCollectionDeletionRecord, \"collectionId\"> & { leaseToken: string },\n): RawBuilder<boolean> {\n\treturn isPostgres(db)\n\t\t? sql<boolean>`EXISTS (\n\t\t\tSELECT 1 FROM _emdash_media_usage_collection_deletions AS deletion\n\t\t\tWHERE deletion.collection_id = ${claim.collectionId}\n\t\t\t\tAND deletion.state = 'leased'\n\t\t\t\tAND deletion.lease_token = ${claim.leaseToken}\n\t\t\t\tAND deletion.lease_expires_at::timestamptz > clock_timestamp()\n\t\t)`\n\t\t: sql<boolean>`EXISTS (\n\t\t\tSELECT 1 FROM _emdash_media_usage_collection_deletions AS deletion\n\t\t\tWHERE deletion.collection_id = ${claim.collectionId}\n\t\t\t\tAND deletion.state = 'leased'\n\t\t\t\tAND deletion.lease_token = ${claim.leaseToken}\n\t\t\t\tAND deletion.lease_expires_at > strftime('%Y-%m-%dT%H:%M:%fZ', 'now')\n\t\t)`;\n}\n\nfunction retryDelaySeconds(attemptCount: number): number {\n\treturn Math.min(\n\t\tMEDIA_USAGE_COLLECTION_DELETION_LIMITS.retryMaxSeconds,\n\t\tMEDIA_USAGE_COLLECTION_DELETION_LIMITS.retryBaseSeconds * 2 ** attemptCount,\n\t);\n}\n","import { sql, type Kysely, type RawBuilder, type Selectable } from \"kysely\";\nimport { ulid } from \"ulidx\";\n\nimport { isPostgres } from \"../../database/dialect-helpers.js\";\nimport { jsonTextValues } from \"../../database/json-recordset.js\";\nimport type { Database, MediaUsageReconciliationTable } from \"../../database/types.js\";\nimport { validateIdentifier } from \"../../database/validate.js\";\n\nconst ACTIVATION_KEY = \"incremental_capture\";\nconst CONTENT_ADAPTER_ID = \"content-media\";\nconst COLLECTION_SCOPE = \"collection\";\nconst MAX_CANDIDATES = 100;\nconst MAX_PORTABLE_DURATION_SECONDS = 365 * 24 * 60 * 60;\nconst STABLE_ERROR_CODE_PATTERN = /^[A-Z][A-Z0-9_]{0,63}$/;\n\nexport type MediaUsageReconciliationState = \"pending\" | \"retry\" | \"leased\" | \"failed\";\nexport type MediaUsageReconciliationPhase = \"scan\" | \"sources\";\n\nexport interface MediaUsageReconciliationRecord {\n\tcollectionId: string;\n\tcollectionSlug: string;\n\trunToken: string;\n\ttargetEpoch: number | string | null;\n\tfieldFingerprint: string | null;\n\tstate: MediaUsageReconciliationState;\n\tphase: MediaUsageReconciliationPhase;\n\tscanCursor: string | null;\n\tscanUpperId: string | null;\n\tsourceCursor: string | null;\n\tsourceUpperKey: string | null;\n\tattemptCount: number;\n\tnextAttemptAt: string;\n\tleaseToken: string | null;\n\tleaseExpiresAt: string | null;\n\tlastErrorCode: string | null;\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface MediaUsageReconciliationClaim extends MediaUsageReconciliationRecord {\n\tleaseToken: string;\n}\n\nexport interface MediaUsageReconciliationSourceCandidate {\n\tsourceKey: string;\n\tcontentId: string | null;\n\tsourceVariant: string;\n}\n\nexport type MediaUsageReconciliationWorkBarrier =\n\t| { state: \"empty\" }\n\t| { state: \"pending\" }\n\t| { state: \"failed\"; errorCode: string };\n\nexport class MediaUsageReconciliationRepository {\n\tconstructor(private db: Kysely<Database>) {}\n\n\tasync findByIdentity(\n\t\tcollectionId: string,\n\t\trunToken: string,\n\t): Promise<MediaUsageReconciliationRecord | null> {\n\t\tassertIdentity({ collectionId, runToken });\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_reconciliations\")\n\t\t\t.selectAll()\n\t\t\t.where(\"collection_id\", \"=\", collectionId)\n\t\t\t.where(\"run_token\", \"=\", runToken)\n\t\t\t.executeTakeFirst();\n\t\treturn row ? rowToRecord(row) : null;\n\t}\n\n\tasync beginRun(claim: MediaUsageReconciliationClaim): Promise<number | string | null> {\n\t\tconst now = timestampOffset(this.db, 0);\n\t\tconst sameRun = sql<boolean>`status = 'running' AND cursor = ${claim.runToken}`;\n\t\tconst row = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_index_status as status\")\n\t\t\t.set({\n\t\t\t\tstatus: \"running\",\n\t\t\t\tstarted_at: sql<string | null>`CASE WHEN ${sameRun} THEN started_at ELSE ${now} END`,\n\t\t\t\tcompleted_at: null,\n\t\t\t\tcursor: claim.runToken,\n\t\t\t\tindexed_source_count: 0,\n\t\t\t\tfailed_source_count: 0,\n\t\t\t\tlast_error_code: null,\n\t\t\t\tchange_epoch: sql<number>`CASE WHEN ${sameRun} THEN change_epoch ELSE change_epoch + 1 END`,\n\t\t\t\treconciliation_required: 1,\n\t\t\t\tupdated_at: now,\n\t\t\t})\n\t\t\t.where(\"status.adapter_id\", \"=\", CONTENT_ADAPTER_ID)\n\t\t\t.where(\"status.scope_type\", \"=\", COLLECTION_SCOPE)\n\t\t\t.where(\"status.collection_id\", \"=\", claim.collectionId)\n\t\t\t.where(\"status.scope_key\", \"=\", claim.collectionSlug)\n\t\t\t.where(\"status.capture_state\", \"=\", \"active\")\n\t\t\t.where(\"status.reconciliation_required\", \"=\", 1)\n\t\t\t.where((eb) =>\n\t\t\t\teb.or([eb(\"status.status\", \"!=\", \"running\"), eb(\"status.cursor\", \"=\", claim.runToken)]),\n\t\t\t)\n\t\t\t.where(this.liveClaimExists(claim))\n\t\t\t.returning(\"change_epoch\")\n\t\t\t.executeTakeFirst();\n\t\treturn row?.change_epoch ?? null;\n\t}\n\n\tasync findScanUpperId(claim: MediaUsageReconciliationClaim): Promise<string | null> {\n\t\tconst tableName = contentTableName(claim.collectionSlug);\n\t\tconst result = await sql<{ id: string }>`\n\t\t\tSELECT content.id\n\t\t\tFROM ${sql.ref(tableName)} AS content\n\t\t\tWHERE ${this.liveClaimExistsSql(claim)}\n\t\t\tORDER BY content.id DESC\n\t\t\tLIMIT 1\n\t\t`.execute(this.db);\n\t\treturn result.rows[0]?.id ?? null;\n\t}\n\n\tasync initializeScan(input: {\n\t\tclaim: MediaUsageReconciliationClaim;\n\t\ttargetEpoch: number | string;\n\t\tfieldFingerprint: string;\n\t\tscanUpperId: string | null;\n\t}): Promise<boolean> {\n\t\tconst result = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_reconciliations as reconciliation\")\n\t\t\t.set({\n\t\t\t\ttarget_epoch: input.targetEpoch,\n\t\t\t\tfield_fingerprint: input.fieldFingerprint,\n\t\t\t\tphase: \"scan\",\n\t\t\t\tscan_cursor: null,\n\t\t\t\tscan_upper_id: input.scanUpperId,\n\t\t\t\tsource_cursor: null,\n\t\t\t\tsource_upper_key: null,\n\t\t\t\tattempt_count: 0,\n\t\t\t\tlast_error_code: null,\n\t\t\t\tupdated_at: timestampOffset(this.db, 0),\n\t\t\t})\n\t\t\t.where(\"reconciliation.collection_id\", \"=\", input.claim.collectionId)\n\t\t\t.where(\"reconciliation.run_token\", \"=\", input.claim.runToken)\n\t\t\t.where(\"reconciliation.target_epoch\", \"is\", null)\n\t\t\t.where(\"reconciliation.state\", \"=\", \"leased\")\n\t\t\t.where(\"reconciliation.lease_token\", \"=\", input.claim.leaseToken)\n\t\t\t.where(liveLease(this.db))\n\t\t\t.where(this.statusOwnsRun(input.claim, input.targetEpoch))\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) === 1;\n\t}\n\n\tasync findScanPage(\n\t\treconciliation: MediaUsageReconciliationRecord,\n\t\tlimit: number,\n\t): Promise<string[]> {\n\t\tif (!Number.isSafeInteger(limit) || limit < 1 || limit > 1_000) {\n\t\t\tthrow new Error(\"Reconciliation scan page limit must be from 1 to 1000\");\n\t\t}\n\t\tif (!reconciliation.leaseToken || reconciliation.targetEpoch === null) return [];\n\t\tconst tableName = contentTableName(reconciliation.collectionSlug);\n\t\tconst lowerBound = reconciliation.scanCursor\n\t\t\t? sql`AND content.id > ${reconciliation.scanCursor}`\n\t\t\t: sql``;\n\t\tconst upperBound = reconciliation.scanUpperId\n\t\t\t? sql`AND content.id <= ${reconciliation.scanUpperId}`\n\t\t\t: sql`AND 1 = 0`;\n\t\tconst result = await sql<{ id: string }>`\n\t\t\tSELECT content.id\n\t\t\tFROM ${sql.ref(tableName)} AS content\n\t\t\tWHERE 1 = 1\n\t\t\t\t${lowerBound}\n\t\t\t\t${upperBound}\n\t\t\t\tAND ${this.liveClaimExistsSql(reconciliation)}\n\t\t\tORDER BY content.id ASC\n\t\t\tLIMIT ${limit}\n\t\t`.execute(this.db);\n\t\treturn result.rows.map((row) => row.id);\n\t}\n\n\tasync checkpointScan(input: {\n\t\tclaim: MediaUsageReconciliationClaim;\n\t\ttargetEpoch: number | string;\n\t\tpreviousCursor: string | null;\n\t\tnextCursor: string;\n\t}): Promise<boolean> {\n\t\tlet query = this.db\n\t\t\t.updateTable(\"_emdash_media_usage_reconciliations as reconciliation\")\n\t\t\t.set({\n\t\t\t\tscan_cursor: input.nextCursor,\n\t\t\t\tattempt_count: 0,\n\t\t\t\tlast_error_code: null,\n\t\t\t\tupdated_at: timestampOffset(this.db, 0),\n\t\t\t})\n\t\t\t.where(\"reconciliation.collection_id\", \"=\", input.claim.collectionId)\n\t\t\t.where(\"reconciliation.run_token\", \"=\", input.claim.runToken)\n\t\t\t.where(\"reconciliation.target_epoch\", \"=\", input.targetEpoch)\n\t\t\t.where(\"reconciliation.state\", \"=\", \"leased\")\n\t\t\t.where(\"reconciliation.phase\", \"=\", \"scan\")\n\t\t\t.where(\"reconciliation.lease_token\", \"=\", input.claim.leaseToken)\n\t\t\t.where(liveLease(this.db))\n\t\t\t.where(this.statusOwnsRun(input.claim, input.targetEpoch));\n\t\tquery = input.previousCursor\n\t\t\t? query.where(\"reconciliation.scan_cursor\", \"=\", input.previousCursor)\n\t\t\t: query.where(\"reconciliation.scan_cursor\", \"is\", null);\n\t\tconst result = await query.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) === 1;\n\t}\n\n\tasync ownsRun(\n\t\tclaim: MediaUsageReconciliationClaim,\n\t\ttargetEpoch: number | string,\n\t): Promise<boolean> {\n\t\tconst result = await sql<{ owned: boolean | number }>`\n\t\t\tSELECT ${this.statusOwnsRun(claim, targetEpoch)} AS owned\n\t\t`.execute(this.db);\n\t\treturn Boolean(result.rows[0]?.owned);\n\t}\n\n\tasync restartRun(\n\t\tclaim: MediaUsageReconciliationClaim,\n\t\tpreviousEpoch: number | string,\n\t): Promise<number | string | null> {\n\t\tconst now = timestampOffset(this.db, 0);\n\t\tconst interruptedRestart = sql<boolean>`status = 'running'\n\t\t\tAND cursor = ${claim.runToken}\n\t\t\tAND change_epoch > ${previousEpoch}`;\n\t\tconst row = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_index_status as status\")\n\t\t\t.set({\n\t\t\t\tstatus: \"running\",\n\t\t\t\tstarted_at: sql<\n\t\t\t\t\tstring | null\n\t\t\t\t>`CASE WHEN ${interruptedRestart} THEN started_at ELSE ${now} END`,\n\t\t\t\tcompleted_at: null,\n\t\t\t\tcursor: claim.runToken,\n\t\t\t\tlast_error_code: null,\n\t\t\t\tchange_epoch: sql<number>`CASE WHEN ${interruptedRestart} THEN change_epoch ELSE change_epoch + 1 END`,\n\t\t\t\treconciliation_required: 1,\n\t\t\t\tupdated_at: now,\n\t\t\t})\n\t\t\t.where(\"status.adapter_id\", \"=\", CONTENT_ADAPTER_ID)\n\t\t\t.where(\"status.scope_type\", \"=\", COLLECTION_SCOPE)\n\t\t\t.where(\"status.collection_id\", \"=\", claim.collectionId)\n\t\t\t.where(\"status.scope_key\", \"=\", claim.collectionSlug)\n\t\t\t.where(\"status.capture_state\", \"=\", \"active\")\n\t\t\t.where(\"status.reconciliation_required\", \"=\", 1)\n\t\t\t.where((eb) =>\n\t\t\t\teb.or([eb(\"status.status\", \"!=\", \"running\"), eb(\"status.cursor\", \"=\", claim.runToken)]),\n\t\t\t)\n\t\t\t.where(this.liveClaimExists(claim))\n\t\t\t.returning(\"change_epoch\")\n\t\t\t.executeTakeFirst();\n\t\treturn row?.change_epoch ?? null;\n\t}\n\n\tasync restartScan(input: {\n\t\tclaim: MediaUsageReconciliationClaim;\n\t\tpreviousEpoch: number | string;\n\t\ttargetEpoch: number | string;\n\t\tfieldFingerprint: string;\n\t\tscanUpperId: string | null;\n\t}): Promise<boolean> {\n\t\tconst result = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_reconciliations as reconciliation\")\n\t\t\t.set({\n\t\t\t\ttarget_epoch: input.targetEpoch,\n\t\t\t\tfield_fingerprint: input.fieldFingerprint,\n\t\t\t\tphase: \"scan\",\n\t\t\t\tscan_cursor: null,\n\t\t\t\tscan_upper_id: input.scanUpperId,\n\t\t\t\tsource_cursor: null,\n\t\t\t\tsource_upper_key: null,\n\t\t\t\tattempt_count: 0,\n\t\t\t\tnext_attempt_at: timestampOffset(this.db, 0),\n\t\t\t\tlast_error_code: null,\n\t\t\t\tupdated_at: timestampOffset(this.db, 0),\n\t\t\t})\n\t\t\t.where(\"reconciliation.collection_id\", \"=\", input.claim.collectionId)\n\t\t\t.where(\"reconciliation.run_token\", \"=\", input.claim.runToken)\n\t\t\t.where(\"reconciliation.target_epoch\", \"=\", input.previousEpoch)\n\t\t\t.where(\"reconciliation.state\", \"=\", \"leased\")\n\t\t\t.where(\"reconciliation.lease_token\", \"=\", input.claim.leaseToken)\n\t\t\t.where(liveLease(this.db))\n\t\t\t.where(this.statusOwnsRun(input.claim, input.targetEpoch))\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) === 1;\n\t}\n\n\tasync findWorkBarrier(collectionId: string): Promise<MediaUsageReconciliationWorkBarrier> {\n\t\tif (!collectionId) throw new Error(\"Reconciliation work barrier requires a collection ID\");\n\t\tconst failed = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_work\")\n\t\t\t.select(\"last_error_code\")\n\t\t\t.where(\"collection_id\", \"=\", collectionId)\n\t\t\t.where(\"state\", \"=\", \"failed\")\n\t\t\t.orderBy(\"content_id\")\n\t\t\t.limit(1)\n\t\t\t.executeTakeFirst();\n\t\tif (failed) {\n\t\t\treturn {\n\t\t\t\tstate: \"failed\",\n\t\t\t\terrorCode: failed.last_error_code ?? \"MEDIA_USAGE_PROCESSING_FAILED\",\n\t\t\t};\n\t\t}\n\t\tconst pending = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_work\")\n\t\t\t.select(\"content_id\")\n\t\t\t.where(\"collection_id\", \"=\", collectionId)\n\t\t\t.limit(1)\n\t\t\t.executeTakeFirst();\n\t\treturn pending ? { state: \"pending\" } : { state: \"empty\" };\n\t}\n\n\tasync findSourceUpperKey(\n\t\tclaim: MediaUsageReconciliationClaim,\n\t\ttargetEpoch: number | string,\n\t): Promise<string | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_sources as source\")\n\t\t\t.select(\"source.source_key\")\n\t\t\t.where(\"source.source_type\", \"=\", \"content\")\n\t\t\t.where(\"source.collection_id\", \"=\", claim.collectionId)\n\t\t\t.where(\"source.identity_version\", \"=\", 1)\n\t\t\t.where(this.liveClaimExists(claim))\n\t\t\t.where(this.statusOwnsRun(claim, targetEpoch))\n\t\t\t.orderBy(\"source.source_key\", \"desc\")\n\t\t\t.limit(1)\n\t\t\t.executeTakeFirst();\n\t\treturn row?.source_key ?? null;\n\t}\n\n\tasync transitionToSources(input: {\n\t\tclaim: MediaUsageReconciliationClaim;\n\t\ttargetEpoch: number | string;\n\t\tfieldFingerprint: string;\n\t\tsourceUpperKey: string | null;\n\t}): Promise<boolean> {\n\t\tconst result = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_reconciliations as reconciliation\")\n\t\t\t.set({\n\t\t\t\tphase: \"sources\",\n\t\t\t\tsource_cursor: null,\n\t\t\t\tsource_upper_key: input.sourceUpperKey,\n\t\t\t\tattempt_count: 0,\n\t\t\t\tlast_error_code: null,\n\t\t\t\tupdated_at: timestampOffset(this.db, 0),\n\t\t\t})\n\t\t\t.where(\"reconciliation.collection_id\", \"=\", input.claim.collectionId)\n\t\t\t.where(\"reconciliation.run_token\", \"=\", input.claim.runToken)\n\t\t\t.where(\"reconciliation.target_epoch\", \"=\", input.targetEpoch)\n\t\t\t.where(\"reconciliation.field_fingerprint\", \"=\", input.fieldFingerprint)\n\t\t\t.where(\"reconciliation.state\", \"=\", \"leased\")\n\t\t\t.where(\"reconciliation.phase\", \"=\", \"scan\")\n\t\t\t.where(\"reconciliation.lease_token\", \"=\", input.claim.leaseToken)\n\t\t\t.where(liveLease(this.db))\n\t\t\t.where(this.statusOwnsRun(input.claim, input.targetEpoch))\n\t\t\t.where((eb) =>\n\t\t\t\teb.not(\n\t\t\t\t\teb.exists(\n\t\t\t\t\t\teb\n\t\t\t\t\t\t\t.selectFrom(\"_emdash_media_usage_work as work\")\n\t\t\t\t\t\t\t.select(\"work.content_id\")\n\t\t\t\t\t\t\t.where(\"work.collection_id\", \"=\", input.claim.collectionId),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) === 1;\n\t}\n\n\tasync findSourcePage(\n\t\treconciliation: MediaUsageReconciliationRecord,\n\t\tlimit: number,\n\t): Promise<MediaUsageReconciliationSourceCandidate[]> {\n\t\tif (!Number.isSafeInteger(limit) || limit < 1 || limit > 1_000) {\n\t\t\tthrow new Error(\"Reconciliation source page limit must be from 1 to 1000\");\n\t\t}\n\t\tif (!reconciliation.leaseToken || reconciliation.targetEpoch === null) return [];\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_sources as source\")\n\t\t\t.select([\"source.source_key\", \"source.content_id\", \"source.source_variant\"])\n\t\t\t.where(\"source.source_type\", \"=\", \"content\")\n\t\t\t.where(\"source.collection_id\", \"=\", reconciliation.collectionId)\n\t\t\t.where(\"source.identity_version\", \"=\", 1)\n\t\t\t.where(this.liveClaimExists(reconciliation))\n\t\t\t.where(this.statusOwnsRun(reconciliation, reconciliation.targetEpoch));\n\t\tif (reconciliation.sourceCursor) {\n\t\t\tquery = query.where(\"source.source_key\", \">\", reconciliation.sourceCursor);\n\t\t}\n\t\tif (reconciliation.sourceUpperKey) {\n\t\t\tquery = query.where(\"source.source_key\", \"<=\", reconciliation.sourceUpperKey);\n\t\t} else {\n\t\t\tquery = query.where(sql<boolean>`1 = 0`);\n\t\t}\n\t\tconst rows = await query.orderBy(\"source.source_key\").limit(limit).execute();\n\t\treturn rows.map((row) => ({\n\t\t\tsourceKey: row.source_key,\n\t\t\tcontentId: row.content_id,\n\t\t\tsourceVariant: row.source_variant,\n\t\t}));\n\t}\n\n\tasync findMissingContentIds(\n\t\tcollectionSlug: string,\n\t\tcontentIds: readonly string[],\n\t): Promise<string[]> {\n\t\tconst unique = [...new Set(contentIds)];\n\t\tif (unique.length === 0) return [];\n\t\tif (unique.length > 1_000 || unique.some((contentId) => !contentId)) {\n\t\t\tthrow new Error(\"Reconciliation source page has invalid content identity\");\n\t\t}\n\t\tconst tableName = contentTableName(collectionSlug);\n\t\tconst requested = jsonTextValues(this.db, unique);\n\t\tconst existing = await sql<{ id: string }>`\n\t\t\tWITH requested AS (${requested})\n\t\t\tSELECT content.id\n\t\t\tFROM ${sql.ref(tableName)} AS content\n\t\t\tINNER JOIN requested ON requested.value = content.id\n\t\t`.execute(this.db);\n\t\tconst present = new Set(existing.rows.map((row) => row.id));\n\t\treturn unique.filter((contentId) => !present.has(contentId));\n\t}\n\n\tasync checkpointSources(input: {\n\t\tclaim: MediaUsageReconciliationClaim;\n\t\ttargetEpoch: number | string;\n\t\tpreviousCursor: string | null;\n\t\tnextCursor: string;\n\t}): Promise<boolean> {\n\t\tlet query = this.db\n\t\t\t.updateTable(\"_emdash_media_usage_reconciliations as reconciliation\")\n\t\t\t.set({\n\t\t\t\tsource_cursor: input.nextCursor,\n\t\t\t\tattempt_count: 0,\n\t\t\t\tlast_error_code: null,\n\t\t\t\tupdated_at: timestampOffset(this.db, 0),\n\t\t\t})\n\t\t\t.where(\"reconciliation.collection_id\", \"=\", input.claim.collectionId)\n\t\t\t.where(\"reconciliation.run_token\", \"=\", input.claim.runToken)\n\t\t\t.where(\"reconciliation.target_epoch\", \"=\", input.targetEpoch)\n\t\t\t.where(\"reconciliation.state\", \"=\", \"leased\")\n\t\t\t.where(\"reconciliation.phase\", \"=\", \"sources\")\n\t\t\t.where(\"reconciliation.lease_token\", \"=\", input.claim.leaseToken)\n\t\t\t.where(liveLease(this.db))\n\t\t\t.where(this.statusOwnsRun(input.claim, input.targetEpoch));\n\t\tquery = input.previousCursor\n\t\t\t? query.where(\"reconciliation.source_cursor\", \"=\", input.previousCursor)\n\t\t\t: query.where(\"reconciliation.source_cursor\", \"is\", null);\n\t\tconst result = await query.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) === 1;\n\t}\n\n\tasync finishFailedCoverage(collectionId: string, runToken: string): Promise<boolean> {\n\t\tassertIdentity({ collectionId, runToken });\n\t\tconst now = timestampOffset(this.db, 0);\n\t\tconst result = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_index_status as status\")\n\t\t\t.set({\n\t\t\t\tstatus: sql<string>`CASE WHEN EXISTS (\n\t\t\t\t\tSELECT 1 FROM _emdash_media_usage_sources AS source\n\t\t\t\t\tWHERE source.source_type = 'content'\n\t\t\t\t\t\tAND source.collection_id = ${collectionId}\n\t\t\t\t\t\tAND source.identity_version = 1\n\t\t\t\t\tLIMIT 1\n\t\t\t\t) THEN 'partial' ELSE 'failed' END`,\n\t\t\t\tcompleted_at: null,\n\t\t\t\tcursor: null,\n\t\t\t\tlast_error_code: sql<string>`CASE WHEN (\n\t\t\t\t\tSELECT reconciliation.last_error_code\n\t\t\t\t\tFROM _emdash_media_usage_reconciliations AS reconciliation\n\t\t\t\t\tWHERE reconciliation.collection_id = ${collectionId}\n\t\t\t\t\t\tAND reconciliation.run_token = ${runToken}\n\t\t\t\t) = 'MEDIA_USAGE_RECONCILIATION_ENTRY_FAILED'\n\t\t\t\tTHEN COALESCE(\n\t\t\t\t\t(SELECT work.last_error_code\n\t\t\t\t\t FROM _emdash_media_usage_work AS work\n\t\t\t\t\t WHERE work.collection_id = ${collectionId} AND work.state = 'failed'\n\t\t\t\t\t ORDER BY work.content_id LIMIT 1),\n\t\t\t\t\t'MEDIA_USAGE_RECONCILIATION_ENTRY_FAILED'\n\t\t\t\t)\n\t\t\t\tELSE (\n\t\t\t\t\tSELECT reconciliation.last_error_code\n\t\t\t\t\tFROM _emdash_media_usage_reconciliations AS reconciliation\n\t\t\t\t\tWHERE reconciliation.collection_id = ${collectionId}\n\t\t\t\t\t\tAND reconciliation.run_token = ${runToken}\n\t\t\t\t) END`,\n\t\t\t\treconciliation_required: 1,\n\t\t\t\tupdated_at: now,\n\t\t\t})\n\t\t\t.where(\"status.adapter_id\", \"=\", CONTENT_ADAPTER_ID)\n\t\t\t.where(\"status.scope_type\", \"=\", COLLECTION_SCOPE)\n\t\t\t.where(\"status.collection_id\", \"=\", collectionId)\n\t\t\t.where(\"status.status\", \"=\", \"running\")\n\t\t\t.where(\"status.cursor\", \"=\", runToken)\n\t\t\t.where(sql<boolean>`status.change_epoch = (\n\t\t\t\tSELECT reconciliation.target_epoch\n\t\t\t\tFROM _emdash_media_usage_reconciliations AS reconciliation\n\t\t\t\tWHERE reconciliation.collection_id = ${collectionId}\n\t\t\t\t\tAND reconciliation.run_token = ${runToken}\n\t\t\t)`)\n\t\t\t.where((eb) =>\n\t\t\t\teb.exists(\n\t\t\t\t\teb\n\t\t\t\t\t\t.selectFrom(\"_emdash_media_usage_reconciliations as reconciliation\")\n\t\t\t\t\t\t.select(\"reconciliation.collection_id\")\n\t\t\t\t\t\t.where(\"reconciliation.collection_id\", \"=\", collectionId)\n\t\t\t\t\t\t.where(\"reconciliation.run_token\", \"=\", runToken)\n\t\t\t\t\t\t.where(\"reconciliation.state\", \"=\", \"failed\"),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) === 1;\n\t}\n\n\tasync finalizeCoverage(input: {\n\t\tclaim: MediaUsageReconciliationClaim;\n\t\ttargetEpoch: number | string;\n\t\tfieldFingerprint: string;\n\t\tschemaVersion: number;\n\t}): Promise<boolean> {\n\t\tconst now = timestampOffset(this.db, 0);\n\t\tconst result = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_index_status as status\")\n\t\t\t.set({\n\t\t\t\tstatus: \"complete\",\n\t\t\t\tschema_version: input.schemaVersion,\n\t\t\t\tcompleted_at: now,\n\t\t\t\tcursor: null,\n\t\t\t\tlast_error_code: null,\n\t\t\t\treconciliation_required: 0,\n\t\t\t\tupdated_at: now,\n\t\t\t})\n\t\t\t.where(\"status.adapter_id\", \"=\", CONTENT_ADAPTER_ID)\n\t\t\t.where(\"status.scope_type\", \"=\", COLLECTION_SCOPE)\n\t\t\t.where(\"status.collection_id\", \"=\", input.claim.collectionId)\n\t\t\t.where(\"status.scope_key\", \"=\", input.claim.collectionSlug)\n\t\t\t.where(\"status.capture_state\", \"=\", \"active\")\n\t\t\t.where(\"status.reconciliation_required\", \"=\", 1)\n\t\t\t.where(\"status.status\", \"=\", \"running\")\n\t\t\t.where(\"status.cursor\", \"=\", input.claim.runToken)\n\t\t\t.where(\"status.change_epoch\", \"=\", input.targetEpoch)\n\t\t\t.where((eb) =>\n\t\t\t\teb.not(\n\t\t\t\t\teb.exists(\n\t\t\t\t\t\teb\n\t\t\t\t\t\t\t.selectFrom(\"_emdash_media_usage_work as work\")\n\t\t\t\t\t\t\t.select(\"work.content_id\")\n\t\t\t\t\t\t\t.where(\"work.collection_id\", \"=\", input.claim.collectionId),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.where((eb) =>\n\t\t\t\teb.exists(\n\t\t\t\t\teb\n\t\t\t\t\t\t.selectFrom(\"_emdash_media_usage_reconciliations as reconciliation\")\n\t\t\t\t\t\t.innerJoin(\"_emdash_collections as collection\", (join) =>\n\t\t\t\t\t\t\tjoin\n\t\t\t\t\t\t\t\t.onRef(\"collection.id\", \"=\", \"reconciliation.collection_id\")\n\t\t\t\t\t\t\t\t.onRef(\"collection.slug\", \"=\", \"reconciliation.collection_slug\"),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.select(\"reconciliation.collection_id\")\n\t\t\t\t\t\t.where(\"reconciliation.collection_id\", \"=\", input.claim.collectionId)\n\t\t\t\t\t\t.where(\"reconciliation.run_token\", \"=\", input.claim.runToken)\n\t\t\t\t\t\t.where(\"reconciliation.target_epoch\", \"=\", input.targetEpoch)\n\t\t\t\t\t\t.where(\"reconciliation.field_fingerprint\", \"=\", input.fieldFingerprint)\n\t\t\t\t\t\t.where(\"reconciliation.state\", \"=\", \"leased\")\n\t\t\t\t\t\t.where(\"reconciliation.phase\", \"=\", \"sources\")\n\t\t\t\t\t\t.where(\"reconciliation.lease_token\", \"=\", input.claim.leaseToken)\n\t\t\t\t\t\t.where(liveLease(this.db, \"reconciliation.lease_expires_at\"))\n\t\t\t\t\t\t.where((inner) =>\n\t\t\t\t\t\t\tinner.not(\n\t\t\t\t\t\t\t\tinner.exists(\n\t\t\t\t\t\t\t\t\tinner\n\t\t\t\t\t\t\t\t\t\t.selectFrom(\"_emdash_media_usage_collection_deletions as deletion\")\n\t\t\t\t\t\t\t\t\t\t.select(\"deletion.collection_id\")\n\t\t\t\t\t\t\t\t\t\t.where(\"deletion.collection_id\", \"=\", input.claim.collectionId),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.where((eb) =>\n\t\t\t\teb.exists(\n\t\t\t\t\teb\n\t\t\t\t\t\t.selectFrom(\"_emdash_media_usage_activation as activation\")\n\t\t\t\t\t\t.select(\"activation.task_key\")\n\t\t\t\t\t\t.where(\"activation.task_key\", \"=\", ACTIVATION_KEY)\n\t\t\t\t\t\t.where(\"activation.state\", \"=\", \"active\"),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) === 1;\n\t}\n\n\tasync deleteFinalized(claim: MediaUsageReconciliationClaim): Promise<boolean> {\n\t\tconst result = await this.db\n\t\t\t.deleteFrom(\"_emdash_media_usage_reconciliations as reconciliation\")\n\t\t\t.where(\"reconciliation.collection_id\", \"=\", claim.collectionId)\n\t\t\t.where(\"reconciliation.run_token\", \"=\", claim.runToken)\n\t\t\t.where(\"reconciliation.state\", \"=\", \"leased\")\n\t\t\t.where(\"reconciliation.lease_token\", \"=\", claim.leaseToken)\n\t\t\t.where((eb) =>\n\t\t\t\teb.exists(\n\t\t\t\t\teb\n\t\t\t\t\t\t.selectFrom(\"_emdash_media_usage_index_status as status\")\n\t\t\t\t\t\t.select(\"status.collection_id\")\n\t\t\t\t\t\t.where(\"status.collection_id\", \"=\", claim.collectionId)\n\t\t\t\t\t\t.where(\"status.scope_key\", \"=\", claim.collectionSlug)\n\t\t\t\t\t\t.where(\"status.status\", \"=\", \"complete\")\n\t\t\t\t\t\t.where(\"status.reconciliation_required\", \"=\", 0),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numDeletedRows ?? 0) === 1;\n\t}\n\n\tasync deleteOneObsolete(): Promise<boolean> {\n\t\tconst result = await sql<{ collection_id: string }>`\n\t\t\tDELETE FROM _emdash_media_usage_reconciliations\n\t\t\tWHERE (collection_id, run_token) IN (\n\t\t\t\tSELECT reconciliation.collection_id, reconciliation.run_token\n\t\t\t\tFROM _emdash_media_usage_reconciliations AS reconciliation\n\t\t\t\tINNER JOIN _emdash_media_usage_index_status AS status\n\t\t\t\t\tON status.collection_id = reconciliation.collection_id\n\t\t\t\t\tAND status.scope_key = reconciliation.collection_slug\n\t\t\t\tWHERE status.adapter_id = ${CONTENT_ADAPTER_ID}\n\t\t\t\t\tAND status.scope_type = ${COLLECTION_SCOPE}\n\t\t\t\t\tAND status.reconciliation_required = 0\n\t\t\t\tORDER BY reconciliation.updated_at, reconciliation.collection_id\n\t\t\t\tLIMIT 1\n\t\t\t)\n\t\t\tRETURNING collection_id\n\t\t`.execute(this.db);\n\t\treturn result.rows.length === 1;\n\t}\n\n\tprivate liveClaimExists(\n\t\tclaim: Pick<\n\t\t\tMediaUsageReconciliationRecord,\n\t\t\t\"collectionId\" | \"collectionSlug\" | \"runToken\" | \"leaseToken\"\n\t\t>,\n\t): RawBuilder<boolean> {\n\t\treturn this.liveClaimExistsSql(claim);\n\t}\n\n\tprivate liveClaimExistsSql(\n\t\tclaim: Pick<\n\t\t\tMediaUsageReconciliationRecord,\n\t\t\t\"collectionId\" | \"collectionSlug\" | \"runToken\" | \"leaseToken\"\n\t\t>,\n\t): RawBuilder<boolean> {\n\t\treturn sql<boolean>`EXISTS (\n\t\t\tSELECT 1\n\t\t\tFROM _emdash_media_usage_reconciliations AS reconciliation\n\t\t\tINNER JOIN _emdash_collections AS collection\n\t\t\t\tON collection.id = reconciliation.collection_id\n\t\t\t\tAND collection.slug = reconciliation.collection_slug\n\t\t\tWHERE reconciliation.collection_id = ${claim.collectionId}\n\t\t\t\tAND reconciliation.collection_slug = ${claim.collectionSlug}\n\t\t\t\tAND reconciliation.run_token = ${claim.runToken}\n\t\t\t\tAND reconciliation.state = 'leased'\n\t\t\t\tAND reconciliation.lease_token = ${claim.leaseToken}\n\t\t\t\tAND ${liveLease(this.db, \"reconciliation.lease_expires_at\")}\n\t\t\t\tAND EXISTS (\n\t\t\t\t\tSELECT 1 FROM _emdash_media_usage_activation AS activation\n\t\t\t\t\tWHERE activation.task_key = ${ACTIVATION_KEY}\n\t\t\t\t\t\tAND activation.state = 'active'\n\t\t\t\t)\n\t\t\t\tAND NOT EXISTS (\n\t\t\t\t\tSELECT 1 FROM _emdash_media_usage_collection_deletions AS deletion\n\t\t\t\t\tWHERE deletion.collection_id = reconciliation.collection_id\n\t\t\t\t)\n\t\t)`;\n\t}\n\n\tprivate statusOwnsRun(\n\t\tclaim: Pick<MediaUsageReconciliationRecord, \"collectionId\" | \"collectionSlug\" | \"runToken\">,\n\t\ttargetEpoch: number | string,\n\t): RawBuilder<boolean> {\n\t\treturn sql<boolean>`EXISTS (\n\t\t\tSELECT 1 FROM _emdash_media_usage_index_status AS status\n\t\t\tWHERE status.adapter_id = ${CONTENT_ADAPTER_ID}\n\t\t\t\tAND status.scope_type = ${COLLECTION_SCOPE}\n\t\t\t\tAND status.collection_id = ${claim.collectionId}\n\t\t\t\tAND status.scope_key = ${claim.collectionSlug}\n\t\t\t\tAND status.capture_state = 'active'\n\t\t\t\tAND status.reconciliation_required = 1\n\t\t\t\tAND status.status = 'running'\n\t\t\t\tAND status.cursor = ${claim.runToken}\n\t\t\t\tAND status.change_epoch = ${targetEpoch}\n\t\t)`;\n\t}\n\n\tasync seedNextCandidate(): Promise<boolean> {\n\t\tconst runToken = ulid();\n\t\tconst now = timestampOffset(this.db, 0);\n\t\tconst result = await sql<{ collection_id: string }>`\n\t\t\tINSERT INTO _emdash_media_usage_reconciliations (\n\t\t\t\tcollection_id,\n\t\t\t\tcollection_slug,\n\t\t\t\trun_token,\n\t\t\t\tnext_attempt_at,\n\t\t\t\tupdated_at\n\t\t\t)\n\t\t\tSELECT status.collection_id, status.scope_key, ${runToken}, ${now}, ${now}\n\t\t\tFROM _emdash_media_usage_index_status AS status\n\t\t\tINNER JOIN _emdash_collections AS collection\n\t\t\t\tON collection.id = status.collection_id\n\t\t\t\tAND collection.slug = status.scope_key\n\t\t\tWHERE status.adapter_id = ${CONTENT_ADAPTER_ID}\n\t\t\t\tAND status.scope_type = ${COLLECTION_SCOPE}\n\t\t\t\tAND status.capture_state = 'active'\n\t\t\t\tAND status.reconciliation_required = 1\n\t\t\t\tAND status.collection_id IS NOT NULL\n\t\t\t\tAND EXISTS (\n\t\t\t\t\tSELECT 1 FROM _emdash_media_usage_activation AS activation\n\t\t\t\t\tWHERE activation.task_key = ${ACTIVATION_KEY}\n\t\t\t\t\t\tAND activation.state = 'active'\n\t\t\t\t)\n\t\t\t\tAND NOT EXISTS (\n\t\t\t\t\tSELECT 1 FROM _emdash_media_usage_reconciliations AS existing\n\t\t\t\t\tWHERE existing.collection_id = status.collection_id\n\t\t\t\t)\n\t\t\t\tAND NOT EXISTS (\n\t\t\t\t\tSELECT 1 FROM _emdash_media_usage_collection_deletions AS deletion\n\t\t\t\t\tWHERE deletion.collection_id = status.collection_id\n\t\t\t\t)\n\t\t\tORDER BY status.collection_id\n\t\t\tLIMIT 1\n\t\t\tON CONFLICT (collection_id) DO NOTHING\n\t\t\tRETURNING collection_id\n\t\t`.execute(this.db);\n\t\treturn result.rows.length === 1;\n\t}\n\n\tasync findDue(limit: number): Promise<MediaUsageReconciliationRecord[]> {\n\t\tassertLimit(limit);\n\t\tconst nextAttemptIsDue = timestampIsDue(this.db, \"next_attempt_at\");\n\t\tconst leaseIsDue = timestampIsDue(this.db, \"lease_expires_at\");\n\t\tconst result = await sql<Selectable<MediaUsageReconciliationTable>>`\n\t\t\tWITH pending_candidates AS (\n\t\t\t\tSELECT * FROM _emdash_media_usage_reconciliations\n\t\t\t\tWHERE state = 'pending' AND ${nextAttemptIsDue}\n\t\t\t\tORDER BY next_attempt_at, updated_at, collection_id\n\t\t\t\tLIMIT ${limit}\n\t\t\t), retry_candidates AS (\n\t\t\t\tSELECT * FROM _emdash_media_usage_reconciliations\n\t\t\t\tWHERE state = 'retry' AND ${nextAttemptIsDue}\n\t\t\t\tORDER BY next_attempt_at, updated_at, collection_id\n\t\t\t\tLIMIT ${limit}\n\t\t\t), leased_candidates AS (\n\t\t\t\tSELECT * FROM _emdash_media_usage_reconciliations\n\t\t\t\tWHERE state = 'leased' AND ${leaseIsDue}\n\t\t\t\tORDER BY lease_expires_at, updated_at, collection_id\n\t\t\t\tLIMIT ${limit}\n\t\t\t), candidates AS (\n\t\t\t\tSELECT * FROM pending_candidates\n\t\t\t\tUNION ALL SELECT * FROM retry_candidates\n\t\t\t\tUNION ALL SELECT * FROM leased_candidates\n\t\t\t)\n\t\t\tSELECT * FROM candidates\n\t\t\tORDER BY CASE WHEN state = 'leased' THEN lease_expires_at ELSE next_attempt_at END,\n\t\t\t\tupdated_at,\n\t\t\t\tcollection_id\n\t\t\tLIMIT ${limit}\n\t\t`.execute(this.db);\n\t\treturn result.rows.map(rowToRecord);\n\t}\n\n\tasync hasDeferredCandidate(): Promise<boolean> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_reconciliations\")\n\t\t\t.select(\"collection_id\")\n\t\t\t.where(\"state\", \"in\", [\"pending\", \"retry\", \"leased\"])\n\t\t\t.limit(1)\n\t\t\t.executeTakeFirst();\n\t\treturn row !== undefined;\n\t}\n\n\tasync wakeDrainedBarrierCandidate(): Promise<boolean> {\n\t\tconst now = timestampOffset(this.db, 0);\n\t\tconst candidateIsDue = timestampIsDue(this.db, \"reconciliation.next_attempt_at\");\n\t\tconst targetIsDue = timestampIsDue(\n\t\t\tthis.db,\n\t\t\t\"_emdash_media_usage_reconciliations.next_attempt_at\",\n\t\t);\n\t\tconst result = await sql<{ collection_id: string }>`\n\t\t\tUPDATE _emdash_media_usage_reconciliations\n\t\t\tSET next_attempt_at = ${now}, updated_at = ${now}\n\t\t\tWHERE collection_id = (\n\t\t\t\tSELECT reconciliation.collection_id\n\t\t\t\tFROM _emdash_media_usage_reconciliations AS reconciliation\n\t\t\t\tINNER JOIN _emdash_media_usage_index_status AS status\n\t\t\t\t\tON status.collection_id = reconciliation.collection_id\n\t\t\t\t\tAND status.scope_key = reconciliation.collection_slug\n\t\t\t\tWHERE reconciliation.state = 'pending'\n\t\t\t\t\tAND reconciliation.target_epoch IS NOT NULL\n\t\t\t\t\tAND NOT ${candidateIsDue}\n\t\t\t\t\tAND status.adapter_id = ${CONTENT_ADAPTER_ID}\n\t\t\t\t\tAND status.scope_type = ${COLLECTION_SCOPE}\n\t\t\t\t\tAND status.capture_state = 'active'\n\t\t\t\t\tAND status.reconciliation_required = 1\n\t\t\t\t\tAND status.status = 'running'\n\t\t\t\t\tAND status.cursor = reconciliation.run_token\n\t\t\t\t\tAND status.change_epoch = reconciliation.target_epoch\n\t\t\t\t\tAND NOT EXISTS (\n\t\t\t\t\t\tSELECT 1 FROM _emdash_media_usage_work AS work\n\t\t\t\t\t\tWHERE work.collection_id = reconciliation.collection_id\n\t\t\t\t\t)\n\t\t\t\t\tAND NOT EXISTS (\n\t\t\t\t\t\tSELECT 1 FROM _emdash_media_usage_collection_deletions AS deletion\n\t\t\t\t\t\tWHERE deletion.collection_id = reconciliation.collection_id\n\t\t\t\t\t)\n\t\t\t\tORDER BY reconciliation.next_attempt_at, reconciliation.updated_at,\n\t\t\t\t\treconciliation.collection_id\n\t\t\t\tLIMIT 1\n\t\t\t)\n\t\t\tAND state = 'pending'\n\t\t\tAND NOT ${targetIsDue}\n\t\t\tAND EXISTS (\n\t\t\t\tSELECT 1 FROM _emdash_media_usage_activation AS activation\n\t\t\t\tWHERE activation.task_key = ${ACTIVATION_KEY}\n\t\t\t\t\tAND activation.state = 'active'\n\t\t\t)\n\t\t\tAND NOT EXISTS (\n\t\t\t\tSELECT 1 FROM _emdash_media_usage_work AS work\n\t\t\t\tWHERE work.collection_id = _emdash_media_usage_reconciliations.collection_id\n\t\t\t)\n\t\t\tRETURNING collection_id\n\t\t`.execute(this.db);\n\t\treturn result.rows.length === 1;\n\t}\n\n\tasync findFailed(limit: number): Promise<MediaUsageReconciliationRecord[]> {\n\t\tassertLimit(limit);\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_media_usage_reconciliations as reconciliation\")\n\t\t\t.innerJoin(\"_emdash_media_usage_index_status as status\", (join) =>\n\t\t\t\tjoin\n\t\t\t\t\t.onRef(\"status.collection_id\", \"=\", \"reconciliation.collection_id\")\n\t\t\t\t\t.onRef(\"status.scope_key\", \"=\", \"reconciliation.collection_slug\"),\n\t\t\t)\n\t\t\t.selectAll(\"reconciliation\")\n\t\t\t.where(\"reconciliation.state\", \"=\", \"failed\")\n\t\t\t.where(\"status.adapter_id\", \"=\", CONTENT_ADAPTER_ID)\n\t\t\t.where(\"status.scope_type\", \"=\", COLLECTION_SCOPE)\n\t\t\t.where((eb) =>\n\t\t\t\teb.or([\n\t\t\t\t\teb(\"status.reconciliation_required\", \"=\", 0),\n\t\t\t\t\teb.and([\n\t\t\t\t\t\teb(\"status.status\", \"=\", \"running\"),\n\t\t\t\t\t\teb(\"status.cursor\", \"=\", eb.ref(\"reconciliation.run_token\")),\n\t\t\t\t\t]),\n\t\t\t\t\teb.and([\n\t\t\t\t\t\teb(\"status.cursor\", \"is\", null),\n\t\t\t\t\t\teb(\"status.change_epoch\", \">\", eb.ref(\"reconciliation.target_epoch\")),\n\t\t\t\t\t]),\n\t\t\t\t]),\n\t\t\t)\n\t\t\t.orderBy(\"reconciliation.updated_at\")\n\t\t\t.orderBy(\"reconciliation.collection_id\")\n\t\t\t.limit(limit)\n\t\t\t.execute();\n\t\treturn rows.map(rowToRecord);\n\t}\n\n\tasync claim(input: {\n\t\tcollectionId: string;\n\t\trunToken: string;\n\t\tleaseDurationSeconds: number;\n\t}): Promise<MediaUsageReconciliationClaim | null> {\n\t\tassertIdentity(input);\n\t\tassertDuration(input.leaseDurationSeconds, \"lease duration\");\n\t\tconst leaseToken = ulid();\n\t\tconst row = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_reconciliations as reconciliation\")\n\t\t\t.set({\n\t\t\t\tstate: \"leased\",\n\t\t\t\tlease_token: leaseToken,\n\t\t\t\tlease_expires_at: timestampOffset(this.db, input.leaseDurationSeconds),\n\t\t\t\tupdated_at: timestampOffset(this.db, 0),\n\t\t\t})\n\t\t\t.where(\"reconciliation.collection_id\", \"=\", input.collectionId)\n\t\t\t.where(\"reconciliation.run_token\", \"=\", input.runToken)\n\t\t\t.where((eb) =>\n\t\t\t\teb.or([\n\t\t\t\t\teb.and([\n\t\t\t\t\t\teb(\"reconciliation.state\", \"in\", [\"pending\", \"retry\"]),\n\t\t\t\t\t\ttimestampIsDue(this.db, \"reconciliation.next_attempt_at\"),\n\t\t\t\t\t]),\n\t\t\t\t\teb.and([\n\t\t\t\t\t\teb(\"reconciliation.state\", \"=\", \"leased\"),\n\t\t\t\t\t\ttimestampIsDue(this.db, \"reconciliation.lease_expires_at\"),\n\t\t\t\t\t]),\n\t\t\t\t]),\n\t\t\t)\n\t\t\t.where((eb) =>\n\t\t\t\teb.exists(\n\t\t\t\t\teb\n\t\t\t\t\t\t.selectFrom(\"_emdash_media_usage_activation as activation\")\n\t\t\t\t\t\t.select(\"activation.task_key\")\n\t\t\t\t\t\t.where(\"activation.task_key\", \"=\", ACTIVATION_KEY)\n\t\t\t\t\t\t.where(\"activation.state\", \"=\", \"active\"),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.where((eb) =>\n\t\t\t\teb.exists(\n\t\t\t\t\teb\n\t\t\t\t\t\t.selectFrom(\"_emdash_media_usage_index_status as status\")\n\t\t\t\t\t\t.innerJoin(\"_emdash_collections as collection\", (join) =>\n\t\t\t\t\t\t\tjoin\n\t\t\t\t\t\t\t\t.onRef(\"collection.id\", \"=\", \"status.collection_id\")\n\t\t\t\t\t\t\t\t.onRef(\"collection.slug\", \"=\", \"status.scope_key\"),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.select(\"status.collection_id\")\n\t\t\t\t\t\t.whereRef(\"status.collection_id\", \"=\", \"reconciliation.collection_id\")\n\t\t\t\t\t\t.whereRef(\"status.scope_key\", \"=\", \"reconciliation.collection_slug\")\n\t\t\t\t\t\t.where(\"status.adapter_id\", \"=\", CONTENT_ADAPTER_ID)\n\t\t\t\t\t\t.where(\"status.scope_type\", \"=\", COLLECTION_SCOPE)\n\t\t\t\t\t\t.where(\"status.capture_state\", \"=\", \"active\")\n\t\t\t\t\t\t.where(\"status.reconciliation_required\", \"=\", 1),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.where((eb) =>\n\t\t\t\teb.not(\n\t\t\t\t\teb.exists(\n\t\t\t\t\t\teb\n\t\t\t\t\t\t\t.selectFrom(\"_emdash_media_usage_collection_deletions as deletion\")\n\t\t\t\t\t\t\t.select(\"deletion.collection_id\")\n\t\t\t\t\t\t\t.whereRef(\"deletion.collection_id\", \"=\", \"reconciliation.collection_id\"),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.returningAll()\n\t\t\t.executeTakeFirst();\n\t\treturn row\n\t\t\t? ({ ...rowToRecord(row), leaseToken } satisfies MediaUsageReconciliationClaim)\n\t\t\t: null;\n\t}\n\n\tasync release(input: {\n\t\tcollectionId: string;\n\t\trunToken: string;\n\t\tleaseToken: string;\n\t\tdelaySeconds: number;\n\t}): Promise<boolean> {\n\t\tassertLeaseIdentity(input);\n\t\tassertDuration(input.delaySeconds, \"release delay\", true);\n\t\tconst result = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_reconciliations\")\n\t\t\t.set({\n\t\t\t\tstate: \"pending\",\n\t\t\t\tnext_attempt_at: timestampOffset(this.db, input.delaySeconds),\n\t\t\t\tlease_token: null,\n\t\t\t\tlease_expires_at: null,\n\t\t\t\tupdated_at: timestampOffset(this.db, 0),\n\t\t\t})\n\t\t\t.where(\"collection_id\", \"=\", input.collectionId)\n\t\t\t.where(\"run_token\", \"=\", input.runToken)\n\t\t\t.where(\"state\", \"=\", \"leased\")\n\t\t\t.where(\"lease_token\", \"=\", input.leaseToken)\n\t\t\t.where(liveLease(this.db))\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) === 1;\n\t}\n\n\tasync recordFailure(input: {\n\t\tcollectionId: string;\n\t\trunToken: string;\n\t\tleaseToken: string;\n\t\terrorCode: string;\n\t\tretryDelaySeconds: number;\n\t\tterminal: boolean;\n\t}): Promise<boolean> {\n\t\tassertLeaseIdentity(input);\n\t\tif (!STABLE_ERROR_CODE_PATTERN.test(input.errorCode)) {\n\t\t\tthrow new Error(\"Reconciliation failure requires a stable error code\");\n\t\t}\n\t\tassertDuration(input.retryDelaySeconds, \"retry delay\", true);\n\t\tconst result = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_reconciliations\")\n\t\t\t.set({\n\t\t\t\tstate: input.terminal\n\t\t\t\t\t? \"failed\"\n\t\t\t\t\t: sql<string>`CASE WHEN attempt_count >= 4 THEN 'failed' ELSE 'retry' END`,\n\t\t\t\t...(input.terminal\n\t\t\t\t\t? {\n\t\t\t\t\t\t\ttarget_epoch: sql<number | string | null>`COALESCE(\n\t\t\t\t\t\t\t\ttarget_epoch,\n\t\t\t\t\t\t\t\t(SELECT status.change_epoch\n\t\t\t\t\t\t\t\t FROM _emdash_media_usage_index_status AS status\n\t\t\t\t\t\t\t\t WHERE status.adapter_id = ${CONTENT_ADAPTER_ID}\n\t\t\t\t\t\t\t\t\tAND status.scope_type = ${COLLECTION_SCOPE}\n\t\t\t\t\t\t\t\t\tAND status.collection_id = ${input.collectionId}\n\t\t\t\t\t\t\t\t\tAND status.status = 'running'\n\t\t\t\t\t\t\t\t\tAND status.cursor = ${input.runToken})\n\t\t\t\t\t\t\t)`,\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\tattempt_count: sql<number>`attempt_count + 1`,\n\t\t\t\tnext_attempt_at: timestampOffset(this.db, input.retryDelaySeconds),\n\t\t\t\tlease_token: null,\n\t\t\t\tlease_expires_at: null,\n\t\t\t\tlast_error_code: input.errorCode,\n\t\t\t\tupdated_at: timestampOffset(this.db, 0),\n\t\t\t})\n\t\t\t.where(\"collection_id\", \"=\", input.collectionId)\n\t\t\t.where(\"run_token\", \"=\", input.runToken)\n\t\t\t.where(\"state\", \"=\", \"leased\")\n\t\t\t.where(\"lease_token\", \"=\", input.leaseToken)\n\t\t\t.where(liveLease(this.db))\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) === 1;\n\t}\n\n\tasync recordEntryFailure(claim: MediaUsageReconciliationClaim): Promise<boolean> {\n\t\tconst result = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_reconciliations as reconciliation\")\n\t\t\t.set({\n\t\t\t\tstate: \"failed\",\n\t\t\t\tattempt_count: sql<number>`attempt_count + 1`,\n\t\t\t\tnext_attempt_at: timestampOffset(this.db, 0),\n\t\t\t\tlease_token: null,\n\t\t\t\tlease_expires_at: null,\n\t\t\t\tlast_error_code: \"MEDIA_USAGE_RECONCILIATION_ENTRY_FAILED\",\n\t\t\t\tupdated_at: timestampOffset(this.db, 0),\n\t\t\t})\n\t\t\t.where(\"reconciliation.collection_id\", \"=\", claim.collectionId)\n\t\t\t.where(\"reconciliation.run_token\", \"=\", claim.runToken)\n\t\t\t.where(\"reconciliation.state\", \"=\", \"leased\")\n\t\t\t.where(\"reconciliation.lease_token\", \"=\", claim.leaseToken)\n\t\t\t.where(liveLease(this.db))\n\t\t\t.where((eb) =>\n\t\t\t\teb.exists(\n\t\t\t\t\teb\n\t\t\t\t\t\t.selectFrom(\"_emdash_media_usage_work as work\")\n\t\t\t\t\t\t.select(\"work.content_id\")\n\t\t\t\t\t\t.where(\"work.collection_id\", \"=\", claim.collectionId)\n\t\t\t\t\t\t.where(\"work.state\", \"=\", \"failed\"),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) === 1;\n\t}\n\n\tasync resetFailedForNewEpoch(\n\t\tobserved: Selectable<MediaUsageReconciliationTable> | MediaUsageReconciliationRecord,\n\t): Promise<boolean> {\n\t\tconst collectionId =\n\t\t\t\"collection_id\" in observed ? observed.collection_id : observed.collectionId;\n\t\tconst runToken = \"run_token\" in observed ? observed.run_token : observed.runToken;\n\t\tconst targetEpoch = \"target_epoch\" in observed ? observed.target_epoch : observed.targetEpoch;\n\t\tif (targetEpoch === null) return false;\n\t\tconst now = timestampOffset(this.db, 0);\n\t\tconst result = await this.db\n\t\t\t.updateTable(\"_emdash_media_usage_reconciliations as reconciliation\")\n\t\t\t.set({\n\t\t\t\tstate: \"pending\",\n\t\t\t\tphase: \"scan\",\n\t\t\t\ttarget_epoch: null,\n\t\t\t\tfield_fingerprint: null,\n\t\t\t\tscan_cursor: null,\n\t\t\t\tscan_upper_id: null,\n\t\t\t\tsource_cursor: null,\n\t\t\t\tsource_upper_key: null,\n\t\t\t\tattempt_count: 0,\n\t\t\t\tnext_attempt_at: now,\n\t\t\t\tlease_token: null,\n\t\t\t\tlease_expires_at: null,\n\t\t\t\tlast_error_code: null,\n\t\t\t\tupdated_at: now,\n\t\t\t})\n\t\t\t.where(\"reconciliation.collection_id\", \"=\", collectionId)\n\t\t\t.where(\"reconciliation.run_token\", \"=\", runToken)\n\t\t\t.where(\"reconciliation.state\", \"=\", \"failed\")\n\t\t\t.where(\"reconciliation.target_epoch\", \"=\", targetEpoch)\n\t\t\t.where((eb) =>\n\t\t\t\teb.exists(\n\t\t\t\t\teb\n\t\t\t\t\t\t.selectFrom(\"_emdash_media_usage_index_status as status\")\n\t\t\t\t\t\t.select(\"status.collection_id\")\n\t\t\t\t\t\t.whereRef(\"status.collection_id\", \"=\", \"reconciliation.collection_id\")\n\t\t\t\t\t\t.whereRef(\"status.scope_key\", \"=\", \"reconciliation.collection_slug\")\n\t\t\t\t\t\t.where(\"status.adapter_id\", \"=\", CONTENT_ADAPTER_ID)\n\t\t\t\t\t\t.where(\"status.scope_type\", \"=\", COLLECTION_SCOPE)\n\t\t\t\t\t\t.where(\"status.capture_state\", \"=\", \"active\")\n\t\t\t\t\t\t.where(\"status.reconciliation_required\", \"=\", 1)\n\t\t\t\t\t\t.where((status) =>\n\t\t\t\t\t\t\tstatus.or([\n\t\t\t\t\t\t\t\tstatus(\"status.cursor\", \"is\", null),\n\t\t\t\t\t\t\t\tstatus.and([\n\t\t\t\t\t\t\t\t\tstatus(\"status.status\", \"=\", \"running\"),\n\t\t\t\t\t\t\t\t\tstatus(\"status.cursor\", \"=\", runToken),\n\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.where(\"status.change_epoch\", \">\", targetEpoch),\n\t\t\t\t),\n\t\t\t)\n\t\t\t.executeTakeFirst();\n\t\treturn Number(result.numUpdatedRows ?? 0) === 1;\n\t}\n}\n\nfunction rowToRecord(\n\trow: Selectable<MediaUsageReconciliationTable>,\n): MediaUsageReconciliationRecord {\n\tif (!isState(row.state) || !isPhase(row.phase) || !Number.isSafeInteger(row.attempt_count)) {\n\t\tthrow new Error(\"Invalid media usage reconciliation lifecycle\");\n\t}\n\treturn {\n\t\tcollectionId: row.collection_id,\n\t\tcollectionSlug: row.collection_slug,\n\t\trunToken: row.run_token,\n\t\ttargetEpoch: row.target_epoch,\n\t\tfieldFingerprint: row.field_fingerprint,\n\t\tstate: row.state,\n\t\tphase: row.phase,\n\t\tscanCursor: row.scan_cursor,\n\t\tscanUpperId: row.scan_upper_id,\n\t\tsourceCursor: row.source_cursor,\n\t\tsourceUpperKey: row.source_upper_key,\n\t\tattemptCount: row.attempt_count,\n\t\tnextAttemptAt: row.next_attempt_at,\n\t\tleaseToken: row.lease_token,\n\t\tleaseExpiresAt: row.lease_expires_at,\n\t\tlastErrorCode: row.last_error_code,\n\t\tcreatedAt: row.created_at,\n\t\tupdatedAt: row.updated_at,\n\t};\n}\n\nfunction isState(state: string): state is MediaUsageReconciliationState {\n\treturn state === \"pending\" || state === \"retry\" || state === \"leased\" || state === \"failed\";\n}\n\nfunction isPhase(phase: string): phase is MediaUsageReconciliationPhase {\n\treturn phase === \"scan\" || phase === \"sources\";\n}\n\nfunction assertLimit(limit: number): void {\n\tif (!Number.isSafeInteger(limit) || limit < 1 || limit > MAX_CANDIDATES) {\n\t\tthrow new Error(\"Reconciliation candidate limit must be from 1 to 100\");\n\t}\n}\n\nfunction assertIdentity(input: { collectionId: string; runToken: string }): void {\n\tif (!input.collectionId || !input.runToken) {\n\t\tthrow new Error(\"Reconciliation requires an exact collection and run token\");\n\t}\n}\n\nfunction assertLeaseIdentity(input: {\n\tcollectionId: string;\n\trunToken: string;\n\tleaseToken: string;\n}): void {\n\tassertIdentity(input);\n\tif (!input.leaseToken) throw new Error(\"Reconciliation requires a lease token\");\n}\n\nfunction assertDuration(value: number, label: string, allowZero = false): void {\n\tif (\n\t\t!Number.isSafeInteger(value) ||\n\t\tvalue < (allowZero ? 0 : 1) ||\n\t\tvalue > MAX_PORTABLE_DURATION_SECONDS\n\t) {\n\t\tthrow new Error(`Reconciliation ${label} is outside the portable range`);\n\t}\n}\n\nfunction liveLease(db: Kysely<Database>, column = \"lease_expires_at\"): RawBuilder<boolean> {\n\tconst expiry = sql.ref(column);\n\treturn isPostgres(db)\n\t\t? sql<boolean>`${expiry} > to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"')`\n\t\t: sql<boolean>`${expiry} > strftime('%Y-%m-%dT%H:%M:%fZ', 'now')`;\n}\n\nfunction timestampIsDue(db: Kysely<Database>, column: string): RawBuilder<boolean> {\n\tconst value = sql.ref(column);\n\treturn isPostgres(db)\n\t\t? sql<boolean>`${value} <= to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"')`\n\t\t: sql<boolean>`${value} <= strftime('%Y-%m-%dT%H:%M:%fZ', 'now')`;\n}\n\nfunction timestampOffset(db: Kysely<Database>, offsetSeconds: number): RawBuilder<string> {\n\tif (isPostgres(db)) {\n\t\treturn sql<string>`to_char(\n\t\t\t(clock_timestamp() AT TIME ZONE 'UTC') + (${offsetSeconds} * INTERVAL '1 second'),\n\t\t\t'YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"'\n\t\t)`;\n\t}\n\treturn sql<string>`strftime(\n\t\t'%Y-%m-%dT%H:%M:%fZ',\n\t\t'now',\n\t\t${`${offsetSeconds >= 0 ? \"+\" : \"\"}${offsetSeconds} seconds`}\n\t)`;\n}\n\nfunction contentTableName(collectionSlug: string): string {\n\tvalidateIdentifier(collectionSlug, \"collection slug\");\n\tconst tableName = `ec_${collectionSlug}`;\n\tvalidateIdentifier(tableName, \"content table\");\n\treturn tableName;\n}\n","import type { Kysely } from \"kysely\";\n\nimport { MediaUsageWorkRepository } from \"../../database/repositories/media-usage-work.js\";\nimport type { Database } from \"../../database/types.js\";\nimport {\n\tbuildContentMediaUsageFieldFingerprint,\n\tloadContentMediaUsageFields,\n} from \"./content-fields.js\";\nimport {\n\tMediaUsageReconciliationRepository,\n\ttype MediaUsageReconciliationClaim,\n\ttype MediaUsageReconciliationRecord,\n} from \"./reconciliation.js\";\nimport { CONTENT_SOURCE_SCHEMA_VERSION } from \"./types.js\";\n\nexport const MEDIA_USAGE_RECONCILIATION_LIMITS = Object.freeze({\n\tcandidatesPerTick: 4,\n\tscanPageSize: 1_000,\n\tsourcePageSize: 1_000,\n\tleaseDurationSeconds: 60,\n\tmaxAttempts: 5,\n\tretryBaseSeconds: 30,\n\tretryMaxSeconds: 15 * 60,\n\tretryJitterRatio: 0.25,\n});\n\nexport type MediaUsageReconciliationOutcome =\n\t| \"inactive\"\n\t| \"not_due\"\n\t| \"claim_lost\"\n\t| \"advanced\"\n\t| \"deferred\"\n\t| \"completed\"\n\t| \"retry\"\n\t| \"failed\";\n\nexport interface MediaUsageReconciliationDetailedResult {\n\toutcome: MediaUsageReconciliationOutcome;\n\tconsumedUnit: boolean;\n\thasDeferredCandidate: boolean;\n}\n\nexport interface ProcessDueMediaUsageReconciliationOptions {\n\tactivationKnownActive?: boolean;\n}\n\nexport type MediaUsageReconciliationScanOutcome =\n\t| \"advanced\"\n\t| \"exhausted\"\n\t| \"deferred\"\n\t| \"restart_required\";\n\nexport async function processDueMediaUsageReconciliation(\n\tdb: Kysely<Database>,\n): Promise<MediaUsageReconciliationOutcome> {\n\treturn (await processDueMediaUsageReconciliationDetailed(db)).outcome;\n}\n\nexport async function processDueMediaUsageReconciliationDetailed(\n\tdb: Kysely<Database>,\n\toptions: ProcessDueMediaUsageReconciliationOptions = {},\n): Promise<MediaUsageReconciliationDetailedResult> {\n\tif (!options.activationKnownActive) {\n\t\tconst activation = await db\n\t\t\t.selectFrom(\"_emdash_media_usage_activation\")\n\t\t\t.select(\"state\")\n\t\t\t.where(\"task_key\", \"=\", \"incremental_capture\")\n\t\t\t.executeTakeFirst();\n\t\tif (activation?.state !== \"active\") {\n\t\t\treturn { outcome: \"inactive\", consumedUnit: false, hasDeferredCandidate: false };\n\t\t}\n\t}\n\n\tconst reconciliation = new MediaUsageReconciliationRepository(db);\n\tif (await reconciliation.deleteOneObsolete()) {\n\t\treturn { outcome: \"completed\", consumedUnit: true, hasDeferredCandidate: false };\n\t}\n\tconst [failed] = await reconciliation.findFailed(1);\n\tif (failed) {\n\t\tif (await reconciliation.finishFailedCoverage(failed.collectionId, failed.runToken)) {\n\t\t\treturn { outcome: \"failed\", consumedUnit: true, hasDeferredCandidate: false };\n\t\t}\n\t\tif (await reconciliation.resetFailedForNewEpoch(failed)) {\n\t\t\treturn { outcome: \"advanced\", consumedUnit: true, hasDeferredCandidate: false };\n\t\t}\n\t}\n\n\tconst seeded = await reconciliation.seedNextCandidate();\n\tconst candidates = await reconciliation.findDue(\n\t\tMEDIA_USAGE_RECONCILIATION_LIMITS.candidatesPerTick,\n\t);\n\tlet claim: MediaUsageReconciliationClaim | null = null;\n\tfor (const candidate of candidates) {\n\t\tclaim = await reconciliation.claim({\n\t\t\tcollectionId: candidate.collectionId,\n\t\t\trunToken: candidate.runToken,\n\t\t\tleaseDurationSeconds: MEDIA_USAGE_RECONCILIATION_LIMITS.leaseDurationSeconds,\n\t\t});\n\t\tif (claim) break;\n\t}\n\tif (!claim) {\n\t\treturn {\n\t\t\toutcome: candidates.length === 0 ? \"not_due\" : \"claim_lost\",\n\t\t\tconsumedUnit: seeded,\n\t\t\thasDeferredCandidate:\n\t\t\t\tcandidates.length === 0 && (await reconciliation.hasDeferredCandidate()),\n\t\t};\n\t}\n\n\ttry {\n\t\treturn {\n\t\t\toutcome: await processClaimedReconciliation(db, claim),\n\t\t\tconsumedUnit: true,\n\t\t\thasDeferredCandidate: false,\n\t\t};\n\t} catch (error) {\n\t\tconst terminal = claim.attemptCount + 1 >= MEDIA_USAGE_RECONCILIATION_LIMITS.maxAttempts;\n\t\tconst recorded = await reconciliation.recordFailure({\n\t\t\tcollectionId: claim.collectionId,\n\t\t\trunToken: claim.runToken,\n\t\t\tleaseToken: claim.leaseToken,\n\t\t\terrorCode: \"MEDIA_USAGE_RECONCILIATION_FAILED\",\n\t\t\tretryDelaySeconds: retryDelaySeconds(claim.attemptCount),\n\t\t\tterminal,\n\t\t});\n\t\tif (!recorded) {\n\t\t\treturn { outcome: \"claim_lost\", consumedUnit: true, hasDeferredCandidate: false };\n\t\t}\n\t\tif (terminal) await reconciliation.finishFailedCoverage(claim.collectionId, claim.runToken);\n\t\tconsole.error(\"[media-usage:reconciliation] Processing failed:\", error);\n\t\treturn {\n\t\t\toutcome: terminal ? \"failed\" : \"retry\",\n\t\t\tconsumedUnit: true,\n\t\t\thasDeferredCandidate: false,\n\t\t};\n\t}\n}\n\nexport async function processClaimedMediaUsageReconciliationScan(\n\tdb: Kysely<Database>,\n\tclaim: MediaUsageReconciliationClaim,\n\toptions: { releaseOnExhausted?: boolean } = {},\n\tknownCurrent?: MediaUsageReconciliationRecord,\n): Promise<MediaUsageReconciliationScanOutcome> {\n\tconst reconciliation = new MediaUsageReconciliationRepository(db);\n\tlet current =\n\t\tknownCurrent ?? (await reconciliation.findByIdentity(claim.collectionId, claim.runToken));\n\tif (!current || current.leaseToken !== claim.leaseToken || current.phase !== \"scan\") {\n\t\treturn \"deferred\";\n\t}\n\n\tlet fields;\n\tlet fieldFingerprint: string;\n\tif (current.targetEpoch === null) {\n\t\tconst targetEpoch = await reconciliation.beginRun(claim);\n\t\tif (targetEpoch === null) {\n\t\t\tawait reconciliation.release({ ...claim, delaySeconds: 30 });\n\t\t\treturn \"deferred\";\n\t\t}\n\t\tfields = await loadContentMediaUsageFields(db, claim.collectionSlug, claim.collectionId);\n\t\tfieldFingerprint = await buildContentMediaUsageFieldFingerprint(fields);\n\t\tconst scanUpperId =\n\t\t\tfields.extractionFields.length === 0 ? null : await reconciliation.findScanUpperId(claim);\n\t\tif (\n\t\t\t!(await reconciliation.initializeScan({\n\t\t\t\tclaim,\n\t\t\t\ttargetEpoch,\n\t\t\t\tfieldFingerprint,\n\t\t\t\tscanUpperId,\n\t\t\t}))\n\t\t) {\n\t\t\treturn \"deferred\";\n\t\t}\n\t\tcurrent = {\n\t\t\t...current,\n\t\t\ttargetEpoch,\n\t\t\tfieldFingerprint,\n\t\t\tscanCursor: null,\n\t\t\tscanUpperId,\n\t\t\tsourceCursor: null,\n\t\t\tsourceUpperKey: null,\n\t\t};\n\t} else {\n\t\tfields = await loadContentMediaUsageFields(db, claim.collectionSlug, claim.collectionId);\n\t\tfieldFingerprint = await buildContentMediaUsageFieldFingerprint(fields);\n\t}\n\n\tif (current.fieldFingerprint !== fieldFingerprint || current.targetEpoch === null) {\n\t\treturn \"restart_required\";\n\t}\n\tconst contentIds = await reconciliation.findScanPage(\n\t\tcurrent,\n\t\tMEDIA_USAGE_RECONCILIATION_LIMITS.scanPageSize,\n\t);\n\tif (contentIds.length === 0) {\n\t\tif (options.releaseOnExhausted ?? true) {\n\t\t\tawait reconciliation.release({ ...claim, delaySeconds: 30 });\n\t\t}\n\t\treturn \"exhausted\";\n\t}\n\n\tconst work = new MediaUsageWorkRepository(db);\n\tawait work.enqueueReconciliationPage({\n\t\tcollectionId: claim.collectionId,\n\t\tcollectionSlug: claim.collectionSlug,\n\t\trunToken: claim.runToken,\n\t\tleaseToken: claim.leaseToken,\n\t\tchangeEpoch: current.targetEpoch,\n\t\tphase: \"scan\",\n\t\tcontentIds,\n\t});\n\tconst nextCursor = contentIds.at(-1)!;\n\tif (\n\t\t!(await reconciliation.checkpointScan({\n\t\t\tclaim,\n\t\t\ttargetEpoch: current.targetEpoch,\n\t\t\tpreviousCursor: current.scanCursor,\n\t\t\tnextCursor,\n\t\t}))\n\t) {\n\t\treturn \"deferred\";\n\t}\n\tif (!(await reconciliation.release({ ...claim, delaySeconds: 0 }))) return \"deferred\";\n\treturn \"advanced\";\n}\n\nasync function processClaimedReconciliation(\n\tdb: Kysely<Database>,\n\tclaim: MediaUsageReconciliationClaim,\n): Promise<MediaUsageReconciliationOutcome> {\n\tconst reconciliation = new MediaUsageReconciliationRepository(db);\n\tlet current: MediaUsageReconciliationRecord = claim;\n\tif (current.targetEpoch !== null && !(await reconciliation.ownsRun(claim, current.targetEpoch))) {\n\t\treturn restartReconciliation(db, reconciliation, claim, current);\n\t}\n\tif (current.targetEpoch !== null) {\n\t\tawait new MediaUsageWorkRepository(db).deleteObsoleteReconciliationWork({\n\t\t\tcollectionId: claim.collectionId,\n\t\t\tcollectionSlug: claim.collectionSlug,\n\t\t\trunToken: claim.runToken,\n\t\t\tleaseToken: claim.leaseToken,\n\t\t\ttargetEpoch: current.targetEpoch,\n\t\t});\n\t}\n\n\tif (current.phase === \"scan\") {\n\t\tconst outcome = await processClaimedMediaUsageReconciliationScan(\n\t\t\tdb,\n\t\t\tclaim,\n\t\t\t{\n\t\t\t\treleaseOnExhausted: false,\n\t\t\t},\n\t\t\tcurrent,\n\t\t);\n\t\tif (outcome === \"restart_required\") {\n\t\t\tcurrent =\n\t\t\t\t(await reconciliation.findByIdentity(claim.collectionId, claim.runToken)) ?? current;\n\t\t\treturn restartReconciliation(db, reconciliation, claim, current);\n\t\t}\n\t\tif (outcome !== \"exhausted\") return outcome;\n\t\tif (current.targetEpoch === null || current.fieldFingerprint === null) {\n\t\t\tcurrent =\n\t\t\t\t(await reconciliation.findByIdentity(claim.collectionId, claim.runToken)) ?? current;\n\t\t}\n\t\tconst barrier = await reconciliation.findWorkBarrier(claim.collectionId);\n\t\tif (barrier.state === \"failed\") {\n\t\t\treturn failReconciliation(reconciliation, claim, barrier.errorCode, true);\n\t\t}\n\t\tif (barrier.state === \"pending\") {\n\t\t\tawait reconciliation.release({ ...claim, delaySeconds: 30 });\n\t\t\treturn \"deferred\";\n\t\t}\n\t\tif (current.targetEpoch === null || current.fieldFingerprint === null) return \"claim_lost\";\n\t\tconst sourceUpperKey = await reconciliation.findSourceUpperKey(claim, current.targetEpoch);\n\t\tif (\n\t\t\t!(await reconciliation.transitionToSources({\n\t\t\t\tclaim,\n\t\t\t\ttargetEpoch: current.targetEpoch,\n\t\t\t\tfieldFingerprint: current.fieldFingerprint,\n\t\t\t\tsourceUpperKey,\n\t\t\t}))\n\t\t) {\n\t\t\treturn \"claim_lost\";\n\t\t}\n\t\tif (!(await reconciliation.release({ ...claim, delaySeconds: 0 }))) return \"claim_lost\";\n\t\treturn \"advanced\";\n\t}\n\n\treturn processSourcePhase(db, reconciliation, claim, current);\n}\n\nasync function processSourcePhase(\n\tdb: Kysely<Database>,\n\treconciliation: MediaUsageReconciliationRepository,\n\tclaim: MediaUsageReconciliationClaim,\n\tcurrent: MediaUsageReconciliationRecord,\n): Promise<MediaUsageReconciliationOutcome> {\n\tif (current.targetEpoch === null || current.fieldFingerprint === null) return \"claim_lost\";\n\tconst fields = await loadContentMediaUsageFields(db, claim.collectionSlug, claim.collectionId);\n\tconst fieldFingerprint = await buildContentMediaUsageFieldFingerprint(fields);\n\tif (fieldFingerprint !== current.fieldFingerprint) {\n\t\treturn restartReconciliation(db, reconciliation, claim, current, fields, fieldFingerprint);\n\t}\n\n\tconst page = await reconciliation.findSourcePage(\n\t\tcurrent,\n\t\tMEDIA_USAGE_RECONCILIATION_LIMITS.sourcePageSize,\n\t);\n\tif (page.length > 0) {\n\t\tlet enqueuedMissingContent = false;\n\t\tconst malformed = page.some(\n\t\t\t(source) =>\n\t\t\t\t!source.contentId ||\n\t\t\t\t(source.sourceVariant !== \"columns\" && source.sourceVariant !== \"draft_overlay\"),\n\t\t);\n\t\tif (malformed) {\n\t\t\treturn failReconciliation(\n\t\t\t\treconciliation,\n\t\t\t\tclaim,\n\t\t\t\t\"MEDIA_USAGE_RECONCILIATION_INVALID_SOURCE\",\n\t\t\t\tfalse,\n\t\t\t);\n\t\t}\n\t\tconst contentIds = [...new Set(page.map((source) => source.contentId!))];\n\t\tconst enqueueIds =\n\t\t\tfields.extractionFields.length === 0\n\t\t\t\t? contentIds\n\t\t\t\t: await reconciliation.findMissingContentIds(claim.collectionSlug, contentIds);\n\t\tif (enqueueIds.length > 0) {\n\t\t\tawait new MediaUsageWorkRepository(db).enqueueReconciliationPage({\n\t\t\t\tcollectionId: claim.collectionId,\n\t\t\t\tcollectionSlug: claim.collectionSlug,\n\t\t\t\trunToken: claim.runToken,\n\t\t\t\tleaseToken: claim.leaseToken,\n\t\t\t\tchangeEpoch: current.targetEpoch,\n\t\t\t\tphase: \"sources\",\n\t\t\t\tcontentIds: enqueueIds,\n\t\t\t});\n\t\t\tenqueuedMissingContent = true;\n\t\t}\n\t\tif (\n\t\t\t!(await reconciliation.checkpointSources({\n\t\t\t\tclaim,\n\t\t\t\ttargetEpoch: current.targetEpoch,\n\t\t\t\tpreviousCursor: current.sourceCursor,\n\t\t\t\tnextCursor: page.at(-1)!.sourceKey,\n\t\t\t}))\n\t\t) {\n\t\t\treturn \"claim_lost\";\n\t\t}\n\t\tif (\n\t\t\tenqueuedMissingContent ||\n\t\t\tpage.length === MEDIA_USAGE_RECONCILIATION_LIMITS.sourcePageSize\n\t\t) {\n\t\t\tif (!(await reconciliation.release({ ...claim, delaySeconds: 0 }))) return \"claim_lost\";\n\t\t\treturn \"advanced\";\n\t\t}\n\t}\n\n\tconst barrier = await reconciliation.findWorkBarrier(claim.collectionId);\n\tif (barrier.state === \"failed\") {\n\t\treturn failReconciliation(reconciliation, claim, barrier.errorCode, true);\n\t}\n\tif (barrier.state === \"pending\") {\n\t\tawait reconciliation.release({ ...claim, delaySeconds: 30 });\n\t\treturn \"deferred\";\n\t}\n\tif (\n\t\t!(await reconciliation.finalizeCoverage({\n\t\t\tclaim,\n\t\t\ttargetEpoch: current.targetEpoch,\n\t\t\tfieldFingerprint,\n\t\t\tschemaVersion: CONTENT_SOURCE_SCHEMA_VERSION,\n\t\t}))\n\t) {\n\t\treturn \"claim_lost\";\n\t}\n\tif (!(await reconciliation.deleteFinalized(claim))) return \"claim_lost\";\n\treturn \"completed\";\n}\n\nasync function restartReconciliation(\n\tdb: Kysely<Database>,\n\treconciliation: MediaUsageReconciliationRepository,\n\tclaim: MediaUsageReconciliationClaim,\n\tcurrent: MediaUsageReconciliationRecord,\n\tfields?: Awaited<ReturnType<typeof loadContentMediaUsageFields>>,\n\tfieldFingerprint?: string,\n): Promise<MediaUsageReconciliationOutcome> {\n\tif (current.targetEpoch === null) return \"claim_lost\";\n\tconst discoveredFields =\n\t\tfields ?? (await loadContentMediaUsageFields(db, claim.collectionSlug, claim.collectionId));\n\tconst fingerprint =\n\t\tfieldFingerprint ?? (await buildContentMediaUsageFieldFingerprint(discoveredFields));\n\tconst targetEpoch = await reconciliation.restartRun(claim, current.targetEpoch);\n\tif (targetEpoch === null) {\n\t\tawait reconciliation.release({ ...claim, delaySeconds: 30 });\n\t\treturn \"deferred\";\n\t}\n\tconst scanUpperId =\n\t\tdiscoveredFields.extractionFields.length === 0\n\t\t\t? null\n\t\t\t: await reconciliation.findScanUpperId(claim);\n\tif (\n\t\t!(await reconciliation.restartScan({\n\t\t\tclaim,\n\t\t\tpreviousEpoch: current.targetEpoch,\n\t\t\ttargetEpoch,\n\t\t\tfieldFingerprint: fingerprint,\n\t\t\tscanUpperId,\n\t\t}))\n\t) {\n\t\treturn \"claim_lost\";\n\t}\n\tif (!(await reconciliation.release({ ...claim, delaySeconds: 0 }))) return \"claim_lost\";\n\treturn \"advanced\";\n}\n\nasync function failReconciliation(\n\treconciliation: MediaUsageReconciliationRepository,\n\tclaim: MediaUsageReconciliationClaim,\n\terrorCode: string,\n\tentryFailure: boolean,\n): Promise<MediaUsageReconciliationOutcome> {\n\tconst recorded = entryFailure\n\t\t? await reconciliation.recordEntryFailure(claim)\n\t\t: await reconciliation.recordFailure({\n\t\t\t\tcollectionId: claim.collectionId,\n\t\t\t\trunToken: claim.runToken,\n\t\t\t\tleaseToken: claim.leaseToken,\n\t\t\t\terrorCode,\n\t\t\t\tretryDelaySeconds: 0,\n\t\t\t\tterminal: true,\n\t\t\t});\n\tif (!recorded) return \"claim_lost\";\n\tawait reconciliation.finishFailedCoverage(claim.collectionId, claim.runToken);\n\treturn \"failed\";\n}\n\nfunction retryDelaySeconds(attemptCount: number): number {\n\tconst exponential = Math.min(\n\t\tMEDIA_USAGE_RECONCILIATION_LIMITS.retryMaxSeconds,\n\t\tMEDIA_USAGE_RECONCILIATION_LIMITS.retryBaseSeconds * 2 ** attemptCount,\n\t);\n\tconst jitter = Math.floor(\n\t\texponential * MEDIA_USAGE_RECONCILIATION_LIMITS.retryJitterRatio * Math.random(),\n\t);\n\treturn Math.min(MEDIA_USAGE_RECONCILIATION_LIMITS.retryMaxSeconds, exponential + jitter);\n}\n","import type { Kysely } from \"kysely\";\n\nimport { isPostgres } from \"../../database/dialect-helpers.js\";\nimport {\n\tMediaUsageWorkRepository,\n\ttype MediaUsageWorkRecord,\n} from \"../../database/repositories/media-usage-work.js\";\nimport { MediaUsageRepository } from \"../../database/repositories/media-usage.js\";\nimport { withTransaction } from \"../../database/transaction.js\";\nimport type { Database } from \"../../database/types.js\";\nimport { getRequestContext } from \"../../request-context.js\";\nimport {\n\tcontentRefreshKey,\n\trefreshContentMediaUsageForWorkBatch,\n\ttype ContentMediaUsageRefreshResult,\n\ttype ContentMediaUsageRefreshErrorCode,\n} from \"./content-refresh.js\";\n\nexport const MEDIA_USAGE_WORK_PROCESSING_LIMITS = Object.freeze({\n\tcandidatesPerTick: 1_000,\n\tleaseDurationSeconds: 20 * 60,\n\tmaxAttempts: 5,\n\tretryBaseSeconds: 30,\n\tretryMaxSeconds: 15 * 60,\n\tretryJitterRatio: 0.25,\n});\n\nexport type MediaUsageWorkProcessingOutcome =\n\t| \"inactive\"\n\t| \"not_due\"\n\t| \"claim_lost\"\n\t| \"completed\"\n\t| \"retry\"\n\t| \"failed\"\n\t| \"superseded\"\n\t| \"obsolete\";\n\nexport interface MediaUsageWorkProcessingResult {\n\toutcome: MediaUsageWorkProcessingOutcome;\n\tclaimed: boolean;\n}\n\nexport interface MediaUsageWorkTickResult {\n\tcandidateCount: number;\n\tclaimedCount: number;\n\tcompletedCount: number;\n\tretryCount: number;\n\tfailedCount: number;\n\tsupersededCount: number;\n\tobsoleteCount: number;\n\tdurationMs: number;\n}\n\nexport interface ProcessDueMediaUsageWorkOptions {\n\tactivationKnownActive?: boolean;\n}\n\nexport async function processMediaUsageWorkAfterWrite(\n\tdb: Kysely<Database>,\n\tcollectionSlug: string,\n\tcontentId: string,\n): Promise<MediaUsageWorkProcessingResult> {\n\tif (!(await isIncrementalCaptureActive(db))) {\n\t\treturn { outcome: \"inactive\", claimed: false };\n\t}\n\n\tawait new MediaUsageRepository(db).recoverIncrementalFinalizations();\n\tconst repo = new MediaUsageWorkRepository(db);\n\tconst work = await repo.findWorkForContent(collectionSlug, contentId);\n\tif (!work) return { outcome: \"not_due\", claimed: false };\n\tconst claimed = await repo.claimWork({\n\t\tcollectionId: work.collectionId,\n\t\tcontentId: work.contentId,\n\t\tworkVersion: work.workVersion,\n\t\tleaseDurationSeconds: MEDIA_USAGE_WORK_PROCESSING_LIMITS.leaseDurationSeconds,\n\t});\n\tif (!claimed) return { outcome: \"claim_lost\", claimed: false };\n\ttry {\n\t\tconst processed = await runClaimedBatch(db, [claimed]);\n\t\treturn processed.get(workResultKey(claimed)) ?? { outcome: \"claim_lost\", claimed: false };\n\t} catch (error) {\n\t\tconst transitioned = await repo.retryClaimedWorkBatch({\n\t\t\twork: [workLease(claimed)],\n\t\t\terrorCode: \"MEDIA_USAGE_PROCESSING_FAILED\",\n\t\t\tretryDelaySeconds: MEDIA_USAGE_WORK_PROCESSING_LIMITS.retryBaseSeconds,\n\t\t\tmaxAttempts: MEDIA_USAGE_WORK_PROCESSING_LIMITS.maxAttempts,\n\t\t});\n\t\tconst outcome = transitioned.get(workIdentityKey(claimed)) ?? \"superseded\";\n\t\tif (outcome === \"failed\") {\n\t\t\tawait new MediaUsageRepository(db).recordIncrementalFailure({\n\t\t\t\tcollectionId: claimed.collectionId,\n\t\t\t\tcollectionSlug: claimed.collectionSlug,\n\t\t\t\tcontentId: claimed.contentId,\n\t\t\t\tworkVersion: claimed.workVersion,\n\t\t\t\terrorCode: \"MEDIA_USAGE_PROCESSING_FAILED\",\n\t\t\t});\n\t\t}\n\t\tconsole.error(\"[media-usage:work] Immediate processing failed:\", error);\n\t\treturn { outcome, claimed: true };\n\t}\n}\n\nexport async function processDueMediaUsageWork(\n\tdb: Kysely<Database>,\n\toptions: ProcessDueMediaUsageWorkOptions = {},\n): Promise<MediaUsageWorkTickResult> {\n\tconst startedAt = Date.now();\n\tconst result: MediaUsageWorkTickResult = {\n\t\tcandidateCount: 0,\n\t\tclaimedCount: 0,\n\t\tcompletedCount: 0,\n\t\tretryCount: 0,\n\t\tfailedCount: 0,\n\t\tsupersededCount: 0,\n\t\tobsoleteCount: 0,\n\t\tdurationMs: 0,\n\t};\n\n\tif (!options.activationKnownActive && !(await isIncrementalCaptureActive(db))) {\n\t\tresult.durationMs = Date.now() - startedAt;\n\t\treturn result;\n\t}\n\n\tawait new MediaUsageRepository(db).recoverIncrementalFinalizations();\n\tconst repo = new MediaUsageWorkRepository(db);\n\tconst candidates = await repo.claimDueWorkBatch({\n\t\tlimit: MEDIA_USAGE_WORK_PROCESSING_LIMITS.candidatesPerTick,\n\t\tleaseDurationSeconds: MEDIA_USAGE_WORK_PROCESSING_LIMITS.leaseDurationSeconds,\n\t});\n\tresult.candidateCount =\n\t\tcandidates.length > 0 || !(await repo.hasNonterminalWork()) ? candidates.length : 1;\n\n\tconst processedBatch = await processClaimedCollections(db, candidates);\n\tfor (const candidate of candidates) {\n\t\tconst processed = processedBatch.get(workResultKey(candidate)) ?? {\n\t\t\toutcome: \"claim_lost\" as const,\n\t\t\tclaimed: false,\n\t\t};\n\t\tif (processed.claimed) result.claimedCount++;\n\t\tif (processed.outcome === \"completed\") result.completedCount++;\n\t\tif (processed.outcome === \"retry\") result.retryCount++;\n\t\tif (processed.outcome === \"failed\") result.failedCount++;\n\t\tif (processed.outcome === \"superseded\") result.supersededCount++;\n\t\tif (processed.outcome === \"obsolete\") result.obsoleteCount++;\n\t}\n\n\tresult.durationMs = Date.now() - startedAt;\n\treturn result;\n}\n\nasync function processClaimedCollections(\n\tdb: Kysely<Database>,\n\tcandidates: readonly MediaUsageWorkRecord[],\n): Promise<Map<string, MediaUsageWorkProcessingResult>> {\n\tconst processed = new Map<string, MediaUsageWorkProcessingResult>();\n\tconst byCollection = new Map<string, MediaUsageWorkRecord[]>();\n\tfor (const candidate of candidates) {\n\t\tconst key = collectionResultKey(candidate);\n\t\tconst collection = byCollection.get(key) ?? [];\n\t\tcollection.push(candidate);\n\t\tbyCollection.set(key, collection);\n\t}\n\tfor (const collection of byCollection.values()) {\n\t\ttry {\n\t\t\tfor (const [key, result] of await runClaimedBatch(db, collection)) {\n\t\t\t\tprocessed.set(key, result);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tfor (const [key, result] of await retryFailedClaimedCollection(db, collection)) {\n\t\t\t\tprocessed.set(key, result);\n\t\t\t}\n\t\t\tconsole.error(\"[media-usage:work] Collection processing failed:\", error);\n\t\t}\n\t}\n\treturn processed;\n}\n\nasync function retryFailedClaimedCollection(\n\tdb: Kysely<Database>,\n\tcandidates: readonly MediaUsageWorkRecord[],\n): Promise<Map<string, MediaUsageWorkProcessingResult>> {\n\tconst transitioned = await new MediaUsageWorkRepository(db).retryClaimedWorkBatch({\n\t\twork: candidates.map(workLease),\n\t\terrorCode: \"MEDIA_USAGE_PROCESSING_FAILED\",\n\t\tretryDelaySeconds: MEDIA_USAGE_WORK_PROCESSING_LIMITS.retryBaseSeconds,\n\t\tmaxAttempts: MEDIA_USAGE_WORK_PROCESSING_LIMITS.maxAttempts,\n\t});\n\tconst processed = new Map<string, MediaUsageWorkProcessingResult>();\n\tconst failedCollectionIds = new Set<string>();\n\tfor (const candidate of candidates) {\n\t\tconst state = transitioned.get(workIdentityKey(candidate));\n\t\tif (state === \"failed\") failedCollectionIds.add(candidate.collectionId);\n\t\tprocessed.set(workResultKey(candidate), {\n\t\t\toutcome: state ?? \"superseded\",\n\t\t\tclaimed: true,\n\t\t});\n\t}\n\tawait new MediaUsageRepository(db).recordIncrementalFailuresByCollection({\n\t\tcollectionIds: [...failedCollectionIds],\n\t\terrorCode: \"MEDIA_USAGE_PROCESSING_FAILED\",\n\t});\n\treturn processed;\n}\n\nasync function runClaimedBatch(\n\tdb: Kysely<Database>,\n\tcandidates: readonly MediaUsageWorkRecord[],\n): Promise<Map<string, MediaUsageWorkProcessingResult>> {\n\treturn isPostgres(db)\n\t\t? withTransaction(db, (trx) =>\n\t\t\t\tprocessClaimedBatch(trx, new MediaUsageWorkRepository(trx), candidates),\n\t\t\t)\n\t\t: processClaimedBatch(db, new MediaUsageWorkRepository(db), candidates);\n}\n\nasync function processClaimedBatch(\n\tdb: Kysely<Database>,\n\trepo: MediaUsageWorkRepository,\n\tcandidates: readonly MediaUsageWorkRecord[],\n): Promise<Map<string, MediaUsageWorkProcessingResult>> {\n\tconst results = new Map<string, MediaUsageWorkProcessingResult>();\n\tconst locked = await repo.lockClaimedWorkBatch(candidates.map(workLease));\n\tconst owned: MediaUsageWorkRecord[] = [];\n\tfor (const candidate of candidates) {\n\t\tif (locked.has(workIdentityKey(candidate))) owned.push(candidate);\n\t\telse {\n\t\t\tresults.set(workResultKey(candidate), { outcome: \"superseded\", claimed: true });\n\t\t}\n\t}\n\tconst currentCollections = await findCurrentCollectionIdentities(db, owned);\n\tconst current: MediaUsageWorkRecord[] = [];\n\tconst obsolete: MediaUsageWorkRecord[] = [];\n\tfor (const candidate of owned) {\n\t\tif (currentCollections.has(collectionResultKey(candidate))) current.push(candidate);\n\t\telse obsolete.push(candidate);\n\t}\n\n\tconst obsoleteCompleted = await repo.completeWorkBatch(obsolete.map(workLease));\n\tfor (const candidate of obsolete) {\n\t\tresults.set(workResultKey(candidate), {\n\t\t\toutcome: obsoleteCompleted.has(workIdentityKey(candidate)) ? \"obsolete\" : \"superseded\",\n\t\t\tclaimed: true,\n\t\t});\n\t}\n\tif (current.length === 0) return results;\n\n\tconst refreshes = await refreshContentMediaUsageForWorkBatch(db, current, {\n\t\tshouldContinue: canContinueBulkWork,\n\t});\n\tconst successful: MediaUsageWorkRecord[] = [];\n\tconst unstarted: MediaUsageWorkRecord[] = [];\n\tconst failedRefreshes: Array<{\n\t\tcandidate: MediaUsageWorkRecord;\n\t\trefresh: ContentMediaUsageRefreshResult;\n\t}> = [];\n\tfor (const candidate of current) {\n\t\tconst refresh = refreshes.get(contentRefreshKey(candidate.collectionId, candidate.contentId));\n\t\tif (refresh?.success) successful.push(candidate);\n\t\telse if (!refresh) unstarted.push(candidate);\n\t\telse failedRefreshes.push({ candidate, refresh });\n\t}\n\tconst terminalFailureCollections = new Map<string, Set<string>>();\n\tconst failureGroups = new Map<\n\t\tstring,\n\t\t{\n\t\t\terrorCode: string;\n\t\t\tretryDelaySeconds: number;\n\t\t\tterminal: boolean;\n\t\t\tcandidates: MediaUsageWorkRecord[];\n\t\t}\n\t>();\n\tfor (const failure of failedRefreshes) {\n\t\tconst errorCode = processingErrorCode(failure.refresh.errorCode);\n\t\tconst terminal =\n\t\t\terrorCode === \"MEDIA_USAGE_RESOURCE_LIMIT\" ||\n\t\t\tfailure.candidate.attemptCount + 1 >= MEDIA_USAGE_WORK_PROCESSING_LIMITS.maxAttempts;\n\t\tconst delay = retryDelaySeconds(failure.candidate.attemptCount);\n\t\tconst key = `${errorCode}\\u0000${terminal ? \"terminal\" : String(delay)}`;\n\t\tconst group = failureGroups.get(key) ?? {\n\t\t\terrorCode,\n\t\t\tretryDelaySeconds: delay,\n\t\t\tterminal,\n\t\t\tcandidates: [],\n\t\t};\n\t\tgroup.candidates.push(failure.candidate);\n\t\tfailureGroups.set(key, group);\n\t}\n\tfor (const group of failureGroups.values()) {\n\t\tconst transitioned = await repo.retryClaimedWorkBatch({\n\t\t\twork: group.candidates.map(workLease),\n\t\t\terrorCode: group.errorCode,\n\t\t\tretryDelaySeconds: group.retryDelaySeconds,\n\t\t\tmaxAttempts: group.terminal ? 1 : MEDIA_USAGE_WORK_PROCESSING_LIMITS.maxAttempts,\n\t\t});\n\t\tfor (const candidate of group.candidates) {\n\t\t\tconst state = transitioned.get(workIdentityKey(candidate));\n\t\t\tif (state === \"failed\") {\n\t\t\t\tconst collections = terminalFailureCollections.get(group.errorCode) ?? new Set<string>();\n\t\t\t\tcollections.add(candidate.collectionId);\n\t\t\t\tterminalFailureCollections.set(group.errorCode, collections);\n\t\t\t}\n\t\t\tresults.set(workResultKey(candidate), {\n\t\t\t\toutcome: state ?? \"superseded\",\n\t\t\t\tclaimed: true,\n\t\t\t});\n\t\t}\n\t}\n\tfor (const [errorCode, collectionIds] of terminalFailureCollections) {\n\t\tawait new MediaUsageRepository(db).recordIncrementalFailuresByCollection({\n\t\t\tcollectionIds: [...collectionIds],\n\t\t\terrorCode,\n\t\t});\n\t}\n\tconst released = await repo.releaseClaimedWorkBatch(unstarted.map(workLease));\n\tfor (const candidate of unstarted) {\n\t\tresults.set(workResultKey(candidate), {\n\t\t\toutcome: released.has(workIdentityKey(candidate)) ? \"not_due\" : \"superseded\",\n\t\t\tclaimed: true,\n\t\t});\n\t}\n\n\tconst usage = new MediaUsageRepository(db);\n\tconst successfulByCollection = new Map<string, MediaUsageWorkRecord[]>();\n\tfor (const candidate of successful) {\n\t\tconst key = collectionResultKey(candidate);\n\t\tconst collection = successfulByCollection.get(key) ?? [];\n\t\tcollection.push(candidate);\n\t\tsuccessfulByCollection.set(key, collection);\n\t}\n\tconst readyToComplete: MediaUsageWorkRecord[] = [];\n\tconst deferredCompletion: MediaUsageWorkRecord[] = [];\n\tconst lostFinalization: MediaUsageWorkRecord[] = [];\n\tlet pendingFinalizationQueries = 2;\n\tfor (const collection of successfulByCollection.values()) {\n\t\tconst first = collection[0];\n\t\tif (!first) continue;\n\t\tconst metrics = getRequestContext()?.metrics;\n\t\tif (metrics && metrics.dbCount + pendingFinalizationQueries + 4 > 900) {\n\t\t\tdeferredCompletion.push(...collection);\n\t\t\tcontinue;\n\t\t}\n\t\tconst finalization = await usage.prepareIncrementalFinalization({\n\t\t\tcollectionId: first.collectionId,\n\t\t\tcollectionSlug: first.collectionSlug,\n\t\t});\n\t\tif (finalization.outcome !== \"lost\") {\n\t\t\treadyToComplete.push(...collection);\n\t\t\tpendingFinalizationQueries += 2;\n\t\t\tcontinue;\n\t\t}\n\t\tlostFinalization.push(...collection);\n\t\tpendingFinalizationQueries += 2;\n\t}\n\tconst lostTransitions = await repo.retryClaimedWorkBatch({\n\t\twork: lostFinalization.map(workLease),\n\t\terrorCode: \"MEDIA_USAGE_GENERATION_CONFLICT\",\n\t\tretryDelaySeconds: MEDIA_USAGE_WORK_PROCESSING_LIMITS.retryBaseSeconds,\n\t\tmaxAttempts: MEDIA_USAGE_WORK_PROCESSING_LIMITS.maxAttempts,\n\t});\n\tconst lostFailedCollections = new Set<string>();\n\tfor (const candidate of lostFinalization) {\n\t\tconst state = lostTransitions.get(workIdentityKey(candidate));\n\t\tif (state === \"failed\") lostFailedCollections.add(candidate.collectionId);\n\t\tresults.set(workResultKey(candidate), {\n\t\t\toutcome: state ?? \"superseded\",\n\t\t\tclaimed: true,\n\t\t});\n\t}\n\tawait usage.recordIncrementalFailuresByCollection({\n\t\tcollectionIds: [...lostFailedCollections],\n\t\terrorCode: \"MEDIA_USAGE_GENERATION_CONFLICT\",\n\t});\n\tconst deferred = await repo.releaseClaimedWorkBatch(deferredCompletion.map(workLease));\n\tfor (const candidate of deferredCompletion) {\n\t\tresults.set(workResultKey(candidate), {\n\t\t\toutcome: deferred.has(workIdentityKey(candidate)) ? \"not_due\" : \"superseded\",\n\t\t\tclaimed: true,\n\t\t});\n\t}\n\tconst completed = await repo.completeWorkBatch(readyToComplete.map(workLease));\n\tconst completedCollections = new Map<string, MediaUsageWorkRecord>();\n\tfor (const candidate of readyToComplete) {\n\t\tconst didComplete = completed.has(workIdentityKey(candidate));\n\t\tresults.set(workResultKey(candidate), {\n\t\t\toutcome: didComplete ? \"completed\" : \"superseded\",\n\t\t\tclaimed: true,\n\t\t});\n\t\tif (didComplete) completedCollections.set(collectionResultKey(candidate), candidate);\n\t}\n\tfor (const collection of completedCollections.values()) {\n\t\tawait usage.recordIncrementalSuccess({\n\t\t\tcollectionId: collection.collectionId,\n\t\t\tcollectionSlug: collection.collectionSlug,\n\t\t});\n\t}\n\treturn results;\n}\n\nasync function findCurrentCollectionIdentities(\n\tdb: Kysely<Database>,\n\tcandidates: readonly MediaUsageWorkRecord[],\n): Promise<Set<string>> {\n\tconst identities = new Map(\n\t\tcandidates.map((candidate) => [collectionResultKey(candidate), candidate] as const),\n\t);\n\tconst current = new Set<string>();\n\tfor (const batch of chunkCollectionIds(\n\t\tArray.from(identities.values(), (item) => item.collectionId),\n\t)) {\n\t\tconst rows = await db\n\t\t\t.selectFrom(\"_emdash_collections\")\n\t\t\t.select([\"id\", \"slug\"])\n\t\t\t.where(\"id\", \"in\", batch)\n\t\t\t.execute();\n\t\tfor (const row of rows) current.add(`${row.id}\\u0000${row.slug}`);\n\t}\n\treturn current;\n}\n\nfunction workLease(work: MediaUsageWorkRecord) {\n\tif (!work.leaseToken) throw new Error(\"Claimed media usage work requires a lease token\");\n\treturn {\n\t\tcollectionId: work.collectionId,\n\t\tcontentId: work.contentId,\n\t\tworkVersion: work.workVersion,\n\t\tleaseToken: work.leaseToken,\n\t};\n}\n\nfunction workIdentityKey(work: MediaUsageWorkRecord): string {\n\treturn `${work.collectionId}\\u0000${work.contentId}\\u0000${String(work.workVersion)}`;\n}\n\nfunction workResultKey(work: MediaUsageWorkRecord): string {\n\treturn workIdentityKey(work);\n}\n\nfunction collectionResultKey(work: Pick<MediaUsageWorkRecord, \"collectionId\" | \"collectionSlug\">) {\n\treturn `${work.collectionId}\\u0000${work.collectionSlug}`;\n}\n\nfunction chunkCollectionIds(ids: readonly string[]): string[][] {\n\tconst unique = [...new Set(ids)];\n\tconst batches: string[][] = [];\n\tfor (let index = 0; index < unique.length; index += 50) {\n\t\tbatches.push(unique.slice(index, index + 50));\n\t}\n\treturn batches;\n}\n\nfunction canContinueBulkWork(): boolean {\n\tconst metrics = getRequestContext()?.metrics;\n\treturn !metrics || metrics.dbCount + 150 <= 900;\n}\n\nasync function isIncrementalCaptureActive(db: Kysely<Database>): Promise<boolean> {\n\tconst row = await db\n\t\t.selectFrom(\"_emdash_media_usage_activation\")\n\t\t.select(\"state\")\n\t\t.where(\"task_key\", \"=\", \"incremental_capture\")\n\t\t.executeTakeFirst();\n\treturn row?.state === \"active\";\n}\n\nfunction retryDelaySeconds(attemptCount: number): number {\n\tconst exponential = Math.min(\n\t\tMEDIA_USAGE_WORK_PROCESSING_LIMITS.retryMaxSeconds,\n\t\tMEDIA_USAGE_WORK_PROCESSING_LIMITS.retryBaseSeconds * 2 ** attemptCount,\n\t);\n\tconst jitter = Math.floor(\n\t\texponential * MEDIA_USAGE_WORK_PROCESSING_LIMITS.retryJitterRatio * Math.random(),\n\t);\n\treturn Math.min(MEDIA_USAGE_WORK_PROCESSING_LIMITS.retryMaxSeconds, exponential + jitter);\n}\n\nfunction processingErrorCode(errorCode: ContentMediaUsageRefreshErrorCode | undefined): string {\n\tif (\n\t\terrorCode === \"DRAFT_REVISION_NOT_FOUND\" ||\n\t\terrorCode === \"DRAFT_REVISION_MISMATCH\" ||\n\t\terrorCode === \"DRAFT_REVISION_INVALID\"\n\t) {\n\t\treturn \"MEDIA_USAGE_SNAPSHOT_FAILED\";\n\t}\n\tif (errorCode === \"CONTENT_USAGE_GENERATION_CONFLICT\") {\n\t\treturn \"MEDIA_USAGE_GENERATION_CONFLICT\";\n\t}\n\tif (errorCode === \"CONTENT_USAGE_RESOURCE_LIMIT\") return \"MEDIA_USAGE_RESOURCE_LIMIT\";\n\treturn \"MEDIA_USAGE_PROCESSING_FAILED\";\n}\n","import type { Kysely } from \"kysely\";\n\nimport type { Database } from \"../../database/types.js\";\nimport { getRequestContext } from \"../../request-context.js\";\nimport {\n\tcontinueMediaUsageActivation,\n\tMEDIA_USAGE_ACTIVATION_RUNTIME_GENERATION,\n\tMediaUsageActivationVersionMismatchError,\n} from \"./activation.js\";\nimport { processDueMediaUsageCollectionDeletions } from \"./collection-deletion-processor.js\";\nimport { processDueMediaUsageReconciliationDetailed } from \"./reconciliation-processor.js\";\nimport { MediaUsageReconciliationRepository } from \"./reconciliation.js\";\nimport { processDueMediaUsageWork } from \"./work-processor.js\";\n\ntype MediaUsageMaintenanceTaskClass = \"entry_work\" | \"collection_deletion\" | \"reconciliation\";\n\nexport type MediaUsageMaintenanceContinuation =\n\t| { kind: \"none\" }\n\t| { kind: \"immediate\" }\n\t| { kind: \"delayed\"; delaySeconds: 30 };\n\nexport interface MediaUsageMaintenanceStepResult {\n\tstate: \"inactive\" | \"idle\" | \"blocked\" | \"progress\";\n\tcontinuation: MediaUsageMaintenanceContinuation;\n}\n\nexport const MEDIA_USAGE_MAINTENANCE_LIMITS = Object.freeze({\n\teventQueryCeiling: 900,\n\tmaxStepQueries: 150,\n});\n\nconst TASK_CLASSES: readonly MediaUsageMaintenanceTaskClass[] = [\n\t\"collection_deletion\",\n\t\"entry_work\",\n\t\"reconciliation\",\n];\n\nexport async function runMediaUsageMaintenanceStep(\n\tdb: Kysely<Database>,\n): Promise<MediaUsageMaintenanceStepResult> {\n\tconst activation = await db\n\t\t.selectFrom(\"_emdash_media_usage_activation\")\n\t\t.select([\"state\", \"runtime_generation\"])\n\t\t.where(\"task_key\", \"=\", \"incremental_capture\")\n\t\t.executeTakeFirst();\n\tif (\n\t\tactivation?.state !== \"active\" ||\n\t\tactivation.runtime_generation !== MEDIA_USAGE_ACTIVATION_RUNTIME_GENERATION\n\t) {\n\t\treturn runActivationStep(db);\n\t}\n\tlet blocked = false;\n\tlet blockedReconciliation = false;\n\tlet madeProgress = false;\n\n\tfor (const taskClass of TASK_CLASSES) {\n\t\tconst metrics = getRequestContext()?.metrics;\n\t\tif (metrics && !canStartMediaUsageMaintenanceStep(metrics)) {\n\t\t\treturn madeProgress\n\t\t\t\t? {\n\t\t\t\t\t\tstate: \"progress\",\n\t\t\t\t\t\tcontinuation: { kind: \"immediate\" },\n\t\t\t\t\t}\n\t\t\t\t: {\n\t\t\t\t\t\tstate: \"blocked\",\n\t\t\t\t\t\tcontinuation: { kind: \"immediate\" },\n\t\t\t\t\t};\n\t\t}\n\t\tconst outcome = await runTaskClass(db, taskClass);\n\t\tif (outcome === \"inactive\") return inactiveResult();\n\t\tif (outcome === \"progress\") madeProgress = true;\n\t\tif (outcome === \"blocked\") {\n\t\t\tblocked = true;\n\t\t\tif (taskClass === \"reconciliation\") blockedReconciliation = true;\n\t\t}\n\t}\n\tif (madeProgress) {\n\t\treturn {\n\t\t\tstate: \"progress\",\n\t\t\tcontinuation: { kind: \"immediate\" },\n\t\t};\n\t}\n\n\tif (\n\t\tblockedReconciliation &&\n\t\t(await new MediaUsageReconciliationRepository(db).wakeDrainedBarrierCandidate())\n\t) {\n\t\treturn {\n\t\t\tstate: \"progress\",\n\t\t\tcontinuation: { kind: \"immediate\" },\n\t\t};\n\t}\n\n\tif (blocked) {\n\t\treturn {\n\t\t\tstate: \"blocked\",\n\t\t\tcontinuation: { kind: \"delayed\", delaySeconds: 30 },\n\t\t};\n\t}\n\n\treturn {\n\t\tstate: \"idle\",\n\t\tcontinuation: { kind: \"none\" },\n\t};\n}\n\nasync function runActivationStep(db: Kysely<Database>): Promise<MediaUsageMaintenanceStepResult> {\n\ttry {\n\t\tconst result = await continueMediaUsageActivation(db);\n\t\tif (result.outcome === \"activating\" || result.outcome === \"active\") {\n\t\t\treturn {\n\t\t\t\tstate: \"progress\",\n\t\t\t\tcontinuation: { kind: \"immediate\" },\n\t\t\t};\n\t\t}\n\t\tif (result.outcome === \"lease_active\" || result.outcome === \"conflict\") {\n\t\t\treturn {\n\t\t\t\tstate: \"blocked\",\n\t\t\t\tcontinuation: { kind: \"delayed\", delaySeconds: 30 },\n\t\t\t};\n\t\t}\n\t\treturn inactiveResult();\n\t} catch (error) {\n\t\tif (error instanceof MediaUsageActivationVersionMismatchError) return inactiveResult();\n\t\tthrow error;\n\t}\n}\n\nasync function runTaskClass(\n\tdb: Kysely<Database>,\n\ttaskClass: MediaUsageMaintenanceTaskClass,\n): Promise<\"inactive\" | \"idle\" | \"blocked\" | \"progress\"> {\n\tif (taskClass === \"entry_work\") {\n\t\tconst result = await processDueMediaUsageWork(db, {\n\t\t\tactivationKnownActive: true,\n\t\t});\n\t\tif (result.claimedCount > 0) return \"progress\";\n\t\treturn result.candidateCount > 0 ? \"blocked\" : \"idle\";\n\t}\n\tif (taskClass === \"collection_deletion\") {\n\t\tconst result = await processDueMediaUsageCollectionDeletions(db);\n\t\tif (result.claimedCount > 0) return \"progress\";\n\t\treturn result.candidateCount > 0 ? \"blocked\" : \"idle\";\n\t}\n\n\tconst result = await processDueMediaUsageReconciliationDetailed(db, {\n\t\tactivationKnownActive: true,\n\t});\n\tif (result.outcome === \"inactive\") return \"inactive\";\n\tif (result.consumedUnit) return \"progress\";\n\treturn result.outcome === \"claim_lost\" || result.hasDeferredCandidate ? \"blocked\" : \"idle\";\n}\n\nfunction inactiveResult(): MediaUsageMaintenanceStepResult {\n\treturn {\n\t\tstate: \"inactive\",\n\t\tcontinuation: { kind: \"none\" },\n\t};\n}\n\nfunction canStartMediaUsageMaintenanceStep(metrics: { dbCount: number }): boolean {\n\treturn (\n\t\tmetrics.dbCount + MEDIA_USAGE_MAINTENANCE_LIMITS.maxStepQueries <=\n\t\tMEDIA_USAGE_MAINTENANCE_LIMITS.eventQueryCeiling\n\t);\n}\n","import type { Kysely } from \"kysely\";\n\nimport {\n\tMediaUsageRepository,\n\ttype MediaUsageCollectionIndexStatusScope,\n\ttype MediaUsageEntryGroup,\n} from \"../../database/repositories/media-usage.js\";\nimport { MediaRepository } from \"../../database/repositories/media.js\";\nimport { InvalidCursorError } from \"../../database/repositories/types.js\";\nimport type { Database } from \"../../database/types.js\";\nimport {\n\tgetMediaUsageActivationStatus,\n\tMediaUsageActivationVersionMismatchError,\n} from \"../../media/usage/activation.js\";\nimport {\n\tCONTENT_MEDIA_USAGE_ADAPTER_ID,\n\tCONTENT_MEDIA_USAGE_COLLECTION_SCOPE,\n} from \"../../media/usage/content-refresh.js\";\nimport {\n\trepairContentMediaUsageAll,\n\trepairContentMediaUsageCollection,\n\ttype ContentMediaUsageRepairAllResult,\n\ttype ContentMediaUsageRepairCollectionResult,\n} from \"../../media/usage/content-repair.js\";\nimport { CONTENT_SOURCE_SCHEMA_VERSION } from \"../../media/usage/content-snapshots.js\";\nimport {\n\trunMediaUsageMaintenanceStep,\n\ttype MediaUsageMaintenanceContinuation,\n} from \"../../media/usage/maintenance-engine.js\";\nimport { ErrorCode } from \"../errors.js\";\nimport type {\n\tMediaUsageCoverage,\n\tMediaUsageCoverageStatus,\n\tMediaUsageDetailsResponse,\n\tMediaUsageEntryDetail,\n\tMediaUsageOccurrenceDetail,\n\tMediaUsageProgress,\n\tMediaUsageProgressAdvanceResponse,\n\tMediaUsageRepairRequest,\n\tMediaUsageRepairResponse,\n\tMediaUsageSummary,\n} from \"../schemas/media-usage.js\";\nimport type { ApiResult } from \"../types.js\";\n\nexport type {\n\tMediaUsageCoverage,\n\tMediaUsageCoverageStatus,\n\tMediaUsageDetailsResponse,\n\tMediaUsageEntryDetail,\n\tMediaUsageOccurrenceDetail,\n\tMediaUsageProgress,\n\tMediaUsageProgressAdvanceResponse,\n\tMediaUsageSourceDetail,\n\tMediaUsageRepairRequest,\n\tMediaUsageRepairResponse,\n\tMediaUsageSummary,\n} from \"../schemas/media-usage.js\";\n\ntype ContentMediaUsageRepairResult =\n\t| ContentMediaUsageRepairCollectionResult\n\t| ContentMediaUsageRepairAllResult;\n\nexport async function handleMediaUsageProgress(\n\tdb: Kysely<Database>,\n): Promise<ApiResult<MediaUsageProgress>> {\n\ttry {\n\t\tconst progress = await new MediaUsageRepository(db).findCollectionProgress();\n\t\tif (!progress) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: ErrorCode.MEDIA_USAGE_PROGRESS_NOT_ACTIVE,\n\t\t\t\t\tmessage: \"Media Usage is not active\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\treturn { success: true, data: progress };\n\t} catch (error) {\n\t\tif (error instanceof MediaUsageActivationVersionMismatchError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: ErrorCode.MEDIA_USAGE_ACTIVATION_VERSION_MISMATCH,\n\t\t\t\t\tmessage: \"Media Usage activation version does not match this runtime\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tconsole.error(\"[media-usage] progress read failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: ErrorCode.MEDIA_USAGE_PROGRESS_READ_ERROR,\n\t\t\t\tmessage: \"Failed to read media usage progress\",\n\t\t\t},\n\t\t};\n\t}\n}\n\nexport async function handleMediaUsageProgressAdvance(\n\tdb: Kysely<Database>,\n): Promise<ApiResult<MediaUsageProgressAdvanceResponse>> {\n\ttry {\n\t\tconst step = await runMediaUsageMaintenanceStep(db);\n\t\tconst activation = await getMediaUsageActivationStatus(db);\n\t\tif (activation.state === \"expanded\") {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: ErrorCode.MEDIA_USAGE_PROGRESS_NOT_ACTIVE,\n\t\t\t\t\tmessage: \"Media Usage activation has not started\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst progress =\n\t\t\tactivation.state === \"active\"\n\t\t\t\t? await new MediaUsageRepository(db).findCollectionProgress()\n\t\t\t\t: null;\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\tactivation,\n\t\t\t\tprogress,\n\t\t\t\tnextRequestInMs: continuationDelayMs(step.continuation, progress),\n\t\t\t},\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof MediaUsageActivationVersionMismatchError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: ErrorCode.MEDIA_USAGE_ACTIVATION_VERSION_MISMATCH,\n\t\t\t\t\tmessage: \"Media Usage activation version does not match this runtime\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tconsole.error(\"[media-usage] progress advance failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: ErrorCode.MEDIA_USAGE_PROGRESS_ADVANCE_ERROR,\n\t\t\t\tmessage: \"Failed to advance media usage progress\",\n\t\t\t},\n\t\t};\n\t}\n}\n\nfunction continuationDelayMs(\n\tcontinuation: MediaUsageMaintenanceContinuation,\n\tprogress: MediaUsageProgress | null,\n): 0 | 30_000 | null {\n\tif (progress?.status === \"needs_attention\") return null;\n\tif (continuation.kind === \"immediate\") return 0;\n\tif (continuation.kind === \"delayed\") return 30_000;\n\tif (progress?.status === \"indexing\") return 0;\n\treturn null;\n}\n\nexport function aggregateMediaUsageCoverageStatus(\n\tscopes: readonly MediaUsageCollectionIndexStatusScope[],\n): MediaUsageCoverageStatus {\n\tconst statuses = scopes.map(normalizeMediaUsageCoverageStatus);\n\tif (statuses.every((status) => status === \"complete\")) {\n\t\treturn \"complete\";\n\t}\n\tif (statuses.includes(\"unknown\")) return \"unknown\";\n\tif (statuses.includes(\"running\")) return \"running\";\n\tif (statuses.includes(\"stale\")) return \"stale\";\n\tif (statuses.includes(\"partial\")) return \"partial\";\n\tif (statuses.every((status) => status === \"never\")) return \"never\";\n\tif (statuses.every((status) => status === \"failed\")) return \"failed\";\n\treturn \"partial\";\n}\n\nexport async function handleMediaUsageSummaries(\n\tdb: Kysely<Database>,\n\tmediaIds: readonly string[],\n\toptions: { includeCount: boolean },\n): Promise<ApiResult<Record<string, MediaUsageSummary>>> {\n\tif (mediaIds.length === 0) return { success: true, data: {} };\n\n\ttry {\n\t\tconst repository = new MediaUsageRepository(db);\n\t\tconst coverage = await loadMediaUsageCoverage(repository);\n\t\tconst counts =\n\t\t\toptions.includeCount && coverage.status === \"complete\"\n\t\t\t\t? await repository.findActiveEntryCountsByMediaIds(mediaIds)\n\t\t\t\t: null;\n\t\tconst summaries: Record<string, MediaUsageSummary> = {};\n\n\t\tfor (const mediaId of new Set(mediaIds)) {\n\t\t\tsummaries[mediaId] = {\n\t\t\t\tcount: counts ? (counts.get(mediaId) ?? 0) : null,\n\t\t\t\tcoverage,\n\t\t\t};\n\t\t}\n\n\t\treturn { success: true, data: summaries };\n\t} catch (error) {\n\t\tconsole.error(\"[media-usage] summary read failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: ErrorCode.MEDIA_USAGE_READ_ERROR,\n\t\t\t\tmessage: \"Failed to read media usage\",\n\t\t\t},\n\t\t};\n\t}\n}\n\nexport async function handleMediaUsageDetails(\n\tdb: Kysely<Database>,\n\tmediaId: string,\n\toptions: { cursor?: string; limit?: number },\n): Promise<ApiResult<MediaUsageDetailsResponse>> {\n\ttry {\n\t\tconst media = await new MediaRepository(db).findById(mediaId);\n\t\tif (!media) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: ErrorCode.NOT_FOUND,\n\t\t\t\t\tmessage: `Media item not found: ${mediaId}`,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst repository = new MediaUsageRepository(db);\n\t\tconst coverage = await loadMediaUsageCoverage(repository);\n\t\tconst page = await repository.findCurrentEntryUsagePageByMediaId(mediaId, options);\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\titems: page.items.map(toMediaUsageEntryDetail),\n\t\t\t\t...(page.nextCursor ? { nextCursor: page.nextCursor } : {}),\n\t\t\t\tcoverage,\n\t\t\t},\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof InvalidCursorError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: ErrorCode.INVALID_CURSOR, message: error.message },\n\t\t\t};\n\t\t}\n\t\tconsole.error(\"[media-usage] detail read failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: ErrorCode.MEDIA_USAGE_READ_ERROR,\n\t\t\t\tmessage: \"Failed to read media usage\",\n\t\t\t},\n\t\t};\n\t}\n}\n\nexport async function handleMediaUsageRepair(\n\tdb: Kysely<Database>,\n\tinput: MediaUsageRepairRequest,\n): Promise<ApiResult<MediaUsageRepairResponse>> {\n\ttry {\n\t\tlet result: ContentMediaUsageRepairResult;\n\t\tif (input.scope === \"collection\") {\n\t\t\tresult = await repairContentMediaUsageCollection(db, { collectionSlug: input.collection });\n\t\t} else if (input.scope === \"all\") {\n\t\t\tresult = await repairContentMediaUsageAll(db);\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: ErrorCode.VALIDATION_ERROR,\n\t\t\t\t\tmessage: \"Invalid media usage repair request\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn { success: true, data: toMediaUsageRepairResponse(result) };\n\t} catch (error) {\n\t\tconsole.error(\"[media-usage] repair failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: ErrorCode.MEDIA_USAGE_REPAIR_ERROR,\n\t\t\t\tmessage: \"Failed to repair media usage\",\n\t\t\t},\n\t\t};\n\t}\n}\n\nexport function toMediaUsageRepairResponse(\n\tresult: ContentMediaUsageRepairResult,\n): MediaUsageRepairResponse {\n\tconst collections = \"collections\" in result ? result.collections : [result];\n\n\treturn {\n\t\tstatus: result.status,\n\t\tindexedSourceCount: result.indexedSourceCount,\n\t\tfailedSourceCount: result.failedSourceCount,\n\t\tskippedSourceCount: result.skippedSourceCount,\n\t\tdeletedSourceCount: result.deletedSourceCount,\n\t\tcollections: collections.map(toMediaUsageRepairCollectionSummary),\n\t};\n}\n\nfunction toMediaUsageRepairCollectionSummary(result: ContentMediaUsageRepairCollectionResult) {\n\treturn {\n\t\tcollection: result.scope.scopeKey,\n\t\tstatus: result.status,\n\t\tindexedSourceCount: result.indexedSourceCount,\n\t\tfailedSourceCount: result.failedSourceCount,\n\t\tskippedSourceCount: result.skippedSourceCount,\n\t\tdeletedSourceCount: result.deletedSourceCount,\n\t\tlastErrorCode: result.lastErrorCode,\n\t\tstartedAt: result.startedAt,\n\t\tcompletedAt: result.completedAt,\n\t};\n}\n\nfunction normalizeMediaUsageCoverageStatus(\n\tscope: MediaUsageCollectionIndexStatusScope,\n): MediaUsageCoverageStatus {\n\tif (scope.status === null) return \"never\";\n\tif (scope.status === \"complete\") {\n\t\tif (scope.reconciliationRequired) return \"stale\";\n\t\treturn scope.schemaVersion === CONTENT_SOURCE_SCHEMA_VERSION ? \"complete\" : \"stale\";\n\t}\n\tif (\n\t\tscope.status === \"never\" ||\n\t\tscope.status === \"running\" ||\n\t\tscope.status === \"partial\" ||\n\t\tscope.status === \"failed\" ||\n\t\tscope.status === \"stale\"\n\t) {\n\t\treturn scope.status;\n\t}\n\treturn \"unknown\";\n}\n\nasync function loadMediaUsageCoverage(\n\trepository: MediaUsageRepository,\n): Promise<MediaUsageCoverage> {\n\tconst scopes = await repository.findCollectionIndexStatusScopes({\n\t\tadapterId: CONTENT_MEDIA_USAGE_ADAPTER_ID,\n\t\tscopeType: CONTENT_MEDIA_USAGE_COLLECTION_SCOPE,\n\t});\n\treturn {\n\t\tscope: \"all_content_collections\",\n\t\tstatus: aggregateMediaUsageCoverageStatus(scopes),\n\t};\n}\n\nfunction toMediaUsageEntryDetail(group: MediaUsageEntryGroup): MediaUsageEntryDetail {\n\tconst preferred =\n\t\tgroup.sources.find(({ source }) => source.sourceVariant === \"draft_overlay\") ??\n\t\tgroup.sources.find(({ source }) => source.sourceVariant === \"columns\");\n\tif (!preferred) {\n\t\tthrow new Error(\"Media usage entry has no supported source\");\n\t}\n\n\treturn {\n\t\tcollection: group.collectionSlug,\n\t\tcontentId: group.contentId,\n\t\ttitle: preferred.source.contentTitle,\n\t\tslug: preferred.source.contentSlug,\n\t\tlocale: preferred.source.locale,\n\t\tstatus: preferred.source.contentStatus,\n\t\tscheduledAt: preferred.source.contentScheduledAt,\n\t\tdeletedAt: group.contentDeletedAt,\n\t\tsources: group.sources.flatMap(({ source, occurrences }) => {\n\t\t\tif (source.sourceVariant !== \"columns\" && source.sourceVariant !== \"draft_overlay\") {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tvariant: source.sourceVariant,\n\t\t\t\t\toccurrences: occurrences.map((occurrence) => ({\n\t\t\t\t\t\tfieldSlug: occurrence.fieldSlug,\n\t\t\t\t\t\tfieldPath: occurrence.fieldPath,\n\t\t\t\t\t\toccurrenceIndex: occurrence.occurrenceIndex,\n\t\t\t\t\t\treferenceType: normalizeMediaUsageReferenceType(occurrence.referenceType),\n\t\t\t\t\t})),\n\t\t\t\t},\n\t\t\t];\n\t\t}),\n\t};\n}\n\nfunction normalizeMediaUsageReferenceType(\n\treferenceType: string,\n): MediaUsageOccurrenceDetail[\"referenceType\"] {\n\tif (\n\t\treferenceType === \"image_field\" ||\n\t\treferenceType === \"file_field\" ||\n\t\treferenceType === \"portable_text_image\"\n\t) {\n\t\treturn referenceType;\n\t}\n\treturn \"unknown\";\n}\n"],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ import { n as MediaUsageActivationVersionMismatchError, r as activateMediaUsageCapture, s as getMediaUsageActivationStatus } from "./activation-K0kGBWuJ.mjs";
2
+ import { t as ErrorCode } from "./errors-n2j49uNf.mjs";
3
+
4
+ //#region src/api/handlers/media-usage-activation.ts
5
+ async function handleMediaUsageActivationStatus(db) {
6
+ try {
7
+ return {
8
+ success: true,
9
+ data: await getMediaUsageActivationStatus(db)
10
+ };
11
+ } catch (error) {
12
+ if (error instanceof MediaUsageActivationVersionMismatchError) return {
13
+ success: false,
14
+ error: {
15
+ code: ErrorCode.MEDIA_USAGE_ACTIVATION_VERSION_MISMATCH,
16
+ message: "Media usage activation version is incompatible with this runtime"
17
+ }
18
+ };
19
+ console.error("[media-usage:activation] status read failed:", error);
20
+ return {
21
+ success: false,
22
+ error: {
23
+ code: ErrorCode.MEDIA_USAGE_ACTIVATION_READ_ERROR,
24
+ message: "Failed to read media usage activation status"
25
+ }
26
+ };
27
+ }
28
+ }
29
+ async function handleMediaUsageActivationAdvance(db, input) {
30
+ try {
31
+ const result = await activateMediaUsageCapture(db, { writersDrained: input.writersDrained });
32
+ if (result.outcome === "lease_active") return {
33
+ success: false,
34
+ error: {
35
+ code: ErrorCode.MEDIA_USAGE_ACTIVATION_BUSY,
36
+ message: "Media usage activation is already in progress",
37
+ details: { leaseExpiresAt: result.leaseExpiresAt }
38
+ }
39
+ };
40
+ if (result.outcome === "conflict") return {
41
+ success: false,
42
+ error: {
43
+ code: ErrorCode.MEDIA_USAGE_ACTIVATION_CONFLICT,
44
+ message: "Media usage activation ownership changed"
45
+ }
46
+ };
47
+ const activation = await getMediaUsageActivationStatus(db);
48
+ if (activation.state === "expanded") throw new Error("Media usage activation did not advance");
49
+ return {
50
+ success: true,
51
+ data: {
52
+ outcome: activation.state,
53
+ processedCollections: result.processedCollections,
54
+ activation
55
+ }
56
+ };
57
+ } catch (error) {
58
+ if (error instanceof MediaUsageActivationVersionMismatchError) return {
59
+ success: false,
60
+ error: {
61
+ code: ErrorCode.MEDIA_USAGE_ACTIVATION_VERSION_MISMATCH,
62
+ message: "Media usage activation version is incompatible with this runtime"
63
+ }
64
+ };
65
+ console.error("[media-usage:activation] advance failed:", error);
66
+ return {
67
+ success: false,
68
+ error: {
69
+ code: ErrorCode.MEDIA_USAGE_ACTIVATION_ADVANCE_ERROR,
70
+ message: "Failed to advance media usage activation"
71
+ }
72
+ };
73
+ }
74
+ }
75
+
76
+ //#endregion
77
+ export { handleMediaUsageActivationStatus as n, handleMediaUsageActivationAdvance as t };
78
+ //# sourceMappingURL=media-usage-activation-Dx0kPV6b.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-usage-activation-Dx0kPV6b.mjs","names":[],"sources":["../src/api/handlers/media-usage-activation.ts"],"sourcesContent":["import type { Kysely } from \"kysely\";\n\nimport type { Database } from \"../../database/types.js\";\nimport {\n\tactivateMediaUsageCapture,\n\tgetMediaUsageActivationStatus,\n\tMediaUsageActivationVersionMismatchError,\n} from \"../../media/usage/activation.js\";\nimport { ErrorCode } from \"../errors.js\";\nimport type {\n\tMediaUsageActivationAdvanceRequest,\n\tMediaUsageActivationAdvanceResponse,\n\tMediaUsageActivationStatus,\n} from \"../schemas/media-usage.js\";\nimport type { ApiResult } from \"../types.js\";\n\nexport async function handleMediaUsageActivationStatus(\n\tdb: Kysely<Database>,\n): Promise<ApiResult<MediaUsageActivationStatus>> {\n\ttry {\n\t\treturn { success: true, data: await getMediaUsageActivationStatus(db) };\n\t} catch (error) {\n\t\tif (error instanceof MediaUsageActivationVersionMismatchError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: ErrorCode.MEDIA_USAGE_ACTIVATION_VERSION_MISMATCH,\n\t\t\t\t\tmessage: \"Media usage activation version is incompatible with this runtime\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tconsole.error(\"[media-usage:activation] status read failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: ErrorCode.MEDIA_USAGE_ACTIVATION_READ_ERROR,\n\t\t\t\tmessage: \"Failed to read media usage activation status\",\n\t\t\t},\n\t\t};\n\t}\n}\n\nexport async function handleMediaUsageActivationAdvance(\n\tdb: Kysely<Database>,\n\tinput: MediaUsageActivationAdvanceRequest,\n): Promise<ApiResult<MediaUsageActivationAdvanceResponse>> {\n\ttry {\n\t\tconst result = await activateMediaUsageCapture(db, {\n\t\t\twritersDrained: input.writersDrained,\n\t\t});\n\t\tif (result.outcome === \"lease_active\") {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: ErrorCode.MEDIA_USAGE_ACTIVATION_BUSY,\n\t\t\t\t\tmessage: \"Media usage activation is already in progress\",\n\t\t\t\t\tdetails: { leaseExpiresAt: result.leaseExpiresAt },\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tif (result.outcome === \"conflict\") {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: ErrorCode.MEDIA_USAGE_ACTIVATION_CONFLICT,\n\t\t\t\t\tmessage: \"Media usage activation ownership changed\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst activation = await getMediaUsageActivationStatus(db);\n\t\tif (activation.state === \"expanded\") {\n\t\t\tthrow new Error(\"Media usage activation did not advance\");\n\t\t}\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\toutcome: activation.state,\n\t\t\t\tprocessedCollections: result.processedCollections,\n\t\t\t\tactivation,\n\t\t\t},\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof MediaUsageActivationVersionMismatchError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: ErrorCode.MEDIA_USAGE_ACTIVATION_VERSION_MISMATCH,\n\t\t\t\t\tmessage: \"Media usage activation version is incompatible with this runtime\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tconsole.error(\"[media-usage:activation] advance failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: ErrorCode.MEDIA_USAGE_ACTIVATION_ADVANCE_ERROR,\n\t\t\t\tmessage: \"Failed to advance media usage activation\",\n\t\t\t},\n\t\t};\n\t}\n}\n"],"mappings":";;;;AAgBA,eAAsB,iCACrB,IACiD;AACjD,KAAI;AACH,SAAO;GAAE,SAAS;GAAM,MAAM,MAAM,8BAA8B,GAAG;GAAE;UAC/D,OAAO;AACf,MAAI,iBAAiB,yCACpB,QAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD;AAEF,UAAQ,MAAM,gDAAgD,MAAM;AACpE,SAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD;;;AAIH,eAAsB,kCACrB,IACA,OAC0D;AAC1D,KAAI;EACH,MAAM,SAAS,MAAM,0BAA0B,IAAI,EAClD,gBAAgB,MAAM,gBACtB,CAAC;AACF,MAAI,OAAO,YAAY,eACtB,QAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT,SAAS,EAAE,gBAAgB,OAAO,gBAAgB;IAClD;GACD;AAEF,MAAI,OAAO,YAAY,WACtB,QAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD;EAGF,MAAM,aAAa,MAAM,8BAA8B,GAAG;AAC1D,MAAI,WAAW,UAAU,WACxB,OAAM,IAAI,MAAM,yCAAyC;AAE1D,SAAO;GACN,SAAS;GACT,MAAM;IACL,SAAS,WAAW;IACpB,sBAAsB,OAAO;IAC7B;IACA;GACD;UACO,OAAO;AACf,MAAI,iBAAiB,yCACpB,QAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD;AAEF,UAAQ,MAAM,4CAA4C,MAAM;AAChE,SAAO;GACN,SAAS;GACT,OAAO;IACN,MAAM,UAAU;IAChB,SAAS;IACT;GACD"}