ghost 6.63.0 → 6.64.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 (624) hide show
  1. package/bin/lib/duplicate-deps.js +204 -0
  2. package/bin/validate-adapters.js +50 -6
  3. package/components/tryghost-adapter-base-scheduling-0.2.3.tgz +0 -0
  4. package/components/tryghost-adapter-base-sso-0.1.3.tgz +0 -0
  5. package/components/tryghost-admin-api-schema-0.0.0.tgz +0 -0
  6. package/components/tryghost-api-framework-0.0.0.tgz +0 -0
  7. package/components/tryghost-i18n-0.0.0.tgz +0 -0
  8. package/components/{tryghost-kg-default-cards-10.3.5.tgz → tryghost-kg-default-cards-10.3.6.tgz} +0 -0
  9. package/components/tryghost-kg-default-nodes-2.2.1.tgz +0 -0
  10. package/components/tryghost-kg-html-to-lexical-1.4.0.tgz +0 -0
  11. package/components/tryghost-kg-lexical-html-renderer-1.5.1.tgz +0 -0
  12. package/components/tryghost-limit-service-0.0.0.tgz +0 -0
  13. package/components/tryghost-metafield-types-0.0.0.tgz +0 -0
  14. package/content/themes/source/assets/built/screen.css +1 -1
  15. package/content/themes/source/assets/css/screen.css +1 -1
  16. package/content/themes/source/package.json +7 -7
  17. package/core/boot.js +10 -4
  18. package/core/built/admin/assets/Combination-DWfJPcz9.js +41 -0
  19. package/core/built/admin/assets/{PolarAngleAxis-pkMyqz8g.js → PolarAngleAxis-a81ieQUO.js} +2 -2
  20. package/core/built/admin/assets/RadialBarChart-CHRBhiBN.js +1 -0
  21. package/core/built/admin/assets/_baseAssignValue-DcPokYW8.js +1 -0
  22. package/core/built/admin/assets/about-39CAfroa.js +1 -0
  23. package/core/built/admin/assets/accordion-CJmRaqK7.js +1 -0
  24. package/core/built/admin/assets/account-migration-DYf7skbb.js +1 -0
  25. package/core/built/admin/assets/action-list-Crnh-_UI.js +1 -0
  26. package/core/built/admin/assets/add-integration-modal-B12oRifD.js +1 -0
  27. package/core/built/admin/assets/add-newsletter-modal-CTvXiIqY.js +1 -0
  28. package/core/built/admin/assets/add-recommendation-modal-CJf92edY.js +1 -0
  29. package/core/built/admin/assets/analytics-PHR1Fggi.js +1 -0
  30. package/core/built/admin/assets/announcement-bar-modal-Bql0CXdp.js +1 -0
  31. package/core/built/admin/assets/api-keys-CubH-7_H.js +1 -0
  32. package/core/built/admin/assets/{api-keys-BGPzLHzA.js → api-keys-omLA6iYn.js} +1 -1
  33. package/core/built/admin/assets/{audience-ceV3XVHq.js → audience-6GXevic-.js} +1 -1
  34. package/core/built/admin/assets/automated-emails-DJQ4uNZo.js +1 -0
  35. package/core/built/admin/assets/automations-DcZSLFDU.js +1 -0
  36. package/core/built/admin/assets/automations-hDVcRPjh.js +1 -0
  37. package/core/built/admin/assets/avatar-flipboard-DiAGgshK.js +1 -0
  38. package/core/built/admin/assets/badge-qP06OT7C.js +1 -0
  39. package/core/built/admin/assets/bluesky-sharing-CJw4d4Mf.js +1 -0
  40. package/core/built/admin/assets/box-CZ_LSVSy.js +1 -0
  41. package/core/built/admin/assets/brand-icon-D3ffDYaC.js +1 -0
  42. package/core/built/admin/assets/breadcrumb-Chn1Ip_q.js +1 -0
  43. package/core/built/admin/assets/button-DvIh2Bq-.js +1 -0
  44. package/core/built/admin/assets/calendar-1QGoStFM.js +1 -0
  45. package/core/built/admin/assets/card-FHQ4D10L.js +1 -0
  46. package/core/built/admin/assets/chart-helpers-CNpA7re_.js +1 -0
  47. package/core/built/admin/assets/{chart-BrhA41Zi.js → chart-jVz9Nf9t.js} +9 -9
  48. package/core/built/admin/assets/checkbox-DKht9xMl.js +1 -0
  49. package/core/built/admin/assets/{chunk-KS7C4IRE-DCsL4i4D.js → chunk-KS7C4IRE-DhOcHQOU.js} +1 -1
  50. package/core/built/admin/assets/{chunk.254.035b85ec456ebbd7336b.js → chunk.368.22ce1b732c0b40abd3f1.js} +159 -120
  51. package/core/built/admin/assets/chunk.524.cc9be98e44890cedc8c8.js +25 -0
  52. package/core/built/admin/assets/{chunk.582.98b485f9b2802f540897.js → chunk.582.e6fe742b3217207b11a6.js} +23 -30
  53. package/core/built/admin/assets/{chunk.901.4ccc639821020230bcca.js → chunk.972.4b8c97f93d66db15e751.js} +10625 -10088
  54. package/core/built/admin/assets/clean-tracked-url-dkN05vOf.js +1 -0
  55. package/core/built/admin/assets/code-editor-view-BLQIV85-.js +1 -0
  56. package/core/built/admin/assets/code-editor-view-Cg5eJxcr.js +1 -0
  57. package/core/built/admin/assets/color-picker-DQoghc0t.js +3 -0
  58. package/core/built/admin/assets/color-picker-field-BbeK5RRs.js +1 -0
  59. package/core/built/admin/assets/combobox-weO4FBbv.js +1 -0
  60. package/core/built/admin/assets/command-DlLrCm9V.js +1 -0
  61. package/core/built/admin/assets/comments-BjTitLmP.js +1 -0
  62. package/core/built/admin/assets/components-CwL6a6As-CCRaoCeP.js +1 -0
  63. package/core/built/admin/assets/{config-kSHvwdTG.js → config-BPljH6wF.js} +1 -1
  64. package/core/built/admin/assets/confirmation-context-IyqoXVk-.js +1 -0
  65. package/core/built/admin/assets/container-DAimjOF_.js +1 -0
  66. package/core/built/admin/assets/content-api-modal-0ZjuLcQ8.js +1 -0
  67. package/core/built/admin/assets/context-menu-BtioYFrg.js +1 -0
  68. package/core/built/admin/assets/copy-field-C6ujqJlP.js +1 -0
  69. package/core/built/admin/assets/create-ghost-browse-value-source-DAZMWZNq.js +1 -0
  70. package/core/built/admin/assets/custom-integration-modal-Dm8QI_J4.js +1 -0
  71. package/core/built/admin/assets/data-list-C0CKkeWW.js +1 -0
  72. package/core/built/admin/assets/date-range-select-DrjHQdgz.js +1 -0
  73. package/core/built/admin/assets/design-and-theme-modal-CXVOzBWu.js +2 -0
  74. package/core/built/admin/assets/detail-page-QpLIL-EO.js +1 -0
  75. package/core/built/admin/assets/dirty-confirm-dialog-DWwxREGh.js +1 -0
  76. package/core/built/admin/assets/disabled-sources-indicator-CLZhMv8J.js +1 -0
  77. package/core/built/admin/assets/dist-BRQkNYN1.js +11 -0
  78. package/core/built/admin/assets/{dist-B3keLvjj.js → dist-BXHrDV19.js} +2 -2
  79. package/core/built/admin/assets/dist-Bf-HQtVL.js +1 -0
  80. package/core/built/admin/assets/dist-Bm-PB47a.js +6 -0
  81. package/core/built/admin/assets/{dist-B6bJuxL3.js → dist-C2lYC76d.js} +1 -1
  82. package/core/built/admin/assets/dist-CUwte9v_.js +1 -0
  83. package/core/built/admin/assets/dist-Cm2qbZKL.js +1 -0
  84. package/core/built/admin/assets/{dist-BtaTA7Ii.js → dist-D7yMk931.js} +1 -1
  85. package/core/built/admin/assets/{dist-zwwGt8Yf.js → dist-DNAdeRyr.js} +1 -1
  86. package/core/built/admin/assets/dist-DS6zpxid.js +1 -0
  87. package/core/built/admin/assets/dist-DVVKsyPh.js +23 -0
  88. package/core/built/admin/assets/dist-DxfQlAmn.js +1 -0
  89. package/core/built/admin/assets/dist-DziNzWI2.js +1 -0
  90. package/core/built/admin/assets/dist-FEQQAwTe.js +1 -0
  91. package/core/built/admin/assets/dist-nmRzULcD.js +1 -0
  92. package/core/built/admin/assets/domain-DBrBic6q.js +1 -0
  93. package/core/built/admin/assets/dropzone-D61QVcEY.js +5 -0
  94. package/core/built/admin/assets/edit-profile-jCqJBxqw.js +1 -0
  95. package/core/built/admin/assets/editor-8Fm4UBEd.js +8 -0
  96. package/core/built/admin/assets/editor-screen-BSX_uC2B.js +27 -0
  97. package/core/built/admin/assets/email-previews-Bs-JDhIw.js +1 -0
  98. package/core/built/admin/assets/email-sending-status-context-C76KYL1V.js +1 -0
  99. package/core/built/admin/assets/email-sending-status-provider-DnNhlIvt.js +1 -0
  100. package/core/built/admin/assets/{emails-vFMk4yYl.js → emails-CgvIIz3q.js} +1 -1
  101. package/core/built/admin/assets/{embed-signup-form-modal-DGqsORxS.js → embed-signup-form-modal-DqtBs1WE.js} +1 -1
  102. package/core/built/admin/assets/empty-indicator-L4Ql5Db7.js +1 -0
  103. package/core/built/admin/assets/en-Cx75dJv5.js +1 -0
  104. package/core/built/admin/assets/esm--rhhUGIG.js +2 -0
  105. package/core/built/admin/assets/explore-DXhDCtKw.js +1 -0
  106. package/core/built/admin/assets/feature-flag-overrides-context-CrcQKm9Z.js +1 -0
  107. package/core/built/admin/assets/feature-image-placeholder-e2q6TcH6.js +1 -0
  108. package/core/built/admin/assets/feed-mmt4noNL.js +1 -0
  109. package/core/built/admin/assets/feedback-BTPBQLT5.js +1 -0
  110. package/core/built/admin/assets/field-p7KnP98B.js +1 -0
  111. package/core/built/admin/assets/filter-bar-CiIKBg3D.js +1 -0
  112. package/core/built/admin/assets/filter-sources-I-dRaQxl.js +1 -0
  113. package/core/built/admin/assets/filters-1injvyxJ.js +1 -0
  114. package/core/built/admin/assets/filters-DnpO6GWX.js +1 -0
  115. package/core/built/admin/assets/first-promoter-modal-wr73Dldc.js +1 -0
  116. package/core/built/admin/assets/focus-koenig-editor-on-bottom-click-CkFA8EkI.js +1 -0
  117. package/core/built/admin/assets/framework-provider-DB-svAju.js +4 -0
  118. package/core/built/admin/assets/{ghost-b4e8a403baba61905cd7560e30b9732d.js → ghost-a1e6e172c6917e8ef8fa6b0007756d9b.js} +39 -30
  119. package/core/built/admin/assets/gift-link-modal-C3H7YFXO.js +1 -0
  120. package/core/built/admin/assets/{gift-links-CfLSnst2.js → gift-links-D8gl_yJS.js} +1 -1
  121. package/core/built/admin/assets/global-data-context-3MItMry2.js +1 -0
  122. package/core/built/admin/assets/grid-5vplBYri.js +1 -0
  123. package/core/built/admin/assets/growth-B1og1kQp.js +1 -0
  124. package/core/built/admin/assets/growth-Bf6OHZlK.js +3 -0
  125. package/core/built/admin/assets/heading-BB21QAbb.js +1 -0
  126. package/core/built/admin/assets/history-modal-t_qEnxPx.js +1 -0
  127. package/core/built/admin/assets/hooks-DYfTEQLk.js +2 -0
  128. package/core/built/admin/assets/html-field-COLQbV4r.js +1 -0
  129. package/core/built/admin/assets/iframe-buffering-Bq1el-gw.js +1 -0
  130. package/core/built/admin/assets/images-4mvoc3lB.js +1 -0
  131. package/core/built/admin/assets/{inbox-gJHG7_xd.js → inbox-DgSZ6w2p.js} +34 -34
  132. package/core/built/admin/assets/index-B3HZU2i8.css +2 -0
  133. package/core/built/admin/assets/index-DDd-zhNL.js +4 -0
  134. package/core/built/admin/assets/index.es-Ct5XQNSj.js +1 -0
  135. package/core/built/admin/assets/inline-B8H6NzIw.js +1 -0
  136. package/core/built/admin/assets/input-group-CLIN2ykI.js +1 -0
  137. package/core/built/admin/assets/{input-surface-BsrIZeSF.js → input-surface-wSO5CRy5.js} +1 -1
  138. package/core/built/admin/assets/integration-header-CKGrXNVP.js +1 -0
  139. package/core/built/admin/assets/{integrations-B4kuRBFY.js → integrations-DnJrZnHv.js} +1 -1
  140. package/core/built/admin/assets/invite-user-modal-BaN2mdhI.js +1 -0
  141. package/core/built/admin/assets/jsx-runtime-BlNNh7jY.js +1 -0
  142. package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +3 -3
  143. package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +1 -1
  144. package/core/built/admin/assets/{koenig-lexical-CGXb0F8o.js → koenig-lexical-CXVgQFUk.js} +1 -1
  145. package/core/built/admin/assets/koenig-loader-B1XPPY5C.js +2 -0
  146. package/core/built/admin/assets/kpi-card-CRLPVlFW.js +1 -0
  147. package/core/built/admin/assets/kpi-card-CRPbW8NZ.js +1 -0
  148. package/core/built/admin/assets/kpi-helpers-D7zT96bp.js +1 -0
  149. package/core/built/admin/assets/kpi-tabs-DE_yh9Go.js +1 -0
  150. package/core/built/admin/assets/label-CgeBxy4o.js +1 -0
  151. package/core/built/admin/assets/label-picker-DGDp4Vwr.js +1 -0
  152. package/core/built/admin/assets/labels-KMkFoRG6.js +1 -0
  153. package/core/built/admin/assets/layout-DWnOMly4.js +1 -0
  154. package/core/built/admin/assets/lib-_QYaUU89.js +2 -0
  155. package/core/built/admin/assets/link-helpers-8J7ixADV.js +1 -0
  156. package/core/built/admin/assets/links-FwNCVyVe.js +1 -0
  157. package/core/built/admin/assets/list-page-DLMP0PxC.js +1 -0
  158. package/core/built/admin/assets/luxon-BXCsmep3.js +1 -0
  159. package/core/built/admin/assets/member-activity-ClMWFyvN.js +1 -0
  160. package/core/built/admin/assets/member-activity-feed-BQY5Rwaj.js +1 -0
  161. package/core/built/admin/assets/member-custom-fields-Dd_ie1zG.js +1 -0
  162. package/core/built/admin/assets/member-detail-DjwkGVne.js +1 -0
  163. package/core/built/admin/assets/members--N9lhk1N.js +4 -0
  164. package/core/built/admin/assets/modal-page-Dz-9TP4E.js +1 -0
  165. package/core/built/admin/assets/moderation-DfYBKq9s.js +1 -0
  166. package/core/built/admin/assets/multi-select-combobox-BcBEzUW_.js +1 -0
  167. package/core/built/admin/assets/navigation-modal-Cd-scywg.js +1 -0
  168. package/core/built/admin/assets/newsletter-detail-modal-CFRY6vg_.js +1 -0
  169. package/core/built/admin/assets/newsletter-emails-4ntck1AC.js +1 -0
  170. package/core/built/admin/assets/newsletter-o6eCJtab.js +1 -0
  171. package/core/built/admin/assets/newsletters-Bmlv0edG.js +1 -0
  172. package/core/built/admin/assets/{newsletters-Rq1M3GD-.js → newsletters-Dz77m__5.js} +1 -1
  173. package/core/built/admin/assets/note-CWs3LF-0.js +1 -0
  174. package/core/built/admin/assets/notifications-BjSvTJqh.js +1 -0
  175. package/core/built/admin/assets/{nql-BLpCn7qX.js → nql-DnDc7UuU.js} +1 -1
  176. package/core/built/admin/assets/nql-lang-CeTB_Bhv.js +19 -0
  177. package/core/built/admin/assets/{offers--e2nGvkW.js → offers-ByWSK0rR.js} +1 -1
  178. package/core/built/admin/assets/offers-container-modal-Bc9A196w.js +1 -0
  179. package/core/built/admin/assets/onboarding-B4hfBi9a.js +1 -0
  180. package/core/built/admin/assets/onboarding-DV_XbHts.js +1 -0
  181. package/core/built/admin/assets/onboarding-route-Di1LJYEE.js +1 -0
  182. package/core/built/admin/assets/overview-DE7NHZQN.js +1 -0
  183. package/core/built/admin/assets/overview-DEF-ZY6x.js +1 -0
  184. package/core/built/admin/assets/page-header-B-G_g42C.js +1 -0
  185. package/core/built/admin/assets/pagemenu-CnkTDO71.js +1 -0
  186. package/core/built/admin/assets/{pages-CjDY2CBI.js → pages-DZ_YGB1D.js} +1 -1
  187. package/core/built/admin/assets/pages-route-VT7r7YhG.js +1 -0
  188. package/core/built/admin/assets/papaparse.min-BlhnCUXn.js +10 -0
  189. package/core/built/admin/assets/pintura-modal-BljM7hf8.js +1 -0
  190. package/core/built/admin/assets/portal-frame-D9V8iq5x.js +1 -0
  191. package/core/built/admin/assets/portal-modal-B5OOR9ZD.js +1 -0
  192. package/core/built/admin/assets/post-analytics-context-bt2YTBAC.js +1 -0
  193. package/core/built/admin/assets/post-analytics-header-J0WciLx6.js +1 -0
  194. package/core/built/admin/assets/post-analytics-provider-CgreZDjS.js +1 -0
  195. package/core/built/admin/assets/post-analytics-rGb-PgD-.js +1 -0
  196. package/core/built/admin/assets/post-share-modal-D0BbTo4W.js +1 -0
  197. package/core/built/admin/assets/posts-list-screen-CO5jAWoU.js +2 -0
  198. package/core/built/admin/assets/posts-route-DV-CXWK9.js +1 -0
  199. package/core/built/admin/assets/{posts-pCPrhQeR.js → posts-tcoO3iRG.js} +1 -1
  200. package/core/built/admin/assets/preferences-Tac29oG6.js +5 -0
  201. package/core/built/admin/assets/preview-chrome-C2lQgZBZ.js +1 -0
  202. package/core/built/admin/assets/preview-modal-CjRbBr8U.js +1 -0
  203. package/core/built/admin/assets/profile-yiM1f_Og.js +1 -0
  204. package/core/built/admin/assets/prop-types-6lTeqvom.js +1 -0
  205. package/core/built/admin/assets/radio-group-CKROWsw4.js +1 -0
  206. package/core/built/admin/assets/react-BXwhMTuc.js +1 -0
  207. package/core/built/admin/assets/{jsx-runtime-DX3WBWVO.js → react-dom-CMOtJ5MH.js} +2 -2
  208. package/core/built/admin/assets/{referrers-D8oHPmDB.js → referrers-1R8bPpoV.js} +1 -1
  209. package/core/built/admin/assets/router-provider-CU87qxXw.js +1 -0
  210. package/core/built/admin/assets/select-CKaC4ggu.js +1 -0
  211. package/core/built/admin/assets/settings-81kxUa28.js +1 -0
  212. package/core/built/admin/assets/settings-BVXFqBVK.js +4 -0
  213. package/core/built/admin/assets/settings-breadcrumbs-czGRx-iu.js +1 -0
  214. package/core/built/admin/assets/{shade-app-CcS3f8MZ-vwURazk8.js → shade-app-CcS3f8MZ-D5BnfHck.js} +1 -1
  215. package/core/built/admin/assets/share-modal-BL-16PiB.js +1 -0
  216. package/core/built/admin/assets/skeleton-DwCva0-b.js +1 -0
  217. package/core/built/admin/assets/slack-modal-D7W_fNON.js +1 -0
  218. package/core/built/admin/assets/sort-button-Dquc83jY.js +1 -0
  219. package/core/built/admin/assets/source-icon-CQboPZQ3.js +1 -0
  220. package/core/built/admin/assets/stack-BURz77VS.js +1 -0
  221. package/core/built/admin/assets/{stats-D9PDLS3x.js → stats-Cvp8Ep5m.js} +1 -1
  222. package/core/built/admin/assets/stats-view-NDja_g96.js +1 -0
  223. package/core/built/admin/assets/step-1-BKhjy0PV.js +1 -0
  224. package/core/built/admin/assets/step-2-PxA1OM7R.js +1 -0
  225. package/core/built/admin/assets/step-3-BJbAiq16.js +2 -0
  226. package/core/built/admin/assets/stripe-button-C3cfCAou.js +1 -0
  227. package/core/built/admin/assets/stripe-connect-modal-FyE3Ey2c.js +1 -0
  228. package/core/built/admin/assets/switch-zfUUy9Jh.js +1 -0
  229. package/core/built/admin/assets/table-dE4GTIRT.js +1 -0
  230. package/core/built/admin/assets/tabs-B3XK93sR.js +1 -0
  231. package/core/built/admin/assets/tag-detail-D4P-tZdM.js +2 -0
  232. package/core/built/admin/assets/tag-picker-BNSZ6Qxw.js +1 -0
  233. package/core/built/admin/assets/tags-BsZcaJ6h.js +1 -0
  234. package/core/built/admin/assets/{tags-ChfdwJyS.js → tags-NwZ7BPK6.js} +1 -1
  235. package/core/built/admin/assets/testimonials-modal-Dkt6ODLW.js +1 -0
  236. package/core/built/admin/assets/text-DC-ot6u2.js +1 -0
  237. package/core/built/admin/assets/textarea-B4FffFmE.js +1 -0
  238. package/core/built/admin/assets/themes-DtcEFQWm.js +1 -0
  239. package/core/built/admin/assets/tier-detail-modal-a77Z2VMH.js +1 -0
  240. package/core/built/admin/assets/{tiers-BCpIOGQr.js → tiers-6mPzCXlM.js} +1 -1
  241. package/core/built/admin/assets/toggle-group-D2p4okmJ.js +1 -0
  242. package/core/built/admin/assets/topic-filter-DVOe3D-b.js +1 -0
  243. package/core/built/admin/assets/transistor-modal-C8RMkhOD.js +1 -0
  244. package/core/built/admin/assets/trend-badge-B9v7kMF8.js +1 -0
  245. package/core/built/admin/assets/unsplash-modal-DXt7Brum.js +1 -0
  246. package/core/built/admin/assets/use-analytics-data-ChHqiZXv.js +1 -0
  247. package/core/built/admin/assets/use-availability-hPdeG76y.js +1 -0
  248. package/core/built/admin/assets/{use-check-theme-limit-error-DRUjK4YM.js → use-check-theme-limit-error-JD-J5aaZ.js} +2 -2
  249. package/core/built/admin/assets/use-email-sending-status-DNMtL5B9.js +1 -0
  250. package/core/built/admin/assets/use-filter-params-BSFigDIn.js +1 -0
  251. package/core/built/admin/assets/use-filterable-api-CEMSAYPg.js +1 -0
  252. package/core/built/admin/assets/use-form-DJKZJhQh.js +1 -0
  253. package/core/built/admin/assets/use-growth-stats-CqqdnESN.js +1 -0
  254. package/core/built/admin/assets/use-host-limits-mpTkZIq8.js +1 -0
  255. package/core/built/admin/assets/use-limiter-DBGjYqu7.js +19 -0
  256. package/core/built/admin/assets/use-navigate-with-base-path-88EQpw2k.js +1 -0
  257. package/core/built/admin/assets/use-pintura-config-BmU45Ruy.js +1 -0
  258. package/core/built/admin/assets/use-pintura-editor-Bz2bZ4iT.js +1 -0
  259. package/core/built/admin/assets/use-post-referrers-DyPjyBSN.js +1 -0
  260. package/core/built/admin/assets/use-query-params-DlOHCo-R.js +1 -0
  261. package/core/built/admin/assets/use-reply-chain-data-DmD2yX5D.js +1 -0
  262. package/core/built/admin/assets/use-router-history-entry-CKx9LhqD.js +1 -0
  263. package/core/built/admin/assets/use-sending-eta-CQeG6OP_.js +1 -0
  264. package/core/built/admin/assets/use-setting-group-Dza6bQ7W.js +1 -0
  265. package/core/built/admin/assets/use-settings-navigation-BIjI5mL3.js +1 -0
  266. package/core/built/admin/assets/use-simple-pagination-DwVxe-Lo.js +1 -0
  267. package/core/built/admin/assets/use-staff-users-i_Mq9OGR.js +1 -0
  268. package/core/built/admin/assets/{use-tinybird-query-CmdbCS9X.js → use-tinybird-query-DXoF74NM.js} +1 -1
  269. package/core/built/admin/assets/use-tinybird-token-Lk1RSn0t.js +1 -0
  270. package/core/built/admin/assets/use-unsaved-changes-guard-CKVPWz_F.js +1 -0
  271. package/core/built/admin/assets/use-upgrade-route-CVjDlNSs.js +1 -0
  272. package/core/built/admin/assets/{use-url-input-fvp-TpPx.js → use-url-input-DpmbDppC.js} +1 -1
  273. package/core/built/admin/assets/user-detail-modal-BU4QCHE7.js +1 -0
  274. package/core/built/admin/assets/{users-DVNWrqg9.js → users-C60_hpn6.js} +1 -1
  275. package/core/built/admin/assets/{validator-Cr0sMKuW.js → validator-DlFQP70j.js} +1 -1
  276. package/core/built/admin/assets/virtual-list-DScLNuU8.js +1 -0
  277. package/core/built/admin/assets/web-BZS-t4H0.js +1 -0
  278. package/core/built/admin/assets/web-DxAUxnK3.js +2 -0
  279. package/core/built/admin/assets/zapier-modal-BafLUO4R.js +1 -0
  280. package/core/built/admin/index.html +35 -32
  281. package/core/cli/command.js +17 -2
  282. package/core/frontend/meta/asset-url.js +1 -16
  283. package/core/frontend/services/asset-hash/index.js +32 -2
  284. package/core/frontend/services/routing/controllers/unsubscribe.js +2 -1
  285. package/core/frontend/services/rss/generate-feed.js +1 -1
  286. package/core/frontend/services/theme-engine/active.js +2 -4
  287. package/core/frontend/services/theme-engine/i18n/i18n.js +11 -1
  288. package/core/frontend/services/theme-engine/i18next/theme-i18n.js +1 -1
  289. package/core/frontend/web/middleware/llms-discovery.js +34 -43
  290. package/core/server/adapters/route-settings/S3RouteSettingsStore.js +1 -1
  291. package/core/server/adapters/storage/LocalFilesStorage.js +12 -2
  292. package/core/server/adapters/storage/LocalStorageBase.js +13 -0
  293. package/core/server/api/endpoints/actions.js +2 -1
  294. package/core/server/api/endpoints/automated-emails.js +3 -2
  295. package/core/server/api/endpoints/automations.js +77 -49
  296. package/core/server/api/endpoints/emails.js +8 -3
  297. package/core/server/api/endpoints/index.js +1 -1
  298. package/core/server/api/endpoints/invites.js +2 -1
  299. package/core/server/api/endpoints/labels.js +6 -2
  300. package/core/server/api/endpoints/member-metafields.js +2 -2
  301. package/core/server/api/endpoints/members.js +22 -6
  302. package/core/server/api/endpoints/pages.js +2 -6
  303. package/core/server/api/endpoints/posts.js +3 -11
  304. package/core/server/api/endpoints/snippets.js +2 -1
  305. package/core/server/api/endpoints/tags.js +6 -2
  306. package/core/server/api/endpoints/users.js +2 -6
  307. package/core/server/api/endpoints/utils/api-filter-utils.js +62 -3
  308. package/core/server/api/endpoints/utils/serializers/output/utils/clean.js +2 -0
  309. package/core/server/api/endpoints/utils/serializers/output/utils/extra-attrs.js +3 -0
  310. package/core/server/api/endpoints/utils/validators/input/settings.js +15 -1
  311. package/core/server/data/exporter/exporter.js +2 -1
  312. package/core/server/data/exporter/table-lists.js +3 -5
  313. package/core/server/data/importer/importers/data/settings-importer.js +8 -2
  314. package/core/server/data/migrations/versions/6.64/2026-09-03-15-40-25-add-member-access-to-members-metafields.js +12 -0
  315. package/core/server/data/migrations/versions/6.64/2026-09-08-11-01-12-add-posts-auto-excerpt-and-reading-time-columns.js +17 -0
  316. package/core/server/data/migrations/versions/6.64/2026-09-09-13-56-18-add-automation-run-updated-at-indexes.js +6 -0
  317. package/core/server/data/migrations/versions/6.64/2026-09-09-13-56-18-add-tinybird-syncs-table.js +10 -0
  318. package/core/server/data/schema/schema.js +28 -2
  319. package/core/server/data/seeders/importers/automations-importer.js +0 -1
  320. package/core/server/data/seeders/importers/comments-importer.js +1 -1
  321. package/core/server/data/seeders/importers/email-recipients-importer.js +1 -1
  322. package/core/server/data/seeders/importers/emails-importer.js +1 -1
  323. package/core/server/data/seeders/importers/members-importer.js +1 -1
  324. package/core/server/data/seeders/importers/members-login-events-importer.js +1 -1
  325. package/core/server/data/seeders/importers/members-stripe-customers-subscriptions-importer.js +1 -1
  326. package/core/server/data/seeders/utils/blog-info.js +4 -3
  327. package/core/server/data/seeders/utils/event-generator.js +72 -46
  328. package/core/server/data/tinybird/datasources/_mv_automation_run_steps.datasource +10 -0
  329. package/core/server/data/tinybird/datasources/_mv_automation_runs.datasource +10 -0
  330. package/core/server/data/tinybird/datasources/_mv_pending_automation_runs.datasource +10 -0
  331. package/core/server/data/tinybird/datasources/automation_run_events.datasource +12 -0
  332. package/core/server/data/tinybird/datasources/automation_run_step_events.datasource +12 -0
  333. package/core/server/data/tinybird/endpoints/api_automation_browse_stats.pipe +43 -0
  334. package/core/server/data/tinybird/fixtures/automation_run_events.ndjson +7 -0
  335. package/core/server/data/tinybird/fixtures/automation_run_step_events.ndjson +8 -0
  336. package/core/server/data/tinybird/pipes/mv_automation_run_steps.pipe +13 -0
  337. package/core/server/data/tinybird/pipes/mv_automation_runs.pipe +15 -0
  338. package/core/server/data/tinybird/pipes/mv_pending_automation_runs.pipe +7 -0
  339. package/core/server/data/tinybird/tests/api_automation_browse_stats.yaml +18 -0
  340. package/core/server/ghost-server.js +3 -3
  341. package/core/server/lib/generate-password.js +54 -0
  342. package/core/server/lib/public-jwk.js +77 -0
  343. package/core/server/models/user.js +11 -9
  344. package/core/server/services/adapter-manager/base-classes.js +21 -3
  345. package/core/server/services/automations/automations-api.js +46 -1
  346. package/core/server/services/automations/tinybird-automation-stats.js +56 -0
  347. package/core/server/services/content-import/import/media.js +1 -1
  348. package/core/server/services/email-analytics/email-analytics-service-wrapper.js +15 -29
  349. package/core/server/services/email-analytics/email-analytics-service.js +19 -3
  350. package/core/server/services/email-analytics/index.js +9 -4
  351. package/core/server/services/email-rendering/finalize.js +7 -2
  352. package/core/server/services/email-service/README.md +3 -0
  353. package/core/server/services/email-service/email-renderer.js +7 -2
  354. package/core/server/services/email-service/email-service-wrapper.js +1 -1
  355. package/core/server/services/email-service/email-service.js +43 -34
  356. package/core/server/services/email-service/sending-status.js +10 -4
  357. package/core/server/services/gifts/gift-email-service.js +10 -3
  358. package/core/server/services/gifts/index.js +1 -0
  359. package/core/server/services/i18n.js +1 -1
  360. package/core/server/services/identity-tokens/identity-token-service-wrapper.js +3 -4
  361. package/core/server/services/limits.js +17 -1
  362. package/core/server/services/member-welcome-emails/service.js +1 -1
  363. package/core/server/services/members/import-export/index.js +5 -4
  364. package/core/server/services/members/members-api/controllers/router-controller.js +7 -2
  365. package/core/server/services/members/members-api/controllers/well-known-controller.js +2 -1
  366. package/core/server/services/members/members-api/repositories/event-repository.js +4 -0
  367. package/core/server/services/members/members-api/services/member-bread-service.js +15 -12
  368. package/core/server/services/members/members-api/services/token-service.js +11 -12
  369. package/core/server/services/members/middleware.js +9 -2
  370. package/core/server/services/members/request-integrity-token-provider.js +2 -1
  371. package/core/server/services/members-metafields/access.js +31 -20
  372. package/core/server/services/members-metafields/actions.js +1 -0
  373. package/core/server/services/members-metafields/codec.js +9 -2
  374. package/core/server/services/members-metafields/definitions-service.js +56 -46
  375. package/core/server/services/members-metafields/index.js +2 -2
  376. package/core/server/services/members-metafields/models.js +2 -0
  377. package/core/server/services/members-metafields/queries.js +39 -11
  378. package/core/server/services/members-metafields/schema.js +2 -0
  379. package/core/server/services/members-metafields/serializers.js +1 -0
  380. package/core/server/services/members-metafields/values-service.js +20 -11
  381. package/core/server/services/mentions/mention-discovery-service.js +1 -1
  382. package/core/server/services/mentions/mention-sending-service.js +1 -1
  383. package/core/server/services/mentions/mention.js +1 -1
  384. package/core/server/services/oembed/oembed-service.js +36 -11
  385. package/core/server/services/posts/post-scheduling.js +20 -0
  386. package/core/server/services/staff/staff-service-emails.js +5 -1
  387. package/core/server/services/stats/stats-service.js +12 -3
  388. package/core/server/services/tier-checkout-config/service.js +17 -1
  389. package/core/server/services/tinybird/tinybird-service.js +1 -0
  390. package/core/server/services/tinybird-sync/get-ingest-config.js +39 -0
  391. package/core/server/services/tinybird-sync/index.js +28 -0
  392. package/core/server/services/tinybird-sync/sync-table-to-tinybird.js +149 -0
  393. package/core/server/services/tinybird-sync/tinybird-sync-service.js +62 -0
  394. package/core/server/web/api/endpoints/admin/routes.js +33 -34
  395. package/core/server/web/well-known.js +12 -16
  396. package/core/shared/config/defaults.json +1 -2
  397. package/core/shared/{flush-logs.js → flush.js} +7 -3
  398. package/core/shared/labs.js +2 -0
  399. package/core/shared/timing-safe-string-equal.js +26 -0
  400. package/package.json +42 -42
  401. package/patches/@elastic__elasticsearch@8.19.2.patch +67 -0
  402. package/patches/juice@11.1.1.patch +46 -0
  403. package/pnpm-lock.yaml +457 -1391
  404. package/pnpm-workspace.yaml +34 -21
  405. package/scripts/prune.mts +70 -3
  406. package/components/tryghost-kg-lexical-html-renderer-1.5.0.tgz +0 -0
  407. package/core/built/admin/assets/Combination-B0l4MKVh.js +0 -41
  408. package/core/built/admin/assets/RadialBarChart-JAKoS4KT.js +0 -1
  409. package/core/built/admin/assets/_baseAssignValue-C_vooEQc.js +0 -1
  410. package/core/built/admin/assets/about-C1C3s5-g.js +0 -1
  411. package/core/built/admin/assets/accordion-CxGsDKwa.js +0 -1
  412. package/core/built/admin/assets/account-migration-CbUhW6gk.js +0 -1
  413. package/core/built/admin/assets/action-list-C4v0-du8.js +0 -1
  414. package/core/built/admin/assets/add-integration-modal-BT_onDJy.js +0 -1
  415. package/core/built/admin/assets/add-newsletter-modal-Cx1kQpiY.js +0 -1
  416. package/core/built/admin/assets/add-recommendation-modal-B5nvAhvr.js +0 -1
  417. package/core/built/admin/assets/analytics-DjoJWPI7.js +0 -1
  418. package/core/built/admin/assets/announcement-bar-modal-Dwd0EGFP.js +0 -1
  419. package/core/built/admin/assets/api-keys-BoeacM-s.js +0 -1
  420. package/core/built/admin/assets/automated-emails-BLesE41L.js +0 -1
  421. package/core/built/admin/assets/automations-BN4u3GR8.js +0 -1
  422. package/core/built/admin/assets/automations-C-ZTUwW3.js +0 -1
  423. package/core/built/admin/assets/avatar-flipboard-C6Kj3Awu.js +0 -1
  424. package/core/built/admin/assets/bluesky-sharing-vzh-oPXL.js +0 -1
  425. package/core/built/admin/assets/box-CdfQAP_F.js +0 -1
  426. package/core/built/admin/assets/brand-icon-CrIGOA3Z.js +0 -1
  427. package/core/built/admin/assets/breadcrumb-CaLk2b7D.js +0 -1
  428. package/core/built/admin/assets/build-CsiH26uS.js +0 -1
  429. package/core/built/admin/assets/button-Dvcv1QSR.js +0 -1
  430. package/core/built/admin/assets/calendar-Bl9RLcZX.js +0 -1
  431. package/core/built/admin/assets/card--VNbfgo3.js +0 -1
  432. package/core/built/admin/assets/chart-helpers-FHywU0pj.js +0 -1
  433. package/core/built/admin/assets/checkbox-BtayFtjg.js +0 -1
  434. package/core/built/admin/assets/chunk.524.e6975095fccdf22d90f8.js +0 -32
  435. package/core/built/admin/assets/code-editor-view-C3ZfoF1X.js +0 -1
  436. package/core/built/admin/assets/code-editor-view-CAyRWy1s.js +0 -1
  437. package/core/built/admin/assets/color-picker-G4kGR7rp.js +0 -3
  438. package/core/built/admin/assets/color-picker-field-DQFVTNnT.js +0 -1
  439. package/core/built/admin/assets/combobox-BnYzgEB4.js +0 -1
  440. package/core/built/admin/assets/command-C_vyTikI.js +0 -1
  441. package/core/built/admin/assets/comments-aBrxfnZf.js +0 -1
  442. package/core/built/admin/assets/components-CwL6a6As-B0E0-NBJ.js +0 -1
  443. package/core/built/admin/assets/confirmation-context-DwXX_Y5h.js +0 -1
  444. package/core/built/admin/assets/container-BuQG1wuP.js +0 -1
  445. package/core/built/admin/assets/content-api-modal-D2G0nJP6.js +0 -1
  446. package/core/built/admin/assets/context-menu-DOVB6yaz.js +0 -1
  447. package/core/built/admin/assets/copy-field-DCJwh9qf.js +0 -1
  448. package/core/built/admin/assets/create-ghost-browse-value-source-5C53jJaX.js +0 -1
  449. package/core/built/admin/assets/custom-field-type-option-BAuW0F-E.js +0 -1
  450. package/core/built/admin/assets/custom-integration-modal-AbJGVyKc.js +0 -1
  451. package/core/built/admin/assets/data-list-CA2jYGPq.js +0 -1
  452. package/core/built/admin/assets/date-range-select-BY3K-ukj.js +0 -1
  453. package/core/built/admin/assets/design-and-theme-modal-BvEy4_pC.js +0 -2
  454. package/core/built/admin/assets/detail-page-Dnv-CdR1.js +0 -1
  455. package/core/built/admin/assets/dirty-confirm-dialog-DVPuGz3U.js +0 -1
  456. package/core/built/admin/assets/disabled-sources-indicator-Cy7Zp4c8.js +0 -1
  457. package/core/built/admin/assets/dist-4m6pHdc0.js +0 -23
  458. package/core/built/admin/assets/dist-8YJUlf3B.js +0 -1
  459. package/core/built/admin/assets/dist-CZgIBXQN.js +0 -1
  460. package/core/built/admin/assets/dist-CiHx7vA5.js +0 -6
  461. package/core/built/admin/assets/dist-DIC8yz5C.js +0 -1
  462. package/core/built/admin/assets/dist-Dcsslyo72.js +0 -1
  463. package/core/built/admin/assets/dist-Dgt2cr6a.js +0 -1
  464. package/core/built/admin/assets/dist-ECAUrdGc.js +0 -1
  465. package/core/built/admin/assets/dist-JLOy8o0Q.js +0 -1
  466. package/core/built/admin/assets/dist-Ndy-PuGN.js +0 -1
  467. package/core/built/admin/assets/dist-Z97pCNqS.js +0 -11
  468. package/core/built/admin/assets/domain-Dl61QGuk.js +0 -1
  469. package/core/built/admin/assets/dropzone-Dtz5Rmjt.js +0 -5
  470. package/core/built/admin/assets/edit-profile-DNJSMDwm.js +0 -1
  471. package/core/built/admin/assets/editor-DbAen9zf.js +0 -8
  472. package/core/built/admin/assets/editor-screen-BFWThIai.js +0 -26
  473. package/core/built/admin/assets/email-sending-status-context-CWDOD1FN.js +0 -1
  474. package/core/built/admin/assets/email-sending-status-provider-DCPkDICt.js +0 -1
  475. package/core/built/admin/assets/empty-indicator-D9QdpuNX.js +0 -1
  476. package/core/built/admin/assets/en-B1jX3WMs.js +0 -1
  477. package/core/built/admin/assets/esm-CXo5SEPy.js +0 -2
  478. package/core/built/admin/assets/explore-nnRr1Fja.js +0 -1
  479. package/core/built/admin/assets/feature-flag-overrides-context-DQjdJFAk.js +0 -1
  480. package/core/built/admin/assets/feature-image-placeholder-BrIHmPs8.js +0 -1
  481. package/core/built/admin/assets/feed-BNUcNu-W.js +0 -1
  482. package/core/built/admin/assets/feedback-DJ4Zb9rZ.js +0 -1
  483. package/core/built/admin/assets/field-C93_Mg6j.js +0 -1
  484. package/core/built/admin/assets/filter-bar-Da1qxybu.js +0 -1
  485. package/core/built/admin/assets/filter-sources-CGJb4C5r.js +0 -1
  486. package/core/built/admin/assets/filters--kKP-EC8.js +0 -1
  487. package/core/built/admin/assets/filters-DxA_a4FP.js +0 -1
  488. package/core/built/admin/assets/first-promoter-modal-BYDtrz2S.js +0 -1
  489. package/core/built/admin/assets/focus-koenig-editor-on-bottom-click-BbSnGOtK.js +0 -1
  490. package/core/built/admin/assets/framework-provider-DqI25epG.js +0 -4
  491. package/core/built/admin/assets/gift-link-modal-B7u5bD4e.js +0 -1
  492. package/core/built/admin/assets/global-data-context-gAMDH9u1.js +0 -1
  493. package/core/built/admin/assets/grid-Dj29PY05.js +0 -1
  494. package/core/built/admin/assets/growth-Cd1uO9d2.js +0 -1
  495. package/core/built/admin/assets/growth-aG32xfdE.js +0 -3
  496. package/core/built/admin/assets/heading-Dh5SFVjL.js +0 -1
  497. package/core/built/admin/assets/history-modal-Df8lW8h-.js +0 -1
  498. package/core/built/admin/assets/hooks-Cy_-oZ4o.js +0 -2
  499. package/core/built/admin/assets/html-field-DA4eU7eq.js +0 -1
  500. package/core/built/admin/assets/iframe-buffering-B2OKJzbz.js +0 -1
  501. package/core/built/admin/assets/images-KXmyO3Ss.js +0 -1
  502. package/core/built/admin/assets/index-BHHXtR5C.css +0 -2
  503. package/core/built/admin/assets/index-CgMCwsxN.js +0 -4
  504. package/core/built/admin/assets/index.es-CY6-yuw9.js +0 -1
  505. package/core/built/admin/assets/inline-BWSs_VzR.js +0 -1
  506. package/core/built/admin/assets/input-group-BE8rM2y1.js +0 -1
  507. package/core/built/admin/assets/integration-header-Bm6IDb1A.js +0 -1
  508. package/core/built/admin/assets/invite-user-modal-B4CuNcx4.js +0 -1
  509. package/core/built/admin/assets/koenig-loader-BeM5rFPX.js +0 -2
  510. package/core/built/admin/assets/kpi-card-B21aToe8.js +0 -1
  511. package/core/built/admin/assets/kpi-card-pz6Wv4Ae.js +0 -1
  512. package/core/built/admin/assets/kpi-helpers-Dq5jelmP.js +0 -1
  513. package/core/built/admin/assets/kpi-tabs-DEZHpKUt.js +0 -1
  514. package/core/built/admin/assets/label-OLCzze8N.js +0 -1
  515. package/core/built/admin/assets/label-picker-BigOvMPV.js +0 -1
  516. package/core/built/admin/assets/labels-Dr0SgUQD.js +0 -1
  517. package/core/built/admin/assets/layout-DUTL8SH5.js +0 -1
  518. package/core/built/admin/assets/lib-7QPTI0FS.js +0 -1
  519. package/core/built/admin/assets/limit-service-BhiEvqcP.js +0 -20
  520. package/core/built/admin/assets/link-helpers-BRAg9SCj.js +0 -1
  521. package/core/built/admin/assets/links-BDHPTlyj.js +0 -1
  522. package/core/built/admin/assets/list-page-BucXJ0hi.js +0 -1
  523. package/core/built/admin/assets/luxon-D1RVjjpq.js +0 -1
  524. package/core/built/admin/assets/member-custom-fields-TRTHCAz9.js +0 -1
  525. package/core/built/admin/assets/member-detail-b6dRwc3C.js +0 -1
  526. package/core/built/admin/assets/members-Czt5lJSc.js +0 -4
  527. package/core/built/admin/assets/modal-page-xCivTMvI.js +0 -1
  528. package/core/built/admin/assets/moderation-ZWefD9uH.js +0 -1
  529. package/core/built/admin/assets/multi-select-combobox-CT13MTo-.js +0 -1
  530. package/core/built/admin/assets/navigation-modal-C8FEhBK5.js +0 -1
  531. package/core/built/admin/assets/newsletter-5VYW4RyJ.js +0 -1
  532. package/core/built/admin/assets/newsletter-detail-modal-ChjC0ZqH.js +0 -1
  533. package/core/built/admin/assets/newsletter-emails-DZH6I-PY.js +0 -1
  534. package/core/built/admin/assets/newsletters-DOC9KBcX.js +0 -1
  535. package/core/built/admin/assets/note-DIV-Pojr.js +0 -1
  536. package/core/built/admin/assets/notifications-s20-H49V.js +0 -1
  537. package/core/built/admin/assets/nql-lang-CaWrLesS.js +0 -19
  538. package/core/built/admin/assets/offers-container-modal-BmG5M5Tv.js +0 -1
  539. package/core/built/admin/assets/onboarding-CUuy9unR.js +0 -1
  540. package/core/built/admin/assets/onboarding-pXyct0Jm.js +0 -1
  541. package/core/built/admin/assets/onboarding-route-CK4pcXoR.js +0 -1
  542. package/core/built/admin/assets/overview-CaPsciMs.js +0 -1
  543. package/core/built/admin/assets/overview-a8GfcsKX.js +0 -1
  544. package/core/built/admin/assets/page-header-DM_KyoFI.js +0 -1
  545. package/core/built/admin/assets/pagemenu-vgZVUVKR.js +0 -1
  546. package/core/built/admin/assets/pages-route-BzKZYdV5.js +0 -1
  547. package/core/built/admin/assets/papaparse.min-cQwnxGCG.js +0 -10
  548. package/core/built/admin/assets/pintura-modal-DExCF1ii.js +0 -1
  549. package/core/built/admin/assets/portal-frame-Cqanidq4.js +0 -1
  550. package/core/built/admin/assets/portal-modal-oinBgA27.js +0 -1
  551. package/core/built/admin/assets/post-analytics-C5oJ1dWV.js +0 -1
  552. package/core/built/admin/assets/post-analytics-context-D0Mw-Pmv.js +0 -1
  553. package/core/built/admin/assets/post-analytics-header-OATo3X_r.js +0 -1
  554. package/core/built/admin/assets/post-analytics-provider-tOpIVGT5.js +0 -1
  555. package/core/built/admin/assets/post-share-modal-DvhC1XgV.js +0 -1
  556. package/core/built/admin/assets/posts-list-screen-o4ZjbgS3.js +0 -2
  557. package/core/built/admin/assets/posts-route-9F--xdIb.js +0 -1
  558. package/core/built/admin/assets/preferences--vNubsqD.js +0 -5
  559. package/core/built/admin/assets/preview-chrome-BljUBlOk.js +0 -1
  560. package/core/built/admin/assets/preview-modal-YYbzlYdO.js +0 -1
  561. package/core/built/admin/assets/profile-BllKV3dR.js +0 -1
  562. package/core/built/admin/assets/prop-types-DeUPn3oD.js +0 -1
  563. package/core/built/admin/assets/radio-group-DL8GI8rt.js +0 -1
  564. package/core/built/admin/assets/react-Bb3IsNbi.js +0 -1
  565. package/core/built/admin/assets/rolldown-runtime-DAXXjFlN.js +0 -1
  566. package/core/built/admin/assets/router-provider-BSvTXgZY.js +0 -1
  567. package/core/built/admin/assets/select-v5YbA3Mw.js +0 -1
  568. package/core/built/admin/assets/settings-PEsZupw1.js +0 -4
  569. package/core/built/admin/assets/settings-breadcrumbs-NwPnCTC7.js +0 -1
  570. package/core/built/admin/assets/settings-u_s1CRkr.js +0 -1
  571. package/core/built/admin/assets/share-modal-SskCmVGL.js +0 -1
  572. package/core/built/admin/assets/skeleton-Ce9GgUpf.js +0 -1
  573. package/core/built/admin/assets/slack-modal-XxSJiYgo.js +0 -1
  574. package/core/built/admin/assets/sort-button-Cx1KtINE.js +0 -1
  575. package/core/built/admin/assets/source-icon-Bdp9Im_5.js +0 -1
  576. package/core/built/admin/assets/stack-B2eszIiq.js +0 -1
  577. package/core/built/admin/assets/stats-view-W2g6Jsd-.js +0 -1
  578. package/core/built/admin/assets/step-1-BQYzvBzr.js +0 -1
  579. package/core/built/admin/assets/step-2-xES32xJV.js +0 -1
  580. package/core/built/admin/assets/step-3-DA_XK5kW.js +0 -2
  581. package/core/built/admin/assets/stripe-button-CVsLHelt.js +0 -1
  582. package/core/built/admin/assets/stripe-connect-modal-ClmLOMGS.js +0 -1
  583. package/core/built/admin/assets/switch-CI4gLWqb.js +0 -1
  584. package/core/built/admin/assets/table-BenqVupI.js +0 -1
  585. package/core/built/admin/assets/tabs-eBBlxPp8.js +0 -1
  586. package/core/built/admin/assets/tag-detail-Ce8Se2qd.js +0 -2
  587. package/core/built/admin/assets/tag-picker-C3UR-uJ-.js +0 -1
  588. package/core/built/admin/assets/tags-B-kJxCs7.js +0 -1
  589. package/core/built/admin/assets/testimonials-modal-9Q6fT06V.js +0 -1
  590. package/core/built/admin/assets/text-BQDSDsKs.js +0 -1
  591. package/core/built/admin/assets/textarea-DJ1Q5V39.js +0 -1
  592. package/core/built/admin/assets/tier-detail-modal-CDyYdqK7.js +0 -1
  593. package/core/built/admin/assets/toggle-group-CviIkyok.js +0 -1
  594. package/core/built/admin/assets/topic-filter-I2jCBGxm.js +0 -1
  595. package/core/built/admin/assets/transistor-modal-p53u3W8y.js +0 -1
  596. package/core/built/admin/assets/trend-badge-CideVzQd.js +0 -1
  597. package/core/built/admin/assets/unsplash-modal-DY8UcKcE.js +0 -1
  598. package/core/built/admin/assets/use-analytics-data-DAIGcr2f.js +0 -1
  599. package/core/built/admin/assets/use-filter-params-JkZhIS8L.js +0 -1
  600. package/core/built/admin/assets/use-filterable-api-BVEVMrhZ.js +0 -1
  601. package/core/built/admin/assets/use-form-vRjI0Kwk.js +0 -1
  602. package/core/built/admin/assets/use-growth-stats-937CUj6j.js +0 -1
  603. package/core/built/admin/assets/use-host-limits-D0Dv3tKA.js +0 -1
  604. package/core/built/admin/assets/use-limiter-CohWfzvK.js +0 -2
  605. package/core/built/admin/assets/use-navigate-with-base-path-BkxcPj5l.js +0 -1
  606. package/core/built/admin/assets/use-pintura-config-xgytjU35.js +0 -1
  607. package/core/built/admin/assets/use-pintura-editor-CaV1mbfO.js +0 -1
  608. package/core/built/admin/assets/use-post-referrers-BCQI7fDg.js +0 -1
  609. package/core/built/admin/assets/use-query-params-BfzuqbcD.js +0 -1
  610. package/core/built/admin/assets/use-reply-chain-data-CYRhoaxY.js +0 -1
  611. package/core/built/admin/assets/use-router-history-entry-NOKcd--l.js +0 -1
  612. package/core/built/admin/assets/use-setting-group-bLKMwoBT.js +0 -1
  613. package/core/built/admin/assets/use-settings-navigation-B-qrriKD.js +0 -1
  614. package/core/built/admin/assets/use-simple-pagination-CNPd6Rf6.js +0 -1
  615. package/core/built/admin/assets/use-staff-users-pRIMIyiW.js +0 -1
  616. package/core/built/admin/assets/use-tinybird-token-KLne235s.js +0 -1
  617. package/core/built/admin/assets/use-unsaved-changes-guard-7-ug0JdH.js +0 -1
  618. package/core/built/admin/assets/use-upgrade-route-Dm_qqKr0.js +0 -1
  619. package/core/built/admin/assets/user-detail-modal-D3KlGYv-.js +0 -1
  620. package/core/built/admin/assets/virtual-list-CZ3RK2Yf.js +0 -1
  621. package/core/built/admin/assets/web-ClEJsCAj.js +0 -2
  622. package/core/built/admin/assets/web-X9rdnrtq.js +0 -1
  623. package/core/built/admin/assets/zapier-modal-DfVhV17j.js +0 -1
  624. /package/core/built/admin/assets/{chunk.901.4ccc639821020230bcca.js.LICENSE.txt → chunk.972.4b8c97f93d66db15e751.js.LICENSE.txt} +0 -0
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.getPublicKeyInfo = getPublicKeyInfo;
40
+ const node_crypto_1 = __importDefault(require("node:crypto"));
41
+ const errors = __importStar(require("@tryghost/errors"));
42
+ // Parsing a PEM and thumbprinting it costs real CPU, so results are shared
43
+ // across every consumer of the same key. Keyed by digest so the cache never
44
+ // holds another reference to private key material.
45
+ const cache = new Map();
46
+ async function parse(privateKeyPem) {
47
+ // jose 6 is ESM-only. tsc emits this as `require('jose')` under module: commonjs,
48
+ // which resolves via Node's require(esm) - available on every Node in `engines`.
49
+ const { calculateJwkThumbprint } = await Promise.resolve().then(() => __importStar(require('jose')));
50
+ // Node handles both PKCS#1 and PKCS#8 PEMs, and exports public fields only.
51
+ const publicKey = node_crypto_1.default.createPublicKey(node_crypto_1.default.createPrivateKey(privateKeyPem));
52
+ const { kty, n, e } = publicKey.export({ format: 'jwk' });
53
+ if (kty !== 'RSA' || !n || !e) {
54
+ throw new errors.IncorrectUsageError({
55
+ message: 'Expected an RSA private key',
56
+ });
57
+ }
58
+ const jwk = { kty, n, e };
59
+ return { kid: await calculateJwkThumbprint(jwk, 'sha256'), jwk };
60
+ }
61
+ /**
62
+ * Public JWK and `kid` for a PEM-encoded RSA private key. Never returns private
63
+ * parameters.
64
+ */
65
+ function getPublicKeyInfo(privateKeyPem) {
66
+ const digest = node_crypto_1.default.createHash('sha256').update(privateKeyPem).digest('hex');
67
+ let info = cache.get(digest);
68
+ if (!info) {
69
+ info = parse(privateKeyPem).catch((err) => {
70
+ // Don't pin a failure forever - a later caller should retry.
71
+ cache.delete(digest);
72
+ throw err;
73
+ });
74
+ cache.set(digest, info);
75
+ }
76
+ return info;
77
+ }
@@ -7,6 +7,7 @@ const tpl = require('@tryghost/tpl');
7
7
  const errors = require('@tryghost/errors');
8
8
  const security = require('@tryghost/security');
9
9
  const { validatePassword } = require('../lib/validate-password');
10
+ const { generatePassword } = require('../lib/generate-password');
10
11
  const permissions = require('../services/permissions');
11
12
  const urlUtils = require('../../shared/url-utils').default;
12
13
  const { setIsRoles } = require('./role-utils');
@@ -66,8 +67,7 @@ User = ghostBookshelf.Model.extend(
66
67
 
67
68
  defaults: function defaults() {
68
69
  return {
69
- // secretlint-disable-next-line @secretlint/secretlint-rule-pattern
70
- password: security.identifier.uid(50),
70
+ password: generatePassword(''),
71
71
  visibility: 'public',
72
72
  status: 'active',
73
73
  comment_notifications: true,
@@ -208,8 +208,7 @@ User = ghostBookshelf.Model.extend(
208
208
  */
209
209
  lock: function lock(options) {
210
210
  const update = {
211
- // secretlint-disable-next-line @secretlint/secretlint-rule-pattern
212
- password: security.identifier.uid(50),
211
+ password: generatePassword(this.get('email') || ''),
213
212
  };
214
213
  if (this.get('status') !== 'inactive') {
215
214
  update.status = 'locked';
@@ -306,8 +305,8 @@ User = ghostBookshelf.Model.extend(
306
305
  }
307
306
 
308
307
  if (options.importing) {
309
- // always set password to a random uid when importing
310
- this.set('password', security.identifier.uid(50));
308
+ // generate a random password when importing
309
+ this.set('password', generatePassword(this.get('email') || ''));
311
310
 
312
311
  // lock users so they have to follow the password reset flow
313
312
  if (this.get('status') !== 'inactive') {
@@ -1037,10 +1036,13 @@ User = ghostBookshelf.Model.extend(
1037
1036
  }),
1038
1037
  );
1039
1038
  }
1040
- } else if (roleId !== contextRoleId) {
1039
+ } else if (roleId !== contextRoleId || editedUserId !== context.user) {
1041
1040
  // CASE: you are trying to change a role, but you are not owner
1042
- // @NOTE: your role is not the same than the role you try to change (!)
1043
- // e.g. admin can assign admin role to a user, but not owner
1041
+ // @NOTE: assigning any role to *another* user must always go through
1042
+ // the assign check, including your own role. Otherwise an Editor could
1043
+ // promote an Author to Editor, which the role hierarchy disallows.
1044
+ // The only case that skips the check is a self-edit that leaves your
1045
+ // own role untouched, e.g. a profile update that echoes back `roles`.
1044
1046
 
1045
1047
  return permissions
1046
1048
  .canThis(context)
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.baseClasses = void 0;
3
+ exports.baseClassPackages = exports.baseClasses = void 0;
4
4
  const ghost_storage_base_1 = require("ghost-storage-base");
5
5
  const adapter_base_scheduling_1 = require("@tryghost/adapter-base-scheduling");
6
6
  const adapter_base_sso_1 = require("@tryghost/adapter-base-sso");
@@ -10,8 +10,7 @@ const adapter_base_route_settings_1 = require("@tryghost/adapter-base-route-sett
10
10
  const adapter_base_jobs_1 = require("@tryghost/adapter-base-jobs");
11
11
  /**
12
12
  * The base class every adapter of a given type must extend. Also read by
13
- * bin/validate-adapters.js, which checks adapter implementations at build time -
14
- * keep this the only place the mapping is declared.
13
+ * bin/validate-adapters.js, so keep this the only place the mapping is declared.
15
14
  */
16
15
  exports.baseClasses = {
17
16
  storage: ghost_storage_base_1.StorageBase,
@@ -22,3 +21,22 @@ exports.baseClasses = {
22
21
  'route-settings': adapter_base_route_settings_1.RouteSettingsStoreBase,
23
22
  jobs: adapter_base_jobs_1.JobsBackendBase,
24
23
  };
24
+ /**
25
+ * The package each base class above is imported from. An adapter that installs
26
+ * one of these itself gets a second copy of the base class - a different function
27
+ * object, so `instanceof` fails and Ghost falls back to comparing class names.
28
+ * bin/validate-adapters.js fails a build on such a duplicate, where a duplicate
29
+ * of any other package is only reported.
30
+ *
31
+ * Keyed by adapter type so `satisfies` demands an entry per type in
32
+ * `baseClasses`; a unit test keeps the names matching the imports above.
33
+ */
34
+ exports.baseClassPackages = {
35
+ storage: 'ghost-storage-base',
36
+ scheduling: '@tryghost/adapter-base-scheduling',
37
+ sso: '@tryghost/adapter-base-sso',
38
+ cache: '@tryghost/adapter-base-cache',
39
+ redirects: '@tryghost/adapter-base-redirects',
40
+ 'route-settings': '@tryghost/adapter-base-route-settings',
41
+ jobs: '@tryghost/adapter-base-jobs',
42
+ };
@@ -18,16 +18,22 @@ exports.getAutomatedEmailRecipientsByMailgunIds = getAutomatedEmailRecipientsByM
18
18
  exports.trackEmailDeliveredAndOpened = trackEmailDeliveredAndOpened;
19
19
  exports.trackEmailClicked = trackEmailClicked;
20
20
  const errors_1 = __importDefault(require("@tryghost/errors"));
21
+ const logging_1 = __importDefault(require("@tryghost/logging"));
21
22
  const tpl_1 = __importDefault(require("@tryghost/tpl"));
22
23
  const bson_objectid_1 = __importDefault(require("bson-objectid"));
23
24
  const zod_1 = require("zod");
24
25
  const database_automations_repository_1 = require("./database-automations-repository");
25
26
  const fake_wait_hours_multiplier_1 = require("./fake-wait-hours-multiplier");
27
+ const tinybird_automation_stats_1 = require("./tinybird-automation-stats");
26
28
  const start_automations_poll_event_1 = require("./events/start-automations-poll-event");
27
29
  const { knex } = require('../../data/db');
28
30
  const domainEvents = require('@tryghost/domain-events');
29
31
  const labs = require('../../../shared/labs');
30
32
  const config = require('../../../shared/config');
33
+ const settingsCache = require('../../../shared/settings-cache');
34
+ const requestExternal = require('../../lib/request-external');
35
+ const TinybirdServiceWrapper = require('../tinybird');
36
+ const { create: createTinybirdClient } = require('../stats/utils/tinybird');
31
37
  const lexicalLib = require('../../lib/lexical');
32
38
  const MAX_AUTOMATION_ACTIONS = 20;
33
39
  const messages = {
@@ -77,8 +83,47 @@ const repository = (0, database_automations_repository_1.createDatabaseAutomatio
77
83
  knex,
78
84
  fakeWaitHoursMultiplier: (0, fake_wait_hours_multiplier_1.parseFakeWaitHoursMultiplier)(config.get('automations:fakeWaitHoursMultiplier')),
79
85
  });
86
+ function getTinybirdClient() {
87
+ if (!labs.isSet('automationsTinybirdSync') || !config.get('tinybird:stats')) {
88
+ return null;
89
+ }
90
+ try {
91
+ const tinybirdService = TinybirdServiceWrapper.instance;
92
+ if (!tinybirdService?.getToken()?.token) {
93
+ return null;
94
+ }
95
+ return createTinybirdClient({
96
+ config,
97
+ // Fall back to MySQL after the first failed attempt.
98
+ request: requestExternal.extend({ retry: { limit: 0 } }),
99
+ settingsCache,
100
+ tinybirdService,
101
+ });
102
+ }
103
+ catch (error) {
104
+ logging_1.default.error('Error preparing Tinybird automation stats client:', error);
105
+ return null;
106
+ }
107
+ }
80
108
  async function browse() {
81
- return await repository.browse({ includeStats: true });
109
+ const tinybirdClient = getTinybirdClient();
110
+ if (!tinybirdClient) {
111
+ return await repository.browse({ includeStats: true });
112
+ }
113
+ const [browseResult, stats] = await Promise.all([
114
+ repository.browse({ includeStats: false }),
115
+ (0, tinybird_automation_stats_1.fetchAutomationStats)(tinybirdClient),
116
+ ]);
117
+ if (stats === null) {
118
+ return await repository.browse({ includeStats: true });
119
+ }
120
+ return {
121
+ ...browseResult,
122
+ data: browseResult.data.map((automation) => ({
123
+ ...automation,
124
+ stats: stats.get(automation.id) ?? { ...tinybird_automation_stats_1.EMPTY_AUTOMATION_STATS },
125
+ })),
126
+ };
82
127
  }
83
128
  async function read(automationId) {
84
129
  const automation = await repository.getById(automationId);
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.EMPTY_AUTOMATION_STATS = void 0;
7
+ exports.fetchAutomationStats = fetchAutomationStats;
8
+ const logging_1 = __importDefault(require("@tryghost/logging"));
9
+ const zod_1 = require("zod");
10
+ exports.EMPTY_AUTOMATION_STATS = {
11
+ last_run_created_at: null,
12
+ total_run_count: 0,
13
+ in_progress_run_count: 0,
14
+ };
15
+ const runCountSchema = zod_1.z
16
+ .union([zod_1.z.number(), zod_1.z.string().regex(/^\d+$/)])
17
+ .pipe(zod_1.z.coerce.number().int().nonnegative());
18
+ const statsRowSchema = zod_1.z.object({
19
+ automation_id: zod_1.z.string(),
20
+ last_run_created_at: zod_1.z.iso
21
+ .datetime()
22
+ .transform((value) => new Date(value))
23
+ .nullable(),
24
+ total_run_count: runCountSchema,
25
+ in_progress_run_count: runCountSchema,
26
+ });
27
+ async function fetchAutomationStats(client) {
28
+ let rows;
29
+ try {
30
+ // Override the traffic analytics version: this pipe has no version suffix.
31
+ rows = await client.fetch('api_automation_browse_stats', { version: '' });
32
+ }
33
+ catch (error) {
34
+ logging_1.default.error('Error fetching Tinybird automation stats:', error);
35
+ return null;
36
+ }
37
+ if (rows === null) {
38
+ return null;
39
+ }
40
+ const parsed = zod_1.z.array(statsRowSchema).safeParse(rows);
41
+ if (!parsed.success) {
42
+ logging_1.default.error({
43
+ system: { event: 'automations.stats.invalid_tinybird_response' },
44
+ issues: parsed.error.issues,
45
+ }, 'Unexpected response from the Tinybird automation stats pipe');
46
+ return null;
47
+ }
48
+ return new Map(parsed.data.map((row) => [
49
+ row.automation_id,
50
+ {
51
+ last_run_created_at: row.last_run_created_at,
52
+ total_run_count: row.total_run_count,
53
+ in_progress_run_count: row.in_progress_run_count,
54
+ },
55
+ ]));
56
+ }
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PostMediaInliner = exports.MediaInliningFailure = void 0;
4
4
  exports.isBlockedMediaUrl = isBlockedMediaUrl;
5
- const cheerio = require('cheerio');
5
+ const cheerio = require('cheerio/slim');
6
6
  class MediaInliningFailure extends Error {
7
7
  failures;
8
8
  constructor(failures) {
@@ -75,7 +75,7 @@ class EmailAnalyticsServiceWrapper {
75
75
  }
76
76
  return result;
77
77
  }
78
- _logJobCompletion(jobType, fetchResult, totalDurationMs) {
78
+ _logJobCompletion(jobType, fetchResult, totalDurationMs, lagSeconds = null) {
79
79
  const config = this.#getConfig();
80
80
  const { eventCount, apiPollingTimeMs, processingTimeMs, aggregationTimeMs, emailAggregationTimeMs, memberAggregationTimeMs, result, } = fetchResult;
81
81
  if (eventCount === 0) {
@@ -89,6 +89,7 @@ class EmailAnalyticsServiceWrapper {
89
89
  const logMessage = [
90
90
  `[Background Job] ${this.#backgroundJobName} processed ${jobType} | ${this.#logPrefix}`,
91
91
  `${eventCount} events in ${(totalDurationMs / 1000).toFixed(1)}s (${throughput.toFixed(2)} events/s)`,
92
+ ...(lagSeconds === null ? [] : [`Lag: ${(lagSeconds / 60).toFixed(1)}m`]),
92
93
  `Mode: ${batchMode}`,
93
94
  `Timings: API ${(apiPollingTimeMs / 1000).toFixed(1)}s (${apiPercent}%) / Processing ${(processingTimeMs / 1000).toFixed(1)}s (${processingPercent}%) / Aggregation ${(aggregationTimeMs / 1000).toFixed(1)}s (${aggregationPercent}%) [Email ${(emailAggregationTimeMs / 1000).toFixed(1)}s / Member ${(memberAggregationTimeMs / 1000).toFixed(1)}s]`,
94
95
  `Events: opened=${result.opened} delivered=${result.delivered} failed=${result.permanentFailed + result.temporaryFailed} unprocessable=${result.unprocessable}`,
@@ -100,6 +101,7 @@ class EmailAnalyticsServiceWrapper {
100
101
  task: jobType,
101
102
  event_count: eventCount,
102
103
  duration_ms: totalDurationMs,
104
+ ...(lagSeconds === null ? {} : { lag_seconds: lagSeconds }),
103
105
  },
104
106
  }, logMessage);
105
107
  // We're only concerned with open throughput as this is displayed to users and is most sensitive to being up to date
@@ -124,46 +126,30 @@ class EmailAnalyticsServiceWrapper {
124
126
  }
125
127
  }
126
128
  }
127
- async fetchLatestOpenedEvents({ maxEvents = Infinity, } = {}) {
128
- const config = this.#getConfig();
129
- const beginTimestamp = await this.service.getLastOpenedEventTimestamp();
130
- const lagMinutes = (Date.now() - beginTimestamp.getTime()) / 60000;
131
- const lagThreshold = config.get('emailAnalytics:openedJobLagWarningMinutes');
132
- // NOTE: We only update the begin timestamp when we process events, so there's cases where we can have a false positive
133
- // - Ghost or Mailgun outages
134
- // - Lack of actual email activity
135
- if (lagThreshold && lagMinutes > lagThreshold) {
136
- logging_1.default.warn(`${this.#logPrefix} Opened events processing is ${lagMinutes.toFixed(1)} minutes behind (threshold: ${lagThreshold})`);
137
- }
129
+ async #fetchAndLog(jobType, fetch, lagPipeline) {
138
130
  const fetchStartedAt = Date.now();
139
- const fetchResult = await this.service.fetchLatestOpenedEvents({ maxEvents });
131
+ const fetchResult = await fetch();
140
132
  const totalDuration = Date.now() - fetchStartedAt;
141
- this._logJobCompletion('latest-opened', fetchResult, totalDuration);
133
+ // Lag is read after the fetch so a clean run counts as caught up
134
+ const lagSeconds = lagPipeline ? this.service.getStatus()[lagPipeline].lagSeconds : null;
135
+ this._logJobCompletion(jobType, fetchResult, totalDuration, lagSeconds);
142
136
  return fetchResult.eventCount;
143
137
  }
138
+ async fetchLatestOpenedEvents({ maxEvents = Infinity, } = {}) {
139
+ return this.#fetchAndLog('latest-opened', () => this.service.fetchLatestOpenedEvents({ maxEvents }), 'latestOpened');
140
+ }
144
141
  async fetchLatestNonOpenedEvents({ maxEvents = Infinity, } = {}) {
145
- const fetchStartedAt = Date.now();
146
- const fetchResult = await this.service.fetchLatestNonOpenedEvents({ maxEvents });
147
- const totalDuration = Date.now() - fetchStartedAt;
148
- this._logJobCompletion('latest', fetchResult, totalDuration);
149
- return fetchResult.eventCount;
142
+ return this.#fetchAndLog('latest', () => this.service.fetchLatestNonOpenedEvents({ maxEvents }), 'latest');
150
143
  }
151
144
  async fetchMissing({ maxEvents = Infinity } = {}) {
152
- const fetchStartedAt = Date.now();
153
- const fetchResult = await this.service.fetchMissing({ maxEvents });
154
- const totalDuration = Date.now() - fetchStartedAt;
155
- this._logJobCompletion('missing', fetchResult, totalDuration);
156
- return fetchResult.eventCount;
145
+ // The missing-events sweep trails the delivery pipeline by design, so it has no lag of its own
146
+ return this.#fetchAndLog('missing', () => this.service.fetchMissing({ maxEvents }));
157
147
  }
158
148
  async fetchScheduled({ maxEvents }) {
159
149
  if (maxEvents < 300) {
160
150
  return 0;
161
151
  }
162
- const fetchStartedAt = Date.now();
163
- const fetchResult = await this.service.fetchScheduled({ maxEvents });
164
- const totalDuration = Date.now() - fetchStartedAt;
165
- this._logJobCompletion('scheduled', fetchResult, totalDuration);
166
- return fetchResult.eventCount;
152
+ return this.#fetchAndLog('scheduled', () => this.service.fetchScheduled({ maxEvents }));
167
153
  }
168
154
  async startFetch() {
169
155
  const startedAt = Date.now();
@@ -65,11 +65,18 @@ class EmailAnalyticsService {
65
65
  this.queries.setJobMetadata(this.#jobNames.scheduled, null);
66
66
  }
67
67
  getStatus() {
68
+ const now = Date.now();
69
+ const withLag = (data) => Object.assign(data, {
70
+ fetchedThrough: data.fetchedThrough ?? null,
71
+ lagSeconds: data.fetchedThrough
72
+ ? Math.max(0, Math.floor((now - data.fetchedThrough.getTime()) / 1000))
73
+ : null,
74
+ });
68
75
  return {
69
- latest: this.#fetchLatestNonOpenedData,
70
- missing: this.#fetchMissingData,
76
+ latest: withLag(this.#fetchLatestNonOpenedData),
77
+ missing: withLag(this.#fetchMissingData),
71
78
  scheduled: this.#fetchScheduledData,
72
- latestOpened: this.#fetchLatestOpenedData,
79
+ latestOpened: withLag(this.#fetchLatestOpenedData),
73
80
  };
74
81
  }
75
82
  /**
@@ -363,6 +370,7 @@ class EmailAnalyticsService {
363
370
  });
364
371
  }
365
372
  };
373
+ let fetchedThrough;
366
374
  try {
367
375
  const fetchResult = await this.#fetchEvents({
368
376
  batchHandler: processBatch,
@@ -371,6 +379,11 @@ class EmailAnalyticsService {
371
379
  maxEvents,
372
380
  events: eventTypes,
373
381
  });
382
+ // A void result means fetching was skipped (for example, Mailgun is not configured).
383
+ // Empty successful windows still establish progress through their requested end.
384
+ if (fetchResult) {
385
+ fetchedThrough = fetchResult.safeCursor ?? end;
386
+ }
374
387
  if (fetchResult?.safeCursor &&
375
388
  (!fetchData.lastEventTimestamp || fetchResult.safeCursor < fetchData.lastEventTimestamp)) {
376
389
  fetchData.lastEventTimestamp = fetchResult.safeCursor;
@@ -425,6 +438,9 @@ class EmailAnalyticsService {
425
438
  if (error) {
426
439
  throw error;
427
440
  }
441
+ if (fetchedThrough) {
442
+ fetchData.fetchedThrough = fetchedThrough;
443
+ }
428
444
  return {
429
445
  eventCount,
430
446
  apiPollingTimeMs,
@@ -50,8 +50,13 @@ const init = ({ automationsApi, config, db, domainEvents, emailSuppressionList,
50
50
  prometheusClient,
51
51
  });
52
52
  const newsletterMailgunTags = ['bulk-email'];
53
- if (config.get('bulkEmail:mailgun:tag')) {
54
- newsletterMailgunTags.push(config.get('bulkEmail:mailgun:tag'));
53
+ const automationMailgunTags = [constants_1.AUTOMATION_EMAIL_TAG];
54
+ const giftMailgunTags = [constants_2.GIFT_DELIVERY_EMAIL_TAG];
55
+ const mailgunTagFromConfig = config.get('bulkEmail:mailgun:tag');
56
+ if (mailgunTagFromConfig) {
57
+ newsletterMailgunTags.push(mailgunTagFromConfig);
58
+ automationMailgunTags.push(mailgunTagFromConfig);
59
+ giftMailgunTags.push(mailgunTagFromConfig);
55
60
  }
56
61
  prometheusClient?.registerCounter({
57
62
  name: newsletter_email_analytics_batch_processor_1.AGGREGATE_MEMBER_STATS_METRIC_NAME,
@@ -91,7 +96,7 @@ const init = ({ automationsApi, config, db, domainEvents, emailSuppressionList,
91
96
  domainEvents,
92
97
  event: start_automation_email_analytics_job_event_1.StartAutomationEmailAnalyticsJobEvent,
93
98
  queries,
94
- mailgunTags: [constants_1.AUTOMATION_EMAIL_TAG],
99
+ mailgunTags: automationMailgunTags,
95
100
  jobNames: {
96
101
  latestNonOpened: 'email-analytics-automation-latest-others',
97
102
  missing: 'email-analytics-automation-missing',
@@ -116,7 +121,7 @@ const init = ({ automationsApi, config, db, domainEvents, emailSuppressionList,
116
121
  domainEvents,
117
122
  event: start_gift_email_analytics_job_event_1.StartGiftEmailAnalyticsJobEvent,
118
123
  queries,
119
- mailgunTags: [constants_2.GIFT_DELIVERY_EMAIL_TAG],
124
+ mailgunTags: giftMailgunTags,
120
125
  jobNames: {
121
126
  latestNonOpened: 'email-analytics-gifts-latest-others',
122
127
  missing: 'email-analytics-gifts-missing',
@@ -1,4 +1,4 @@
1
- const cheerio = require('cheerio');
1
+ const cheerio = require('cheerio/slim');
2
2
  const juice = require('juice');
3
3
  const htmlToPlaintext = require('@tryghost/html-to-plaintext');
4
4
 
@@ -12,7 +12,12 @@ const finalizeHtml = (html) => {
12
12
  $('figcaption').addClass('kg-card-figcaption');
13
13
  html = $.html();
14
14
 
15
- const juicedHtml = juice(html, { inlinePseudoElements: true, removeStyleTags: true });
15
+ // resolveCSSVariables crashes on nameless declarations in user-authored style attributes
16
+ const juicedHtml = juice(html, {
17
+ inlinePseudoElements: true,
18
+ removeStyleTags: true,
19
+ resolveCSSVariables: false,
20
+ });
16
21
 
17
22
  // Many email clients, like Outlook and Yahoo, [lack support for <figure>
18
23
  // and <figcaption>][0]. To work around this, change the tags to <div>s.
@@ -25,6 +25,9 @@ failed email.
25
25
  The rough ETA measures recent recipient throughput, including work completed by
26
26
  concurrent workers. It stays `null` until enough timing samples are available in
27
27
  the current phase and attempt, so short sends may finish without showing an ETA.
28
+ The rate uses the last minute of completions, including the interval crossing
29
+ the window boundary. Early estimates use the available history. Sparse sends
30
+ retain at least two measured intervals.
28
31
  Progress counts update independently of the estimate.
29
32
 
30
33
  The ETA is always `null` for failed emails and `0` once no work remains in the
@@ -192,7 +192,7 @@ function escapeRegExp(string) {
192
192
  * @return {ReturnType<typeof cheerio.load>}
193
193
  */
194
194
  function cheerioLoad(html) {
195
- const cheerio = require('cheerio');
195
+ const cheerio = require('cheerio/slim');
196
196
  return cheerio.load(html);
197
197
  }
198
198
 
@@ -709,7 +709,12 @@ class EmailRenderer {
709
709
 
710
710
  // Juice HTML (inline CSS)
711
711
  const juice = require('juice');
712
- html = juice(html, { inlinePseudoElements: true, removeStyleTags: true });
712
+ // resolveCSSVariables crashes on nameless declarations in user-authored style attributes
713
+ html = juice(html, {
714
+ inlinePseudoElements: true,
715
+ removeStyleTags: true,
716
+ resolveCSSVariables: false,
717
+ });
713
718
 
714
719
  // happens after inlining of CSS so we can change element types without worrying about styling
715
720
  $ = cheerioLoad(html);
@@ -44,7 +44,7 @@ class EmailServiceWrapper {
44
44
  const limitService = require('../limits');
45
45
  const labs = require('../../../shared/labs');
46
46
  const emailAddressService = require('../email-address');
47
- const i18nLib = require('@tryghost/i18n');
47
+ const i18nLib = require('@tryghost/i18n').default;
48
48
  const lexicalLib = require('../../lib/lexical');
49
49
  const urlUtils = require('../../../shared/url-utils').default;
50
50
  const memberAttribution = require('../member-attribution');