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
@@ -1,28 +1,39 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.INTERNAL = exports.MEMBERS = exports.ADMIN = void 0;
4
- exports.readableFields = readableFields;
3
+ exports.INTERNAL = exports.MEMBERS = exports.ADMIN = exports.MemberAccessSchema = exports.MEMBER_ACCESS = void 0;
4
+ exports.readableLevels = readableLevels;
5
5
  exports.canWrite = canWrite;
6
+ const metafield_types_1 = require("@tryghost/metafield-types");
7
+ Object.defineProperty(exports, "MEMBER_ACCESS", { enumerable: true, get: function () { return metafield_types_1.MEMBER_ACCESS; } });
8
+ Object.defineProperty(exports, "MemberAccessSchema", { enumerable: true, get: function () { return metafield_types_1.MemberAccessSchema; } });
9
+ const EVERY_LEVEL = [...metafield_types_1.MEMBER_ACCESS_LEVELS];
6
10
  exports.ADMIN = { entry: 'admin' };
7
11
  exports.MEMBERS = { entry: 'members' };
8
12
  exports.INTERNAL = { entry: 'internal' };
9
- /**
10
- * Which of the site's fields this audience may see.
11
- *
12
- * Every field, whichever door they came through. Written as a function rather than
13
- * left unwritten so that when a publisher can mark a field as staff only, one
14
- * function changes and every caller is already asking.
15
- */
16
- function readableFields(_audience, fields) {
17
- return fields;
13
+ // Every audience is spelled out with the levels it may read, staff included, because
14
+ // reads narrow on whatever this returns and an audience with no entry gets an empty
15
+ // list, which matches no field. Giving staff a way to skip the check instead would
16
+ // invert that: an unrecognised audience would then match everything.
17
+ const READABLE = {
18
+ admin: EVERY_LEVEL,
19
+ internal: EVERY_LEVEL,
20
+ members: [metafield_types_1.MEMBER_ACCESS.read, metafield_types_1.MEMBER_ACCESS.write],
21
+ };
22
+ const WRITABLE = {
23
+ admin: EVERY_LEVEL,
24
+ internal: EVERY_LEVEL,
25
+ members: [metafield_types_1.MEMBER_ACCESS.write],
26
+ };
27
+ // `Object.hasOwn` rather than a plain lookup: an entry naming a property every object
28
+ // inherits (`__proto__`, `constructor`, `toString`) would otherwise return that
29
+ // inherited value instead of falling through to the empty list.
30
+ function levelsFor(table, audience) {
31
+ const entry = audience?.entry;
32
+ return entry !== undefined && Object.hasOwn(table, entry) ? table[entry] : [];
18
33
  }
19
- /**
20
- * Whether this audience may write this field.
21
- *
22
- * Also total today. Kept separate from `readableFields` because the asymmetry to
23
- * expect is a field a member may read but not change, which one combined
24
- * permission could not express.
25
- */
26
- function canWrite(_audience, _field) {
27
- return true;
34
+ function readableLevels(audience) {
35
+ return levelsFor(READABLE, audience);
36
+ }
37
+ function canWrite(audience, field) {
38
+ return levelsFor(WRITABLE, audience).includes(field.memberAccess);
28
39
  }
@@ -31,6 +31,7 @@ const COMMANDS = {
31
31
  create: 'added',
32
32
  rename: 'edited',
33
33
  reorder: 'edited',
34
+ changeAccess: 'edited',
34
35
  archive: 'archived',
35
36
  restore: 'restored',
36
37
  delete: 'deleted',
@@ -9,6 +9,13 @@ const models_1 = require("./models");
9
9
  exports.metafieldCodec = zod_1.z.codec(schema_1.DbMetafield, models_1.Metafield, {
10
10
  // DbMetafield validates `type` as the field-type enum, so the decoded row
11
11
  // already carries a FieldType and camelKeys preserves it — no cast needed.
12
- decode: (row) => ({ ...(0, case_keys_1.camelKeys)(row), namespace: identity_1.CUSTOM_NAMESPACE }),
13
- encode: ({ namespace: _namespace, ...field }) => (0, case_keys_1.snakeKeys)(field),
12
+ decode: ({ member_access: memberAccess, ...row }) => ({
13
+ ...(0, case_keys_1.camelKeys)(row),
14
+ namespace: identity_1.CUSTOM_NAMESPACE,
15
+ access: { member: memberAccess },
16
+ }),
17
+ encode: ({ namespace: _namespace, access, ...field }) => ({
18
+ ...(0, case_keys_1.snakeKeys)(field),
19
+ member_access: access.member,
20
+ }),
14
21
  });
@@ -47,10 +47,12 @@ const FieldName = zod_1.z
47
47
  .trim()
48
48
  .min(1, { message: 'Custom field name is required.' })
49
49
  .max(MAX_NAME_LENGTH, { message: 'Custom field name is too long.' });
50
- // The backend mints the key from the name, so create takes just a name and type.
50
+ const FieldAccess = zod_1.z.object({ member: access_1.MemberAccessSchema });
51
+ // No key: the backend mints it from the name.
51
52
  const AddFieldInput = zod_1.z.object({
52
53
  name: FieldName,
53
54
  type: metafield_types_1.FieldTypeSchema,
55
+ access: FieldAccess.optional(),
54
56
  });
55
57
  // A bound on the work one request can ask for, separate from how many definitions
56
58
  // a site may hold in total. Every definition in a batch costs several queries
@@ -73,11 +75,12 @@ const ReorderInput = zod_1.z
73
75
  key: zod_1.z.string().min(1, { message: 'Every custom field in the order needs a key.' }),
74
76
  }))
75
77
  .min(1, { message: 'The order must name every custom field.' });
76
- // Name and status are mutable. `key` and `type` are accepted so the immutability
77
- // rules can reject a change loudly; they are never persisted.
78
+ // Name, status and access are mutable. `key` and `type` are accepted so the
79
+ // immutability rules can reject a change loudly; they are never persisted.
78
80
  const EditFieldInput = zod_1.z.object({
79
81
  name: FieldName.optional(),
80
82
  status: schema_1.FieldStatusSchema.optional(),
83
+ access: FieldAccess.optional(),
81
84
  key: zod_1.z.string().optional(),
82
85
  type: metafield_types_1.FieldTypeSchema.optional(),
83
86
  });
@@ -95,8 +98,8 @@ class MetafieldDefinitionsService {
95
98
  // restart. Where the number comes from is the caller's business.
96
99
  this.getMaxDefinitions = getMaxDefinitions;
97
100
  }
98
- async hasAnyActive() {
99
- const [field] = await this.list((0, queries_1.activeFields)(this.knex).limit(1));
101
+ async hasAnyReadable(audience) {
102
+ const [field] = await this.list((0, queries_1.definitions)(this.knex, { audience, status: queries_1.ACTIVE_ONLY, limit: 1 }));
100
103
  return Boolean(field);
101
104
  }
102
105
  /**
@@ -106,34 +109,35 @@ class MetafieldDefinitionsService {
106
109
  isStored(namespace) {
107
110
  return namespace === identity_1.CUSTOM_NAMESPACE;
108
111
  }
109
- async browse(options = {}, audience = access_1.ADMIN) {
112
+ async browse(options, audience) {
110
113
  if (options.namespace !== undefined && !this.isStored(options.namespace)) {
111
114
  return [];
112
115
  }
113
- // Archived fields are hidden by default: most surfaces (member details, the
114
- // filter picker, the importer) only ever want active fields. A caller-
115
- // supplied `filter` can widen that — Settings pulls active and archived
116
- // together in one request (`filter=status:[active,archived]`).
117
- //
118
116
  // Whichever set comes back, it comes back in the publisher's order: filtering
119
117
  // narrows the list, it never reorders it.
120
- const query = options.filter
121
- ? applyFilter(this.knex(TABLE), options.filter)
122
- : (0, queries_1.activeFields)(this.knex);
123
- return (0, access_1.readableFields)(audience, await this.list(query));
118
+ const { filter } = options;
119
+ if (filter) {
120
+ // A filter naming `status` decides the statuses itself, which is how Settings
121
+ // pulls active and archived together in one request
122
+ // (`filter=status:[active,archived]`). One that does not gets the same active-only
123
+ // scope as an unfiltered read.
124
+ const parsed = parseFilter(filter);
125
+ return this.list((0, queries_1.definitions)(this.knex, {
126
+ audience,
127
+ status: filterReferencesStatus(parsed) ? queries_1.ANY_STATUS : queries_1.ACTIVE_ONLY,
128
+ filter: (query) => knexify(query, parsed, { tableName: TABLE }),
129
+ }));
130
+ }
131
+ return this.list((0, queries_1.definitions)(this.knex, { audience, status: queries_1.ACTIVE_ONLY }));
124
132
  }
125
- /**
126
- * Decode a definition query into the domain, in the publisher's order.
127
- *
128
- * Typed off `activeFields` so the builder keeps the table's row type: every caller
129
- * hands over a query against the definitions table, whatever it has narrowed.
130
- */
131
133
  async list(query) {
132
134
  const rows = await (0, queries_1.inFieldOrder)(query).select('*');
133
135
  return rows.map((row) => zod_1.z.decode(codec_1.metafieldCodec, row));
134
136
  }
135
- async read(namespace, key) {
136
- const [field] = this.isStored(namespace) ? await this.list((0, queries_1.fieldByKey)(this.knex, key)) : [];
137
+ async read(namespace, key, audience) {
138
+ const [field] = this.isStored(namespace)
139
+ ? await this.list((0, queries_1.definitions)(this.knex, { audience, status: queries_1.ANY_STATUS, key }))
140
+ : [];
137
141
  if (!field) {
138
142
  throw new errors_1.default.NotFoundError({ message: 'Custom field not found.' });
139
143
  }
@@ -191,6 +195,7 @@ class MetafieldDefinitionsService {
191
195
  key,
192
196
  name: field.name,
193
197
  type: field.type,
198
+ memberAccess: field.access?.member ?? access_1.MEMBER_ACCESS.none,
194
199
  sortOrder: firstSortOrder + index,
195
200
  });
196
201
  keys.push(key);
@@ -236,6 +241,7 @@ class MetafieldDefinitionsService {
236
241
  key: wanted.key,
237
242
  name: wanted.name,
238
243
  type: wanted.type,
244
+ memberAccess: wanted.access.member,
239
245
  sortOrder: await this.nextSortOrder(db),
240
246
  });
241
247
  const [created] = await this.readMany(db, [wanted.key]);
@@ -263,6 +269,7 @@ class MetafieldDefinitionsService {
263
269
  key: field.key,
264
270
  name: field.name,
265
271
  type: field.type,
272
+ member_access: field.memberAccess,
266
273
  sort_order: field.sortOrder,
267
274
  created_at: new Date(),
268
275
  });
@@ -351,7 +358,8 @@ class MetafieldDefinitionsService {
351
358
  .where('key', key)
352
359
  .update({ sort_order: ranks.get(key) });
353
360
  }
354
- return this.list(trx(TABLE));
361
+ // An order covers the whole list, archived definitions included.
362
+ return this.list((0, queries_1.definitions)(trx, { audience: access_1.ADMIN, status: queries_1.ANY_STATUS }));
355
363
  });
356
364
  await this.recordAction({
357
365
  context,
@@ -460,7 +468,7 @@ class MetafieldDefinitionsService {
460
468
  });
461
469
  }
462
470
  const patch = parsed.data;
463
- const existing = await this.read(identity_1.CUSTOM_NAMESPACE, key);
471
+ const existing = await this.read(identity_1.CUSTOM_NAMESPACE, key, access_1.ADMIN);
464
472
  // Key and type are immutable after creation: values are addressed by key
465
473
  // and interpreted by type, so changing either would silently orphan or
466
474
  // corrupt stored values. Reject a differing value rather than ignore it.
@@ -500,6 +508,22 @@ class MetafieldDefinitionsService {
500
508
  details: { primary_name: patch.name, key, previous_name: existing.name },
501
509
  });
502
510
  }
511
+ if (patch.access !== undefined && patch.access.member !== existing.access.member) {
512
+ await this.knex(TABLE)
513
+ .where('key', key)
514
+ .update({ member_access: patch.access.member, updated_at: new Date() });
515
+ await this.recordAction({
516
+ context,
517
+ verb: 'changeAccess',
518
+ subject: existing.id,
519
+ details: {
520
+ primary_name: patch.name ?? existing.name,
521
+ key,
522
+ member_access: patch.access.member,
523
+ previous_member_access: existing.access.member,
524
+ },
525
+ });
526
+ }
503
527
  // A status change is the archive/restore transition. Only write (and log)
504
528
  // when it actually flips, so re-sending the current status is a no-op.
505
529
  if (patch.status !== undefined && patch.status !== existing.status) {
@@ -514,7 +538,7 @@ class MetafieldDefinitionsService {
514
538
  details: { primary_name: patch.name ?? existing.name, key },
515
539
  });
516
540
  }
517
- return this.read(identity_1.CUSTOM_NAMESPACE, key);
541
+ return this.read(identity_1.CUSTOM_NAMESPACE, key, access_1.ADMIN);
518
542
  }
519
543
  /**
520
544
  * Permanently delete a field and every member value attached to it (the FK
@@ -597,12 +621,11 @@ function isUniqueConstraintViolation(error) {
597
621
  const code = error?.code;
598
622
  return code === 'ER_DUP_ENTRY' || code === 'SQLITE_CONSTRAINT';
599
623
  }
600
- // Apply a caller-supplied NQL filter to the definition query. A malformed filter
601
- // is a client error (400), not a 500. The active-only default is preserved unless
602
- // the filter itself constrains status, so a filter on another field (e.g. type)
603
- // can never surface archived fields — this is the invariant queries.ts centralises,
604
- // held here as the per-field default override Bookshelf's filter plugin does.
605
- function applyFilter(query, filter) {
624
+ // Parse a caller-supplied NQL filter, without applying it. A malformed filter is a
625
+ // client error (400), not a 500. Whether the result widens the statuses is decided by
626
+ // the caller, which reads it with `filterReferencesStatus` and says so when building
627
+ // the query; nothing here narrows anything.
628
+ function parseFilter(filter) {
606
629
  let mongoQuery;
607
630
  try {
608
631
  mongoQuery = nql(filter).toJSON();
@@ -623,20 +646,7 @@ function applyFilter(query, filter) {
623
646
  property: 'filter',
624
647
  });
625
648
  }
626
- try {
627
- knexify(query, mongoQuery, { tableName: TABLE });
628
- }
629
- catch (err) {
630
- throw new errors_1.default.BadRequestError({
631
- message: 'Could not parse the filter parameter.',
632
- property: 'filter',
633
- err: err,
634
- });
635
- }
636
- if (!filterReferencesStatus(mongoQuery)) {
637
- query.where('status', schema_1.FIELD_STATUS.active);
638
- }
639
- return query;
649
+ return mongoQuery;
640
650
  }
641
651
  // Whether an NQL-parsed filter constrains `status` anywhere, including inside the
642
652
  // $and/$or/$nor combinators — so a status filter at any nesting counts as the
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.bindings = exports.values = exports.definitions = exports.readableFields = exports.canWrite = exports.MEMBERS = exports.INTERNAL = exports.ADMIN = exports.actingContext = void 0;
3
+ exports.bindings = exports.values = exports.definitions = exports.canWrite = exports.MEMBER_ACCESS = exports.MEMBERS = exports.INTERNAL = exports.ADMIN = exports.actingContext = void 0;
4
4
  exports.init = init;
5
5
  const definitions_service_1 = require("./definitions-service");
6
6
  const values_service_1 = require("./values-service");
@@ -16,8 +16,8 @@ var access_1 = require("./access");
16
16
  Object.defineProperty(exports, "ADMIN", { enumerable: true, get: function () { return access_1.ADMIN; } });
17
17
  Object.defineProperty(exports, "INTERNAL", { enumerable: true, get: function () { return access_1.INTERNAL; } });
18
18
  Object.defineProperty(exports, "MEMBERS", { enumerable: true, get: function () { return access_1.MEMBERS; } });
19
+ Object.defineProperty(exports, "MEMBER_ACCESS", { enumerable: true, get: function () { return access_1.MEMBER_ACCESS; } });
19
20
  Object.defineProperty(exports, "canWrite", { enumerable: true, get: function () { return access_1.canWrite; } });
20
- Object.defineProperty(exports, "readableFields", { enumerable: true, get: function () { return access_1.readableFields; } });
21
21
  function init() {
22
22
  // The three are constructed together below, so checking all of them keeps the "all or
23
23
  // none" invariant explicit rather than trusting one to stand in for the rest.
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Metafield = void 0;
4
4
  const zod_1 = require("zod");
5
5
  const metafield_types_1 = require("@tryghost/metafield-types");
6
+ const access_1 = require("./access");
6
7
  const schema_1 = require("./schema");
7
8
  exports.Metafield = zod_1.z.object({
8
9
  id: zod_1.z.string(),
@@ -11,6 +12,7 @@ exports.Metafield = zod_1.z.object({
11
12
  name: zod_1.z.string(),
12
13
  type: metafield_types_1.FieldTypeSchema,
13
14
  status: schema_1.FieldStatusSchema,
15
+ access: zod_1.z.object({ member: access_1.MemberAccessSchema }),
14
16
  createdAt: zod_1.z.date(),
15
17
  updatedAt: zod_1.z.date().nullable(),
16
18
  });
@@ -1,20 +1,48 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.activeFields = activeFields;
4
- exports.fieldByKey = fieldByKey;
3
+ exports.ANY_STATUS = exports.ACTIVE_ONLY = void 0;
4
+ exports.readableBy = readableBy;
5
+ exports.definitions = definitions;
5
6
  exports.inFieldOrder = inFieldOrder;
7
+ const access_1 = require("./access");
6
8
  const schema_1 = require("./schema");
7
9
  const FIELDS_TABLE = 'members_metafields';
8
- // Archived fields must stay out of every read and write, and nothing in the database
9
- // enforces that — no constraint stops a value row referencing an archived field. A query
10
- // that forgets the filter is a silent bug, so the filter lives in one place.
11
- /** Takes the executor so the same query runs standalone or inside a write's transaction. */
12
- function activeFields(db) {
13
- return db(FIELDS_TABLE).where('status', schema_1.FIELD_STATUS.active);
10
+ // Nothing in the database keeps an archived or hidden field out of a read: no
11
+ // constraint stops a value row referencing one. Both filters are therefore applied in
12
+ // code, and a query that forgets either is a silent bug.
13
+ function readableBy(query, audience) {
14
+ query.whereIn(`${FIELDS_TABLE}.member_access`, (0, access_1.readableLevels)(audience));
15
+ return query;
16
+ }
17
+ /**
18
+ * Whether a read includes definitions the publisher has archived.
19
+ *
20
+ * A member is never offered an archived field. Staff managing the list are always
21
+ * shown one, since an archived field is still theirs to rename, restore or delete.
22
+ */
23
+ exports.ACTIVE_ONLY = 'active-only';
24
+ exports.ANY_STATUS = 'any-status';
25
+ // Unannotated so the builder keeps the row type knex derives from the table
26
+ // registration; naming a type here would both lose that and make the alias below
27
+ // refer to itself.
28
+ function metafieldsTable(db) {
29
+ return db(FIELDS_TABLE);
14
30
  }
15
- /** One field by key, as the same kind of query the rest of this reads through. */
16
- function fieldByKey(db, key) {
17
- return db(FIELDS_TABLE).where(`${FIELDS_TABLE}.key`, key);
31
+ function definitions(db, scope) {
32
+ let query = metafieldsTable(db);
33
+ if (scope.filter) {
34
+ query = scope.filter(query);
35
+ }
36
+ if (scope.key !== undefined) {
37
+ query = query.where(`${FIELDS_TABLE}.key`, scope.key);
38
+ }
39
+ if (scope.status === exports.ACTIVE_ONLY) {
40
+ query = query.where(`${FIELDS_TABLE}.status`, schema_1.FIELD_STATUS.active);
41
+ }
42
+ if (scope.limit !== undefined) {
43
+ query = query.limit(scope.limit);
44
+ }
45
+ return readableBy(query, scope.audience);
18
46
  }
19
47
  /**
20
48
  * The publisher's order, applied to every read of the list. Here for the same reason the
@@ -4,6 +4,7 @@ exports.DbBoundField = exports.DbMetafieldBinding = exports.DbMetafieldLeaf = ex
4
4
  const zod_1 = require("zod");
5
5
  const metafield_types_1 = require("@tryghost/metafield-types");
6
6
  const date_1 = require("../../lib/db-types/date");
7
+ const access_1 = require("./access");
7
8
  // `archived` is soft: the field drops out of the values path but stays in the definition
8
9
  // list so it can be renamed, restored or deleted. Mirrors schema.js's `isIn` on the
9
10
  // column, which is static config and cannot import this.
@@ -17,6 +18,7 @@ exports.DbMetafield = zod_1.z.object({
17
18
  name: zod_1.z.string(),
18
19
  type: metafield_types_1.FieldTypeSchema,
19
20
  status: exports.FieldStatusSchema,
21
+ member_access: access_1.MemberAccessSchema,
20
22
  created_at: date_1.DbDate,
21
23
  updated_at: date_1.DbDate.nullable(),
22
24
  });
@@ -10,6 +10,7 @@ const MetafieldResource = zod_1.z.object({
10
10
  name: zod_1.z.string(),
11
11
  type: zod_1.z.string(),
12
12
  status: zod_1.z.string(),
13
+ access: zod_1.z.object({ member: zod_1.z.string() }),
13
14
  created_at: zod_1.z.date(),
14
15
  updated_at: zod_1.z.date().nullable(),
15
16
  });
@@ -47,7 +47,11 @@ class MetafieldValuesService {
47
47
  this.knex = knex;
48
48
  this.getMaxDefinitions = getMaxDefinitions;
49
49
  }
50
- async activeFieldsByIdentity(identities) {
50
+ // The query is scoped to the audience, so a field they may not see is absent from
51
+ // the map and the caller reports it as unknown. Looking up unscoped and rejecting
52
+ // afterwards would let a member tell a hidden field from an undefined one by the
53
+ // reply they got.
54
+ async allowedFieldsByIdentity(identities, audience) {
51
55
  const keys = identities
52
56
  .map((identity) => (0, identity_1.parseIdentity)(identity))
53
57
  .filter((parsed) => parsed !== null && parsed.namespace === identity_1.CUSTOM_NAMESPACE)
@@ -55,12 +59,19 @@ class MetafieldValuesService {
55
59
  if (keys.length === 0) {
56
60
  return new Map();
57
61
  }
58
- const fields = await (0, queries_1.activeFields)(this.knex)
62
+ const fields = await (0, queries_1.definitions)(this.knex, { audience, status: queries_1.ACTIVE_ONLY })
59
63
  .whereIn('key', keys)
60
- .select('id', 'key', 'name', 'type');
64
+ .select('id', 'key', 'name', 'type', 'member_access');
61
65
  return new Map(fields.map((field) => [
62
66
  (0, identity_1.formatIdentity)({ namespace: identity_1.CUSTOM_NAMESPACE, key: field.key, partPath: null }),
63
- { ...field, namespace: identity_1.CUSTOM_NAMESPACE },
67
+ {
68
+ id: field.id,
69
+ key: field.key,
70
+ name: field.name,
71
+ type: field.type,
72
+ namespace: identity_1.CUSTOM_NAMESPACE,
73
+ memberAccess: field.member_access,
74
+ },
64
75
  ]));
65
76
  }
66
77
  async getValuesForMembers(memberIds, audience) {
@@ -70,8 +81,7 @@ class MetafieldValuesService {
70
81
  // Not ordered by field: these rows become an object keyed by field, and an object
71
82
  // cannot carry an order. `path` is ordered so composite parts assemble the same
72
83
  // way every time.
73
- const rows = await this.knex(VALUES_TABLE)
74
- .join(FIELDS_TABLE, `${VALUES_TABLE}.metafield_key`, `${FIELDS_TABLE}.key`)
84
+ const rows = await (0, queries_1.readableBy)(this.knex(VALUES_TABLE).join(FIELDS_TABLE, `${VALUES_TABLE}.metafield_key`, `${FIELDS_TABLE}.key`), audience)
75
85
  .whereIn(`${VALUES_TABLE}.member_id`, memberIds)
76
86
  .where(`${FIELDS_TABLE}.status`, schema_1.FIELD_STATUS.active)
77
87
  .orderBy(`${VALUES_TABLE}.path`, 'asc')
@@ -90,10 +100,7 @@ class MetafieldValuesService {
90
100
  }, 'Skipping an unreadable metafield value');
91
101
  }
92
102
  }
93
- // Narrowed before assembly, not after: a composite is one value spread across
94
- // several rows, and dropping some of its parts later would hand back half an
95
- // address rather than no address.
96
- const flat = (0, storage_1.valuesFromLeaves)((0, access_1.readableFields)(audience, leaves));
103
+ const flat = (0, storage_1.valuesFromLeaves)(leaves);
97
104
  return new Map(memberIds.map((memberId) => [memberId, { [identity_1.CUSTOM_NAMESPACE]: flat.get(memberId) ?? {} }]));
98
105
  }
99
106
  parseValues(input) {
@@ -157,7 +164,7 @@ class MetafieldValuesService {
157
164
  property: identity_1.QUALIFIER,
158
165
  });
159
166
  }
160
- const byIdentity = await this.activeFieldsByIdentity(identities);
167
+ const byIdentity = await this.allowedFieldsByIdentity(identities, audience);
161
168
  const writes = [];
162
169
  for (const [identity, raw] of Object.entries(values)) {
163
170
  const field = byIdentity.get(identity);
@@ -167,6 +174,8 @@ class MetafieldValuesService {
167
174
  property: wireProperty(identity),
168
175
  });
169
176
  }
177
+ // A different refusal from the unknown-field one above: this audience can
178
+ // already see the field, so naming it discloses nothing.
170
179
  if (!(0, access_1.canWrite)(audience, field)) {
171
180
  throw new errors_1.default.ValidationError({
172
181
  message: `Cannot set custom field: ${identity}`,
@@ -63,7 +63,7 @@ module.exports = class MentionDiscoveryService {
63
63
  return null;
64
64
  }
65
65
 
66
- const cheerio = require('cheerio');
66
+ const cheerio = require('cheerio/slim');
67
67
  const $ = cheerio.load(response.body);
68
68
 
69
69
  // must be first <link> OR <a> element with rel=webmention
@@ -242,7 +242,7 @@ module.exports = class MentionSendingService {
242
242
  * @returns {URL[]}
243
243
  */
244
244
  getLinks(html) {
245
- const cheerio = require('cheerio');
245
+ const cheerio = require('cheerio/slim');
246
246
  const $ = cheerio.load(html);
247
247
  const urls = [];
248
248
  const siteUrl = this.siteUrl;
@@ -61,7 +61,7 @@ module.exports = class Mention {
61
61
 
62
62
  if (contentType.includes('text/html')) {
63
63
  try {
64
- const cheerio = require('cheerio');
64
+ const cheerio = require('cheerio/slim');
65
65
  const $ = cheerio.load(html);
66
66
  const hasTargetUrl =
67
67
  $(
@@ -42,6 +42,7 @@ const messages = {
42
42
  unableToFetchOembed: 'Unable to fetch requested embed.',
43
43
  unauthorized: 'URL contains a private resource.',
44
44
  unconvertibleSvg: 'SVG image is too large or compressed to convert.',
45
+ unsupportedImage: 'Image is not a supported file type.',
45
46
  };
46
47
 
47
48
  const SVG_RASTER_SIZE = 256;
@@ -68,6 +69,16 @@ const shouldRasterize = (buffer, ext) => {
68
69
  return head.startsWith('<') && /<svg[\s:>]/i.test(head);
69
70
  };
70
71
 
72
+ let fileTypeFromBuffer;
73
+
74
+ const detectFileType = async (buffer) => {
75
+ if (!fileTypeFromBuffer) {
76
+ ({ fileTypeFromBuffer } = await import('file-type'));
77
+ }
78
+
79
+ return fileTypeFromBuffer(buffer);
80
+ };
81
+
71
82
  /**
72
83
  * @param {string} url
73
84
  * @returns {{url: string, provider: boolean}}
@@ -234,6 +245,20 @@ class OEmbedService {
234
245
  });
235
246
 
236
247
  ext = '.png';
248
+ } else {
249
+ // The URL's extension is attacker-controlled and decides the
250
+ // Content-Type the stored file is later served with, so name the
251
+ // file after its contents and hold it to the same allowlist as image
252
+ // uploads. `file-type` never reports SVG, which is handled above.
253
+ const fileType = await detectFileType(imageBuffer);
254
+ ext = fileType ? `.${fileType.ext}` : '';
255
+
256
+ if (!this.config.get('uploads').images.extensions.includes(ext)) {
257
+ throw new errors.ValidationError({
258
+ message: tpl(messages.unsupportedImage),
259
+ context: imageUrl,
260
+ });
261
+ }
237
262
  }
238
263
 
239
264
  const uniqueFileName = `${name}-${crypto.randomUUID()}${ext}`;
@@ -561,12 +586,12 @@ class OEmbedService {
561
586
  */
562
587
  async fetchOembedData(url, html, cardType) {
563
588
  // Lazy require the library to keep boot quick
564
- const cheerio = require('cheerio');
589
+ const cheerio = require('cheerio/slim');
565
590
 
566
591
  // check for <link rel="alternate" type="application/json+oembed"> element
567
592
  let oembedUrl;
568
593
  try {
569
- oembedUrl = cheerio('link[type="application/json+oembed"]', html).attr('href');
594
+ oembedUrl = cheerio.load(html)('link[type="application/json+oembed"]').attr('href');
570
595
  } catch (e) {
571
596
  return this.unknownProvider(url);
572
597
  }
@@ -622,15 +647,15 @@ class OEmbedService {
622
647
  return;
623
648
  }
624
649
 
625
- // `rich` and `video` responses ship provider-supplied HTML that gets
626
- // stored in the post's Lexical payload and rendered into the admin
627
- // editor preview (via srcdoc) and into public themes (via innerHTML).
628
- // Known providers (YouTube, Twitter, etc.) go through `knownProvider`
629
- // with @extractus/oembed-extractor's allowlist — anything reaching
630
- // here is an arbitrary site's self-declared oEmbed endpoint, which we
631
- // must not trust. Drop the response and let the caller fall back to
632
- // a bookmark card.
633
- if (oembed.type === 'video' || oembed.type === 'rich') {
650
+ // `rich`, `video` and `photo` responses can all ship provider-supplied
651
+ // HTML that gets stored in the post's Lexical payload and rendered
652
+ // into the admin editor preview (via srcdoc) and into public themes
653
+ // and emails (via innerHTML). Known providers (YouTube, Twitter, etc.)
654
+ // go through `knownProvider` with @extractus/oembed-extractor's
655
+ // allowlist — anything reaching here is an arbitrary site's
656
+ // self-declared oEmbed endpoint, which we must not trust. Drop the
657
+ // response and let the caller fall back to a bookmark card.
658
+ if (oembed.type === 'video' || oembed.type === 'rich' || oembed.type === 'photo') {
634
659
  return;
635
660
  }
636
661
 
@@ -16,6 +16,10 @@ const messages = {
16
16
  // retrying a publish that will never happen.
17
17
  const NO_OP = { scheduledResource: null, preScheduledResource: null };
18
18
 
19
+ // Ignore overlapping deliveries for the same resource. The scheduler owns
20
+ // retries if the active publish fails; always release the guard when it settles.
21
+ const inFlight = new Set();
22
+
19
23
  /**
20
24
  * Publishes scheduled resource (a post or a page at the moment of writing)
21
25
  *
@@ -27,6 +31,22 @@ const NO_OP = { scheduledResource: null, preScheduledResource: null };
27
31
  * `scheduledResource: null` when there was nothing to publish yet
28
32
  */
29
33
  exports.publish = async (resourceType, id, force, options) => {
34
+ const key = `${resourceType}:${id}`;
35
+
36
+ if (inFlight.has(key)) {
37
+ return NO_OP;
38
+ }
39
+
40
+ inFlight.add(key);
41
+
42
+ try {
43
+ return await publishNow(resourceType, id, force, options);
44
+ } finally {
45
+ inFlight.delete(key);
46
+ }
47
+ };
48
+
49
+ const publishNow = async (resourceType, id, force, options) => {
30
50
  const publishAPostBySchedulerToleranceInMinutes =
31
51
  config.get('times').publishAPostBySchedulerToleranceInMinutes;
32
52