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
@@ -29,12 +29,15 @@ const messages = {
29
29
  retryEmailNotFailed: 'Only failed emails can be retried',
30
30
  };
31
31
 
32
- // Resume scanner won't pick up `submitting` rows older than this. Rows beyond the cutoff
33
- // are flipped to `failed` on first boot so they surface in admin UI for operator review
34
- // rather than being silently resumed (and sending stale newsletters to current members).
32
+ // Resume scanner won't pick up `pending` or `submitting` rows older than this. Rows beyond
33
+ // the cutoff are flipped to `failed` on first boot so they surface in admin UI for operator
34
+ // review rather than being silently resumed (and sending stale newsletters to current members).
35
35
  // Override via `bulkEmail:resumeMaxAgeMs` in config.
36
36
  const DEFAULT_RESUME_MAX_AGE_MS = 24 * 60 * 60 * 1000;
37
37
 
38
+ // Non-terminal email statuses, both of which the boot scanner recovers.
39
+ const RESUMABLE_EMAIL_STATUSES = ['pending', 'submitting'];
40
+
38
41
  class EmailService {
39
42
  #batchSendingService;
40
43
  #sendingService;
@@ -223,28 +226,31 @@ class EmailService {
223
226
  }
224
227
 
225
228
  /**
226
- * Boot-time scanner: resumes newsletter emails left in `submitting` after a
227
- * previous container's interrupted send. Iterates sequentially; one failure
228
- * does not skip others. Rows older than the configured max-age are flipped
229
- * to `failed` (not resumed) so stale content does not get sent to current members.
229
+ * Boot-time scanner: recovers newsletter emails a previous container left without work.
230
+ * Two shapes, both resumed through the normal emailJob path:
231
+ * - `submitting` the send was cut off mid-flight.
232
+ * - `pending` dispatch was dropped from the in-memory job queue before the job ever
233
+ * started, so no batch work exists and nothing else will ever pick the row up.
234
+ * Iterates sequentially; one failure does not skip others. Rows older than the configured
235
+ * max-age are flipped to `failed` (not resumed) so stale content does not get sent to
236
+ * current members.
230
237
  */
231
238
  async resumeInterruptedSends() {
232
239
  const maxAgeMs = this.#config?.get?.('bulkEmail:resumeMaxAgeMs') ?? DEFAULT_RESUME_MAX_AGE_MS;
233
240
  const cutoffIso = new Date(Date.now() - maxAgeMs).toISOString();
234
241
 
235
242
  // Stale rows: too old to safely resume. Flip to `failed` so they surface in admin UI
236
- // for operator review instead of being silently left in `submitting` forever.
243
+ // for operator review instead of being silently stuck in their current status forever.
237
244
  const stale = await this.#models.Email.findAll({
238
- filter: `status:submitting+created_at:<'${cutoffIso}'`,
245
+ filter: `status:[${RESUMABLE_EMAIL_STATUSES.join(',')}]+created_at:<'${cutoffIso}'`,
239
246
  });
240
- const staleList = stale.models || stale;
241
- for (const email of staleList) {
247
+ for (const email of stale.models) {
242
248
  try {
243
249
  const locked = await this.#batchSendingService.updateStatusLock(
244
250
  this.#models.Email,
245
251
  email.id,
246
252
  'failed',
247
- ['submitting'],
253
+ [email.get('status')],
248
254
  );
249
255
  if (locked) {
250
256
  logging.warn(
@@ -257,20 +263,19 @@ class EmailService {
257
263
  }
258
264
 
259
265
  // Fresh rows: within the cutoff. Resume through the normal emailJob path.
260
- const emails = await this.#models.Email.findAll({
261
- filter: `status:submitting+created_at:>'${cutoffIso}'`,
266
+ const fresh = await this.#models.Email.findAll({
267
+ filter: `status:[${RESUMABLE_EMAIL_STATUSES.join(',')}]+created_at:>'${cutoffIso}'`,
262
268
  });
263
- const list = emails.models || emails;
264
- if (staleList.length === 0 && list.length === 0) {
269
+ if (stale.models.length === 0 && fresh.models.length === 0) {
265
270
  return;
266
271
  }
267
- if (list.length > 0) {
272
+ if (fresh.models.length > 0) {
268
273
  logging.info(
269
- `Email resume: found ${list.length} email(s) in submitting status within max age (${maxAgeMs}ms)`,
274
+ `Email resume: found ${fresh.models.length} pending or submitting email(s) within max age (${maxAgeMs}ms)`,
270
275
  );
271
276
  }
272
277
 
273
- for (const email of list) {
278
+ for (const email of fresh.models) {
274
279
  try {
275
280
  await this.#resumeOneEmail(email);
276
281
  } catch (e) {
@@ -279,23 +284,24 @@ class EmailService {
279
284
  }
280
285
 
281
286
  logging.info(
282
- `Email resume scan complete: ${staleList.length} stale email(s) flipped to failed, ${list.length} fresh email(s) rescheduled`,
287
+ `Email resume scan complete: ${stale.models.length} stale email(s) flipped to failed, ${fresh.models.length} fresh email(s) rescheduled`,
283
288
  );
284
289
  }
285
290
 
286
291
  async #resumeOneEmail(email) {
292
+ const status = email.get('status');
287
293
  const post = await email.getLazyRelation('post');
288
294
  const postStatus = post ? post.get('status') : null;
289
295
  const sendable = postStatus === 'published' || postStatus === 'sent';
290
296
 
291
297
  if (!sendable) {
292
298
  // Parent post was unpublished or deleted while the email was in flight.
293
- // Can't resume — mark the email as failed so it stops showing as "submitting".
299
+ // Can't resume — mark the email as failed so it stops showing as unsent.
294
300
  const locked = await this.#batchSendingService.updateStatusLock(
295
301
  this.#models.Email,
296
302
  email.id,
297
303
  'failed',
298
- ['submitting'],
304
+ [status],
299
305
  );
300
306
  if (locked) {
301
307
  logging.warn(
@@ -305,19 +311,22 @@ class EmailService {
305
311
  return;
306
312
  }
307
313
 
308
- // Flip submitting -> pending so emailJob's status lock (['pending', 'failed']) admits it.
309
- // If updateStatusLock returns undefined, another path raced us — just continue.
310
- const locked = await this.#batchSendingService.updateStatusLock(
311
- this.#models.Email,
312
- email.id,
313
- 'pending',
314
- ['submitting'],
315
- );
316
- if (!locked) {
317
- logging.info(
318
- `Email resume: ${email.id} status changed before lock could be taken — skipping`,
314
+ // `pending` is already what emailJob's status lock (['pending', 'failed']) admits, so
315
+ // only `submitting` needs flipping. If updateStatusLock returns undefined, another path
316
+ // raced us leave it to whoever won.
317
+ if (status === 'submitting') {
318
+ const locked = await this.#batchSendingService.updateStatusLock(
319
+ this.#models.Email,
320
+ email.id,
321
+ 'pending',
322
+ ['submitting'],
319
323
  );
320
- return;
324
+ if (!locked) {
325
+ logging.info(
326
+ `Email resume: ${email.id} status changed before lock could be taken — skipping`,
327
+ );
328
+ return;
329
+ }
321
330
  }
322
331
 
323
332
  // Structured breadcrumb so post-incident timing/batch state is recoverable from logs.
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EmailSendingStatus = exports.SendingStatus = exports.SendingProgress = exports.SendingPhase = void 0;
4
4
  exports.buildSendingStatus = buildSendingStatus;
5
5
  const zod_1 = require("zod");
6
- const ETA_COMPLETION_WINDOW = 20;
6
+ const ETA_WINDOW_MS = 60_000;
7
7
  const ETA_MIN_INTERVALS = 2;
8
8
  exports.SendingPhase = zod_1.z.enum(['preparing', 'submitting']);
9
9
  exports.SendingProgress = zod_1.z.object({
@@ -96,12 +96,18 @@ function estimateSecondsRemaining({ remaining, samples, attemptStartedAt, }) {
96
96
  completions.push({ ...sample });
97
97
  }
98
98
  }
99
- // Limit usable timestamps, not rows: fast sends may finish many batches per timestamp.
100
- const window = completions.slice(-ETA_COMPLETION_WINDOW);
101
99
  // Three distinct timestamps provide two measured intervals for an initial rate.
102
- if (window.length < ETA_MIN_INTERVALS + 1) {
100
+ if (completions.length < ETA_MIN_INTERVALS + 1) {
103
101
  return null;
104
102
  }
103
+ // Include the baseline at or before the last minute so the first interval's
104
+ // recipients have their full elapsed time. Sparse sends still need two intervals.
105
+ const cutoff = completions[completions.length - 1].timestamp - ETA_WINDOW_MS;
106
+ let baseline = completions.length - 1;
107
+ while (baseline > 0 && completions[baseline].timestamp > cutoff) {
108
+ baseline -= 1;
109
+ }
110
+ const window = completions.slice(Math.max(0, Math.min(baseline, completions.length - ETA_MIN_INTERVALS - 1)));
105
111
  // Measure combined throughput across the window, including overlapping workers.
106
112
  // The first completion is only the baseline: its recipients were processed
107
113
  // before the measured time span.
@@ -13,6 +13,7 @@ const gift_date_1 = require("./gift-date");
13
13
  const DEFAULT_ACCENT_COLOR = '#15212A';
14
14
  class GiftEmailService {
15
15
  transactionalMailer;
16
+ config;
16
17
  bulkMailer;
17
18
  settingsCache;
18
19
  urlUtils;
@@ -21,7 +22,8 @@ class GiftEmailService {
21
22
  blogIcon;
22
23
  renderer;
23
24
  t;
24
- constructor({ transactionalMailer, bulkMailer, settingsCache, urlUtils, getFromAddress, getReplyToAddress, blogIcon, t, }) {
25
+ constructor({ config, transactionalMailer, bulkMailer, settingsCache, urlUtils, getFromAddress, getReplyToAddress, blogIcon, t, }) {
26
+ this.config = config;
25
27
  this.transactionalMailer = transactionalMailer;
26
28
  this.bulkMailer = bulkMailer;
27
29
  this.settingsCache = settingsCache;
@@ -205,6 +207,11 @@ class GiftEmailService {
205
207
  buyerName,
206
208
  interpolation: { escapeValue: false },
207
209
  });
210
+ const tags = [constants_1.GIFT_DELIVERY_EMAIL_TAG];
211
+ const mailgunTagFromConfig = this.config.get('bulkEmail:mailgun:tag');
212
+ if (typeof mailgunTagFromConfig === 'string' && mailgunTagFromConfig.length > 0) {
213
+ tags.push(mailgunTagFromConfig);
214
+ }
208
215
  if (!this.bulkMailer.isConfigured()) {
209
216
  await this.transactionalMailer.send({
210
217
  to: recipientEmail,
@@ -214,7 +221,7 @@ class GiftEmailService {
214
221
  from: this.getFromAddress(),
215
222
  replyTo: this.getReplyToAddress(),
216
223
  forceTextContent: true,
217
- tags: [constants_1.GIFT_DELIVERY_EMAIL_TAG],
224
+ tags,
218
225
  disableTracking: true,
219
226
  });
220
227
  return { providerMessageId: null };
@@ -225,7 +232,7 @@ class GiftEmailService {
225
232
  plaintext: text,
226
233
  from: this.getFromAddress(),
227
234
  replyTo: this.getReplyToAddress(),
228
- tags: [constants_1.GIFT_DELIVERY_EMAIL_TAG],
235
+ tags,
229
236
  disable_tracking: true,
230
237
  }, { [recipientEmail]: {} }, []);
231
238
  const providerMessageId = (0, mailgun_message_id_1.getMailgunMessageId)(response) ?? null;
@@ -52,6 +52,7 @@ function init(options) {
52
52
  getStripeApi: () => require('../stripe').api,
53
53
  });
54
54
  const giftEmailService = new gift_email_service_1.GiftEmailService({
55
+ config,
55
56
  transactionalMailer: new GhostMailer(),
56
57
  bulkMailer: new MailgunClient({ config, settings: settingsCache }),
57
58
  settingsCache,
@@ -19,7 +19,7 @@ exports.t = (...args) => {
19
19
  };
20
20
 
21
21
  exports.init = () => {
22
- const i18n = require('@tryghost/i18n');
22
+ const i18n = require('@tryghost/i18n').default;
23
23
  const events = require('../lib/common/events');
24
24
  const settingsCache = require('../../shared/settings-cache');
25
25
 
@@ -13,12 +13,11 @@ module.exports = class IdentityTokenServiceWrapper {
13
13
  const issuer = urlUtils.urlFor('admin', true);
14
14
 
15
15
  const settings = require('../../../shared/settings-cache');
16
- const jose = require('node-jose');
16
+ const { getPublicKeyInfo } = require('../../lib/public-jwk');
17
17
 
18
18
  const privateKey = settings.get('ghost_private_key');
19
- const keyStore = jose.JWK.createKeyStore();
20
- const key = await keyStore.add(privateKey, 'pem');
19
+ const { kid } = await getPublicKeyInfo(privateKey);
21
20
 
22
- IdentityTokenServiceWrapper.instance = new IdentityTokenService(privateKey, issuer, key.kid);
21
+ IdentityTokenServiceWrapper.instance = new IdentityTokenService(privateKey, issuer, kid);
23
22
  }
24
23
  };
@@ -2,7 +2,7 @@ const errors = require('@tryghost/errors');
2
2
  const config = require('../../shared/config');
3
3
  const db = require('../data/db');
4
4
  const logging = require('@tryghost/logging');
5
- const LimitService = require('@tryghost/limit-service');
5
+ const { LimitService } = require('@tryghost/limit-service');
6
6
  let limitService = new LimitService();
7
7
 
8
8
  const init = () => {
@@ -47,6 +47,22 @@ const init = () => {
47
47
  }
48
48
  };
49
49
 
50
+ /**
51
+ * Route guard for a feature a host can switch off, for the routes that exist only to
52
+ * change it. Answers 403 with the host's own wording, which is a different thing to tell a
53
+ * caller than the 404 a labs flag gives: the feature exists, this plan does not include it.
54
+ */
55
+ const requireFeature = (limitName) =>
56
+ async function requireFeatureMw(req, res, next) {
57
+ try {
58
+ await limitService.errorIfWouldGoOverLimit(limitName);
59
+ next();
60
+ } catch (err) {
61
+ next(err);
62
+ }
63
+ };
64
+
50
65
  module.exports = limitService;
51
66
 
52
67
  module.exports.init = init;
68
+ module.exports.requireFeature = requireFeature;
@@ -898,7 +898,7 @@ class MemberWelcomeEmailServiceWrapper {
898
898
  }
899
899
 
900
900
  if (!this.i18n) {
901
- const i18nLib = require('@tryghost/i18n');
901
+ const i18nLib = require('@tryghost/i18n').default;
902
902
  const events = require('../../lib/common/events');
903
903
 
904
904
  this.i18n = i18nLib(settingsCache.get('locale') || 'en', 'ghost');
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.makeImporter = makeImporter;
7
7
  exports.makeExporter = makeExporter;
8
+ const members_metafields_1 = require("../../members-metafields");
8
9
  const importer_1 = __importDefault(require("./import/importer"));
9
10
  const reader_1 = __importDefault(require("./import/reader"));
10
11
  const spool_1 = require("./import/spool");
@@ -57,8 +58,8 @@ function makeImporter(deps) {
57
58
  }),
58
59
  };
59
60
  const metafields = {
60
- activeFields: async () => deps.metafields.definitions.browse(),
61
- planWrite: (values) => deps.metafields.values.planWrite(values),
61
+ activeFields: async () => deps.metafields.definitions.browse({}, members_metafields_1.INTERNAL),
62
+ planWrite: (values) => deps.metafields.values.planWrite(values, members_metafields_1.INTERNAL),
62
63
  // Every value the import writes came out of the file, whichever column carried it.
63
64
  // An import has no id to give until runs are tracked, so it names its kind only.
64
65
  applyWrite: (memberId, plan, executor) => deps.metafields.values.applyWrite(memberId, plan, {
@@ -121,8 +122,8 @@ function makeExporter({ definitions, values, }) {
121
122
  metafields: {
122
123
  // Boot builds the definitions and values services before this one, so they
123
124
  // are always present -- no not-initialised state to guard.
124
- activeDefinitions: async () => definitions.browse(),
125
- valuesForMembers: (memberIds) => values.getValuesForMembers(memberIds),
125
+ activeDefinitions: async () => definitions.browse({}, members_metafields_1.INTERNAL),
126
+ valuesForMembers: (memberIds) => values.getValuesForMembers(memberIds, members_metafields_1.INTERNAL),
126
127
  },
127
128
  });
128
129
  return (options = {}) => exporter.export(options);
@@ -1097,7 +1097,7 @@ module.exports = class RouterController {
1097
1097
  labels: req.body.labels,
1098
1098
  name: req.body.name,
1099
1099
  reqIp: req.ip ?? undefined,
1100
- newsletters: await this._validateNewsletters(req.body?.newsletters ?? []),
1100
+ newsletters: await this._validateNewsletters(req.body?.newsletters),
1101
1101
  attribution: await this._memberAttributionService.getAttribution(req.body.urlHistory),
1102
1102
  ...(giftToken ? { giftToken } : {}),
1103
1103
  };
@@ -1149,10 +1149,15 @@ module.exports = class RouterController {
1149
1149
  * @returns {Promise<object[] | undefined>} The validated newsletters
1150
1150
  */
1151
1151
  async _validateNewsletters(requestedNewsletters) {
1152
- if (!requestedNewsletters || requestedNewsletters.length === 0) {
1152
+ if (!requestedNewsletters || !Array.isArray(requestedNewsletters)) {
1153
1153
  return undefined;
1154
1154
  }
1155
1155
 
1156
+ // An explicit empty list means "no newsletters", not "the defaults"
1157
+ if (requestedNewsletters.length === 0) {
1158
+ return [];
1159
+ }
1160
+
1156
1161
  if (requestedNewsletters.some((newsletter) => !newsletter.name)) {
1157
1162
  return undefined;
1158
1163
  }
@@ -7,7 +7,8 @@ const messages = {
7
7
  };
8
8
 
9
9
  /**
10
- * @typedef {import('node-jose').JWK[]} JWKS
10
+ * @typedef {import('../../../../lib/public-jwk').PublicRsaJwk & {kid: string}} PublicJWK
11
+ * @typedef {{keys: PublicJWK[]}} JWKS
11
12
  */
12
13
 
13
14
  /**
@@ -428,6 +428,8 @@ module.exports = class EventRepository {
428
428
  delete json.postAttribution?.mobiledoc;
429
429
  delete json.postAttribution?.lexical;
430
430
  delete json.postAttribution?.plaintext;
431
+ delete json.postAttribution?.auto_excerpt;
432
+ delete json.postAttribution?.reading_time;
431
433
  const createdWithStatus = json.signupStatusEvent?.to_status ?? null;
432
434
  delete json.signupStatusEvent;
433
435
  return {
@@ -488,6 +490,8 @@ module.exports = class EventRepository {
488
490
  delete json.postAttribution?.mobiledoc;
489
491
  delete json.postAttribution?.lexical;
490
492
  delete json.postAttribution?.plaintext;
493
+ delete json.postAttribution?.auto_excerpt;
494
+ delete json.postAttribution?.reading_time;
491
495
  return {
492
496
  type: 'donation_event',
493
497
  data: {
@@ -95,16 +95,17 @@ module.exports = class MemberBREADService {
95
95
  * size or a delivery address. Their values live in their own table, so they are fetched
96
96
  * here rather than loaded alongside the member.
97
97
  *
98
- * Returns null when the site has defined no fields, which tells the caller to leave the
99
- * `metafields` key off the member payload rather than send an empty object: a key added to
100
- * an API response cannot be withdrawn without breaking whoever started reading it, and
101
- * most sites have never defined a field, so those sites keep the payload they had before
102
- * this feature existed.
98
+ * Returns null when this audience has no field to be told about, which tells the caller to
99
+ * leave the `metafields` key off the member payload rather than send an empty object: a key
100
+ * added to an API response cannot be withdrawn without breaking whoever started reading it,
101
+ * and most sites have never defined a field, so those sites keep the payload they had
102
+ * before this feature existed.
103
103
  * @param {string[]} memberIds
104
+ * @param {import('../../../members-metafields').Audience} audience
104
105
  * @returns {Promise<Map<string, Record<string, unknown>> | null>}
105
106
  */
106
107
  async fetchMetafieldValues(memberIds, audience) {
107
- if (!(await this.metafieldDefinitions.hasAnyActive())) {
108
+ if (!(await this.metafieldDefinitions.hasAnyReadable(audience))) {
108
109
  return null;
109
110
  }
110
111
 
@@ -385,15 +386,17 @@ module.exports = class MemberBREADService {
385
386
  /**
386
387
  * @param {object} data
387
388
  * @param {object} [options]
388
- * @param {import('../../../members-metafields').Audience | null} [options.metafieldsFor]
389
+ * @param {import('../../../members-metafields').Audience | null} options.metafieldsFor
389
390
  * Who the extra fields a publisher defined are being read for, or null to leave them
390
391
  * off entirely. Null is not the same as "nobody may see them": it means this caller
391
392
  * never shows them, so fetching them is two database queries whose results are thrown
392
393
  * away. Ghost identifies a signed-in reader on every page view of a themed site
393
394
  * through this method, and that caller renders a member through a fixed list of
394
395
  * fields which has never included these.
396
+ *
397
+ * Defaults to null, so a caller that does not ask gets none of them.
395
398
  */
396
- async read(data, { metafieldsFor = ADMIN, ...options } = {}) {
399
+ async read(data, { metafieldsFor = null, ...options } = {}) {
397
400
  const defaultWithRelated = [
398
401
  'labels',
399
402
  'stripeSubscriptions',
@@ -562,7 +565,7 @@ module.exports = class MemberBREADService {
562
565
  await this.memberRepository.setComplimentarySubscription(model, sharedOptions);
563
566
  }
564
567
 
565
- return this.read({ id: model.id }, options);
568
+ return this.read({ id: model.id }, { ...options, metafieldsFor: ADMIN });
566
569
  }
567
570
 
568
571
  async edit(data, options) {
@@ -678,7 +681,7 @@ module.exports = class MemberBREADService {
678
681
  }
679
682
  }
680
683
 
681
- return this.read({ id: model.id }, options);
684
+ return this.read({ id: model.id }, { ...options, metafieldsFor: ADMIN });
682
685
  }
683
686
 
684
687
  /**
@@ -710,7 +713,7 @@ module.exports = class MemberBREADService {
710
713
  );
711
714
  }
712
715
 
713
- return this.read({ id: memberId });
716
+ return this.read({ id: memberId }, { metafieldsFor: ADMIN });
714
717
  }
715
718
 
716
719
  /**
@@ -732,7 +735,7 @@ module.exports = class MemberBREADService {
732
735
 
733
736
  await this.memberRepository.saveCommenting(memberId, updated, 'commenting_enabled', context);
734
737
 
735
- return this.read({ id: memberId });
738
+ return this.read({ id: memberId }, { metafieldsFor: ADMIN });
736
739
  }
737
740
 
738
741
  async logout(options) {
@@ -1,6 +1,6 @@
1
- const jose = require('node-jose');
2
1
  const jwt = require('jsonwebtoken');
3
2
  const crypto = require('crypto');
3
+ const { getPublicKeyInfo } = require('../../../../lib/public-jwk');
4
4
 
5
5
  // A token's `scope` declares its purpose. Only identity tokens may act as a
6
6
  // member; entitlement tokens are read-only and handed to integrations.
@@ -9,24 +9,23 @@ const ENTITLEMENT_TOKEN_SCOPE = 'members:entitlements:read';
9
9
 
10
10
  module.exports = class TokenService {
11
11
  constructor({ privateKey, publicKey, issuer }) {
12
- this._keyStore = jose.JWK.createKeyStore();
13
- this._keyStoreReady = this._keyStore.add(privateKey, 'pem');
12
+ this._keyReady = getPublicKeyInfo(privateKey);
14
13
  this._privateKey = privateKey;
15
14
  this._publicKey = publicKey;
16
15
  this._issuer = issuer;
17
16
  }
18
17
 
19
18
  async encodeIdentityToken({ sub }) {
20
- const jwk = await this._keyStoreReady;
19
+ const { kid } = await this._keyReady;
21
20
  return jwt.sign(
22
21
  {
23
22
  sub,
24
- kid: jwk.kid,
23
+ kid,
25
24
  scope: IDENTITY_TOKEN_SCOPE,
26
25
  },
27
26
  this._privateKey,
28
27
  {
29
- keyid: jwk.kid,
28
+ keyid: kid,
30
29
  algorithm: 'RS512',
31
30
  audience: this._issuer,
32
31
  expiresIn: '10m',
@@ -36,12 +35,12 @@ module.exports = class TokenService {
36
35
  }
37
36
 
38
37
  async encodeEntitlementToken({ sub, memberUuid, paid, activeTierIds = [] }) {
39
- const jwk = await this._keyStoreReady;
38
+ const { kid } = await this._keyReady;
40
39
 
41
40
  return jwt.sign(
42
41
  {
43
42
  sub,
44
- kid: jwk.kid,
43
+ kid,
45
44
  scope: ENTITLEMENT_TOKEN_SCOPE,
46
45
  member_uuid: memberUuid,
47
46
  paid,
@@ -50,7 +49,7 @@ module.exports = class TokenService {
50
49
  },
51
50
  this._privateKey,
52
51
  {
53
- keyid: jwk.kid,
52
+ keyid: kid,
54
53
  algorithm: 'RS512',
55
54
  audience: this._issuer,
56
55
  expiresIn: '5m',
@@ -73,7 +72,7 @@ module.exports = class TokenService {
73
72
  * @returns {Promise<jwt.JwtPayload>}
74
73
  */
75
74
  async decodeToken(token) {
76
- await this._keyStoreReady;
75
+ await this._keyReady;
77
76
 
78
77
  const result = jwt.verify(token, this._publicKey, {
79
78
  algorithms: ['RS512'],
@@ -92,7 +91,7 @@ module.exports = class TokenService {
92
91
  }
93
92
 
94
93
  async getPublicKeys() {
95
- await this._keyStoreReady;
96
- return this._keyStore.toJSON();
94
+ const { kid, jwk } = await this._keyReady;
95
+ return { keys: [{ kty: jwk.kty, kid, n: jwk.n, e: jwk.e }] };
97
96
  }
98
97
  };
@@ -12,6 +12,7 @@ const onHeaders = require('on-headers');
12
12
  const tiersService = require('../tiers/service');
13
13
  const config = require('../../../shared/config');
14
14
  const settingsHelpers = require('../settings-helpers');
15
+ const { timingSafeStringEqual } = require('../../../shared/timing-safe-string-equal');
15
16
 
16
17
  const messages = {
17
18
  missingUuid: 'Missing uuid.',
@@ -237,13 +238,19 @@ const authMemberByUuid = async function authMemberByUuid(req, res, next) {
237
238
  .createHmac('sha256', settingsHelpers.getMembersValidationKey())
238
239
  .update(uuid)
239
240
  .digest('hex');
240
- if (memberHmac !== key) {
241
+ if (!timingSafeStringEqual(memberHmac, key)) {
241
242
  throw new errors.UnauthorizedError({
242
243
  message: tpl(messages.invalidKey),
243
244
  });
244
245
  }
245
246
 
246
- const member = await membersService.api.memberBREADService.read({ uuid });
247
+ // Nothing reached through this middleware renders a member's extra fields, so
248
+ // they are not fetched. It authenticates by a signed link rather than a session,
249
+ // which makes anything loaded here readable without being signed in.
250
+ const member = await membersService.api.memberBREADService.read(
251
+ { uuid },
252
+ { metafieldsFor: null },
253
+ );
247
254
  if (!member) {
248
255
  throw new errors.UnauthorizedError({
249
256
  message: tpl(messages.invalidUuid),
@@ -1,4 +1,5 @@
1
1
  const crypto = require('crypto');
2
+ const { timingSafeStringEqual } = require('../../../shared/timing-safe-string-equal');
2
3
 
3
4
  class RequestIntegrityTokenProvider {
4
5
  #themeSecret;
@@ -45,7 +46,7 @@ class RequestIntegrityTokenProvider {
45
46
  hmac.update(`${timestamp.toString()}:${nonce}`);
46
47
  const expectedHmac = hmac.digest('hex');
47
48
 
48
- if (expectedHmac !== hmacDigest) {
49
+ if (!timingSafeStringEqual(expectedHmac, hmacDigest)) {
49
50
  // HMAC mismatch
50
51
  return false;
51
52
  }