ghost 6.60.0 → 6.61.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 (399) hide show
  1. package/components/tryghost-adapter-base-scheduling-0.2.3.tgz +0 -0
  2. package/components/tryghost-adapter-base-sso-0.1.3.tgz +0 -0
  3. package/components/tryghost-custom-field-types-0.0.0.tgz +0 -0
  4. package/components/tryghost-kg-default-cards-10.3.5.tgz +0 -0
  5. package/core/boot.js +13 -4
  6. package/core/built/admin/assets/{Combination-gnJO3vIw.js → Combination-5fYEzgbs.js} +1 -1
  7. package/core/built/admin/assets/{PolarAngleAxis-C4qtHy1B.js → PolarAngleAxis-pkMyqz8g.js} +1 -1
  8. package/core/built/admin/assets/{RadialBarChart-Bh09Stsj.js → RadialBarChart-JAKoS4KT.js} +1 -1
  9. package/core/built/admin/assets/{about-BgpmhCuM.js → about-Bve7IJS2.js} +1 -1
  10. package/core/built/admin/assets/{account-migration-8qTEI1i1.js → account-migration-DRhAehfw.js} +1 -1
  11. package/core/built/admin/assets/{action-list-lGzZLHc8.js → action-list-C4v0-du8.js} +1 -1
  12. package/core/built/admin/assets/activitypub/{account-migration-DMHuPnJn.js → account-migration-C-aej4x_.js} +7 -7
  13. package/core/built/admin/assets/activitypub/activitypub.js +3 -4
  14. package/core/built/admin/assets/activitypub/{avatar-DhTo5D1B.js → avatar-DLPL3Abs.js} +59 -68
  15. package/core/built/admin/assets/activitypub/{avatar-flipboard-DnVgbEfa.js → avatar-flipboard-C9iDY-QV.js} +2 -2
  16. package/core/built/admin/assets/activitypub/{bluesky-sharing-BT4zAlW7.js → bluesky-sharing-BXkA5mqV.js} +8 -8
  17. package/core/built/admin/assets/activitypub/{content-formatters-BeDZ-DIa.js → content-formatters-CHcyMFk4.js} +17 -17
  18. package/core/built/admin/assets/activitypub/{copy-8sqxUuNd.js → copy-DIAOQoCZ.js} +2 -2
  19. package/core/built/admin/assets/activitypub/{domain-xQDDu1CS.js → domain-B3ihkPde.js} +8 -8
  20. package/core/built/admin/assets/activitypub/{edit-profile-BXdF_r2G.js → edit-profile-DsZM3rTX.js} +5 -5
  21. package/core/built/admin/assets/activitypub/{explore-CMt7gKlL.js → explore-BodNrZgR.js} +8 -8
  22. package/core/built/admin/assets/activitypub/{feed-Bwqdddp_.js → feed-PwH1iJ84.js} +9 -9
  23. package/core/built/admin/assets/activitypub/{field-4co_8FVg.js → field-D06-kmOJ.js} +3 -3
  24. package/core/built/admin/assets/activitypub/{hash-DwakMs4X.js → hash-Bm3WxYN4.js} +2 -2
  25. package/core/built/admin/assets/activitypub/{inbox-DQ5CwLma.js → inbox-BluD2ucT.js} +16 -16
  26. package/core/built/admin/assets/activitypub/{inbox-ckD4wo_r.js → inbox-d8oJRTf4.js} +2 -2
  27. package/core/built/admin/assets/activitypub/{label-B72sfvEU.js → label-FHSh6ZAw.js} +3 -3
  28. package/core/built/admin/assets/activitypub/layout-Cq4NG0Xr.js +1 -0
  29. package/core/built/admin/assets/activitypub/{moderation-KCCO7L2J.js → moderation-D1Yapsod.js} +9 -9
  30. package/core/built/admin/assets/activitypub/{note-BX_Bz5A0.js → note-C5zjqq5C.js} +8 -8
  31. package/core/built/admin/assets/activitypub/{notifications-BQOYGvRv.js → notifications-B9p8eCHD.js} +9 -9
  32. package/core/built/admin/assets/activitypub/{preferences-6h43G9_q.js → preferences-BCqUdC3v.js} +9 -9
  33. package/core/built/admin/assets/activitypub/{profile-BMN9VVZ2.js → profile-BRCWoFem.js} +178 -178
  34. package/core/built/admin/assets/activitypub/{reply-ZNo04xsO.js → reply-DYK5vVqb.js} +2 -2
  35. package/core/built/admin/assets/activitypub/{routes-3B9mUQ7i.js → routes-BSXT992i.js} +81 -84
  36. package/core/built/admin/assets/activitypub/{separator-D9taVCCa.js → separator-BbQqTm-p.js} +3 -3
  37. package/core/built/admin/assets/activitypub/{settings-71gCm3SO.js → settings-DQDkr06X.js} +6 -6
  38. package/core/built/admin/assets/activitypub/{step-1-BsGGnBuT.js → step-1-B-YfsVeO.js} +5 -5
  39. package/core/built/admin/assets/activitypub/{step-2-teosIS0k.js → step-2-DtPQzlTH.js} +6 -6
  40. package/core/built/admin/assets/activitypub/{step-3-BjD5TokC.js → step-3-D6BFMXL_.js} +10 -10
  41. package/core/built/admin/assets/activitypub/{tabs-Cvwl1wXU.js → tabs-GpNecvfB.js} +6 -6
  42. package/core/built/admin/assets/activitypub/{topic-filter-C3LZJc2X.js → topic-filter-BPDeQQys.js} +3 -3
  43. package/core/built/admin/assets/activitypub/{use-activity-pub-queries-Dp9f0gov.js → use-activity-pub-queries-BoVOxXkV.js} +2 -2
  44. package/core/built/admin/assets/activitypub/{use-navigate-with-base-path-C4RI0sa9.js → use-navigate-with-base-path-Bmk5h4lW.js} +220 -220
  45. package/core/built/admin/assets/activitypub/{use-reply-chain-data-C2oNDMUH.js → use-reply-chain-data-wVBX7swM.js} +5 -5
  46. package/core/built/admin/assets/activitypub/{x-Dxm6pV9X.js → x-DbQZOLiI.js} +2 -2
  47. package/core/built/admin/assets/{add-integration-modal--YpTq3c0.js → add-integration-modal-BC0jExDZ.js} +1 -1
  48. package/core/built/admin/assets/{add-newsletter-modal-C8Ix2hol.js → add-newsletter-modal-DchTkA7l.js} +1 -1
  49. package/core/built/admin/assets/{add-recommendation-modal-CScuNFz4.js → add-recommendation-modal-DMvaJZKp.js} +1 -1
  50. package/core/built/admin/assets/alert-dialog-QhXzdHfc.js +1 -0
  51. package/core/built/admin/assets/{analytics-Cnji45H5.js → analytics-No1DDY3A.js} +1 -1
  52. package/core/built/admin/assets/{announcement-bar-modal-BTHiy1ZO.js → announcement-bar-modal-DM3cYOpo.js} +1 -1
  53. package/core/built/admin/assets/{api-keys-Boy5pLbD.js → api-keys-BLm2NDBh.js} +1 -1
  54. package/core/built/admin/assets/audience-9mwU5TW6.js +1 -0
  55. package/core/built/admin/assets/{automations-BWpRCZ_f.js → automations-DpUNUdcZ.js} +1 -1
  56. package/core/built/admin/assets/{bluesky-sharing-DHOpQxff.js → bluesky-sharing-Cjrv_f62.js} +1 -1
  57. package/core/built/admin/assets/{box-By_EgGtm.js → box-CdfQAP_F.js} +1 -1
  58. package/core/built/admin/assets/{brand-icon-09YqFZjV.js → brand-icon-CrIGOA3Z.js} +1 -1
  59. package/core/built/admin/assets/{breadcrumb-CcFr_ltt.js → breadcrumb-DLiqCyFc.js} +1 -1
  60. package/core/built/admin/assets/{button-BshWPHvn.js → button-B2jcu6bk.js} +1 -1
  61. package/core/built/admin/assets/{card-CiiE7QfM.js → card--VNbfgo3.js} +1 -1
  62. package/core/built/admin/assets/{chart-BnXyfH11.js → chart-BrhA41Zi.js} +1 -1
  63. package/core/built/admin/assets/chart-helpers-Fo3bUL3K.js +1 -0
  64. package/core/built/admin/assets/{checkbox-Dwwr_3Py.js → checkbox-BfKktMph.js} +1 -1
  65. package/core/built/admin/assets/{chunk.524.91ecb33e6afc3bd8949b.js → chunk.524.60ca4692d91c6022042f.js} +4 -4
  66. package/core/built/admin/assets/{chunk.582.512549909741883f960c.js → chunk.582.525c7617c2d9e94c940a.js} +6 -6
  67. package/core/built/admin/assets/{chunk.16.f76a6314082d813d67e0.js → chunk.896.435fe0637944d4a69810.js} +3 -3
  68. package/core/built/admin/assets/{code-editor-view-BwIdPy_k.js → code-editor-view-CYVu4EW6.js} +1 -1
  69. package/core/built/admin/assets/{code-editor-view-CtkF82Fv.js → code-editor-view-DCQJxsfU.js} +1 -1
  70. package/core/built/admin/assets/{color-picker-Bmo1r9Fc.js → color-picker-BTY_NdEm.js} +1 -1
  71. package/core/built/admin/assets/{color-picker-field-DywowPhF.js → color-picker-field-CPlkzOH0.js} +1 -1
  72. package/core/built/admin/assets/{combobox-C4QCh6Yw.js → combobox-DrMtv_4P.js} +1 -1
  73. package/core/built/admin/assets/command-ZdgYJpoI.js +1 -0
  74. package/core/built/admin/assets/comments-kidj60-h.js +1 -0
  75. package/core/built/admin/assets/{confirmation-context-CLFHhyyH.js → confirmation-context-BhbmQQEl.js} +1 -1
  76. package/core/built/admin/assets/{container-LiZf3XdY.js → container-BuQG1wuP.js} +1 -1
  77. package/core/built/admin/assets/{content-api-modal-BtpNI92-.js → content-api-modal-CyQEC3fr.js} +1 -1
  78. package/core/built/admin/assets/{copy-field-CglgRZyG.js → copy-field-B3M1s78L.js} +1 -1
  79. package/core/built/admin/assets/{custom-field-type-option-D0PXoSnP.js → custom-field-type-option-CsGIZk1J.js} +1 -1
  80. package/core/built/admin/assets/{custom-integration-modal-DCIHKN33.js → custom-integration-modal-BY37O_9X.js} +1 -1
  81. package/core/built/admin/assets/{data-list-CupF7bjM.js → data-list-CA2jYGPq.js} +1 -1
  82. package/core/built/admin/assets/{date-range-select-JPwM0yUj.js → date-range-select-DD2RKkgB.js} +1 -1
  83. package/core/built/admin/assets/design-and-theme-modal-DUSKM4uC.js +22 -0
  84. package/core/built/admin/assets/{detail-page-D8lx2SdP.js → detail-page-Dnv-CdR1.js} +1 -1
  85. package/core/built/admin/assets/dialog-B44iRwlc.js +1 -0
  86. package/core/built/admin/assets/{dirty-confirm-dialog-CmARpZQS.js → dirty-confirm-dialog-BxgQgQ6H.js} +1 -1
  87. package/core/built/admin/assets/{disabled-sources-indicator-BTJ2ClQu.js → disabled-sources-indicator-Cvy47bE2.js} +1 -1
  88. package/core/built/admin/assets/{dist-DzcfoDJ3.js → dist-8YJUlf3B.js} +1 -1
  89. package/core/built/admin/assets/{dist-Cb5RSHSg.js → dist-B3keLvjj.js} +1 -1
  90. package/core/built/admin/assets/{dist-QLZuGq7o2.js → dist-Cy8tfrp_.js} +1 -1
  91. package/core/built/admin/assets/{dist-BT_Z-eCn.js → dist-Dgt2cr6a.js} +1 -1
  92. package/core/built/admin/assets/{domain-D0SAtc-T.js → domain-Ca6KhoQt.js} +1 -1
  93. package/core/built/admin/assets/{dropzone-CaPOeDRZ.js → dropzone-Bb-5zQTk.js} +1 -1
  94. package/core/built/admin/assets/edit-profile-BdupLlus.js +1 -0
  95. package/core/built/admin/assets/{editor-COXn4Atu.js → editor-BP883Lpn.js} +3 -3
  96. package/core/built/admin/assets/{embed-signup-form-modal-BFTPf04i.js → embed-signup-form-modal-DeBMLxlL.js} +1 -1
  97. package/core/built/admin/assets/{empty-indicator-WB1WgT9h.js → empty-indicator-D9QdpuNX.js} +1 -1
  98. package/core/built/admin/assets/{explore-BsNYrubV.js → explore-FB-CimXw.js} +1 -1
  99. package/core/built/admin/assets/{feed-8RR1O1bK.js → feed-C1GxsmI2.js} +1 -1
  100. package/core/built/admin/assets/{field-LmNk7wZh.js → field-Cj8lmDOo.js} +1 -1
  101. package/core/built/admin/assets/{filter-sources-4C0kF1NU.js → filter-sources-D5n5bFA2.js} +1 -1
  102. package/core/built/admin/assets/{filters-CV5jCb9n.js → filters-DJEzkMUK.js} +1 -1
  103. package/core/built/admin/assets/{filters-Dmr0PoqU.js → filters-MZXvdH5D.js} +1 -1
  104. package/core/built/admin/assets/{first-promoter-modal-OCzSaL3B.js → first-promoter-modal-CGTGLCr5.js} +1 -1
  105. package/core/built/admin/assets/{ghost-403cb39badad3df411fc0ba27d220047.js → ghost-3894eedcc6968f658578c0abfe942aab.js} +2 -2
  106. package/core/built/admin/assets/{gift-link-modal-0mzjn5oF.js → gift-link-modal-B6v0tnRN.js} +1 -1
  107. package/core/built/admin/assets/{grid-CUciBfjf.js → grid-Dj29PY05.js} +1 -1
  108. package/core/built/admin/assets/growth-BGAJD1rs.js +3 -0
  109. package/core/built/admin/assets/growth-D6mhcx3q.js +1 -0
  110. package/core/built/admin/assets/{heading-CRZZ2FUe.js → heading-Dh5SFVjL.js} +1 -1
  111. package/core/built/admin/assets/history-modal-iKwUY3XR.js +1 -0
  112. package/core/built/admin/assets/html-field-C8qVGGC1.js +1 -0
  113. package/core/built/admin/assets/{images-C0XvUYMb.js → images-h8VZEQ9k.js} +1 -1
  114. package/core/built/admin/assets/{inbox-DZXDUt4s.js → inbox-BYd1M06Q.js} +13 -13
  115. package/core/built/admin/assets/index-DjQe-e5s.js +4 -0
  116. package/core/built/admin/assets/{index.es-BMUCj9TR.js → index.es-VihPwfeH.js} +1 -1
  117. package/core/built/admin/assets/{inline-Cw-gigDW.js → inline-BWSs_VzR.js} +1 -1
  118. package/core/built/admin/assets/{input-UHrKuvBT.js → input--W-rCTrX.js} +1 -1
  119. package/core/built/admin/assets/{input-group-BPAxETpQ.js → input-group-D8sCXRF5.js} +1 -1
  120. package/core/built/admin/assets/{input-surface-BdOe4KzO.js → input-surface-BsrIZeSF.js} +1 -1
  121. package/core/built/admin/assets/{integration-header-B4DyXV06.js → integration-header-Bm6IDb1A.js} +1 -1
  122. package/core/built/admin/assets/{invite-user-modal-BrAkxEO3.js → invite-user-modal-MdImLCaJ.js} +1 -1
  123. package/core/built/admin/assets/{koenig-lexical-60O_8aiO.js → koenig-lexical-_-IsVI7E.js} +1 -1
  124. package/core/built/admin/assets/koenig-loader-DYZpm6El.js +2 -0
  125. package/core/built/admin/assets/{kpi-card-fUHZlzBX.js → kpi-card-DW_2y3ug.js} +1 -1
  126. package/core/built/admin/assets/kpi-card-DZQk_0W8.js +1 -0
  127. package/core/built/admin/assets/kpi-helpers-PueTKuA6.js +1 -0
  128. package/core/built/admin/assets/kpi-tabs-CojDs-Qz.js +1 -0
  129. package/core/built/admin/assets/{label-VIG969IC.js → label-DjbT91GM.js} +1 -1
  130. package/core/built/admin/assets/{label-picker-BBWykUeA.js → label-picker-cB51xl1r.js} +1 -1
  131. package/core/built/admin/assets/layout-c_B_1hax.js +1 -0
  132. package/core/built/admin/assets/{link-helpers-Dtq9fxQg.js → link-helpers-MVDdnFCY.js} +1 -1
  133. package/core/built/admin/assets/{list-page-CdsnQR9N.js → list-page-BucXJ0hi.js} +1 -1
  134. package/core/built/admin/assets/{loading-indicator-SFTqyYVE.js → loading-indicator-BpFWTVgh.js} +1 -1
  135. package/core/built/admin/assets/{member-custom-fields-gOv6Hoh3.js → member-custom-fields-qs0dIkxM.js} +1 -1
  136. package/core/built/admin/assets/member-detail-B6uec2a6.js +1 -0
  137. package/core/built/admin/assets/members-BQF3CqhI.js +2 -0
  138. package/core/built/admin/assets/{modal-page-BMTzFHVO.js → modal-page-xCivTMvI.js} +1 -1
  139. package/core/built/admin/assets/{moderation-DzzPLDyl.js → moderation-DY4wF1Q3.js} +1 -1
  140. package/core/built/admin/assets/{multi-select-combobox-CGohnsxJ.js → multi-select-combobox-B6LiRzDO.js} +1 -1
  141. package/core/built/admin/assets/navigation-modal-DX-gNF3X.js +1 -0
  142. package/core/built/admin/assets/newsletter-CyQA7m3m.js +1 -0
  143. package/core/built/admin/assets/{newsletter-detail-modal-DQU3r4g2.js → newsletter-detail-modal-BDrptuxn.js} +1 -1
  144. package/core/built/admin/assets/{newsletter-emails-D5ql1rud.js → newsletter-emails-CFeLlt4z.js} +1 -1
  145. package/core/built/admin/assets/newsletters-DXuNmC42.js +1 -0
  146. package/core/built/admin/assets/{note-i8k6pjaw.js → note-Cgo2LCJ6.js} +1 -1
  147. package/core/built/admin/assets/notifications-BC50AMku.js +1 -0
  148. package/core/built/admin/assets/{offers-container-modal-BWfjSdyg.js → offers-container-modal-DWycIMzT.js} +1 -1
  149. package/core/built/admin/assets/{onboarding-route-Cu_ROWPn.js → onboarding-route-Dmc4IPm3.js} +1 -1
  150. package/core/built/admin/assets/overview-CVbFtn-k.js +1 -0
  151. package/core/built/admin/assets/overview-YKj7SZaK.js +1 -0
  152. package/core/built/admin/assets/{page-header-Cfds8pCg.js → page-header-BR_nbIPp.js} +1 -1
  153. package/core/built/admin/assets/{pintura-modal-TDTrJ89x.js → pintura-modal-BR9hEvS8.js} +1 -1
  154. package/core/built/admin/assets/popover-CCy0h5rq.js +1 -0
  155. package/core/built/admin/assets/{portal-frame-DjBF-uy2.js → portal-frame-dc4XKr0e.js} +1 -1
  156. package/core/built/admin/assets/portal-modal-BvvdF_B9.js +1 -0
  157. package/core/built/admin/assets/{post-analytics-Buz1COoY.js → post-analytics-DX470WRG.js} +1 -1
  158. package/core/built/admin/assets/{post-analytics-header-B-P0eFnT.js → post-analytics-header-CXpJmdDv.js} +1 -1
  159. package/core/built/admin/assets/{post-analytics-provider-Cu3jNeFh.js → post-analytics-provider-CLfKGWZy.js} +1 -1
  160. package/core/built/admin/assets/{post-share-modal-P1_M6o-H.js → post-share-modal-Cl0NXRJr.js} +1 -1
  161. package/core/built/admin/assets/{preferences-Cq1aOiLy.js → preferences-DO0UUWFp.js} +2 -2
  162. package/core/built/admin/assets/{preview-chrome-BOVO6_PE.js → preview-chrome-BljUBlOk.js} +1 -1
  163. package/core/built/admin/assets/{preview-modal-MlTjP8UU.js → preview-modal-C-BL-F9k.js} +1 -1
  164. package/core/built/admin/assets/profile-CxT-0l4d.js +1 -0
  165. package/core/built/admin/assets/radio-group-Bgz60i81.js +1 -0
  166. package/core/built/admin/assets/{router-provider-CJC58zTy.js → router-provider-B0gZyiGJ.js} +1 -1
  167. package/core/built/admin/assets/{schemas-CRsC53ls.js → schemas-4UPic-oD.js} +2 -2
  168. package/core/built/admin/assets/select-DuDUFdPq.js +1 -0
  169. package/core/built/admin/assets/{settings-B5hJKZ5C.js → settings-BjCii7BM.js} +1 -1
  170. package/core/built/admin/assets/settings-b8kNzZSQ.js +4 -0
  171. package/core/built/admin/assets/{settings-breadcrumbs-sLDNedBW.js → settings-breadcrumbs-CyP_9zTo.js} +1 -1
  172. package/core/built/admin/assets/{shade-app-F7WxOyfk-nufqw1hd.js → shade-app-CcS3f8MZ-vwURazk8.js} +2 -2
  173. package/core/built/admin/assets/{share-modal-CLBfj377.js → share-modal-BV70mr9k.js} +1 -1
  174. package/core/built/admin/assets/{skeleton-D7hwjdry.js → skeleton-Ce9GgUpf.js} +1 -1
  175. package/core/built/admin/assets/{slack-modal-Bt9I_tEo.js → slack-modal-Be2_KK-z.js} +1 -1
  176. package/core/built/admin/assets/sort-button-Cc-Z96sA.js +1 -0
  177. package/core/built/admin/assets/{source-icon-BPsD5ees.js → source-icon-v6PUnmyM.js} +1 -1
  178. package/core/built/admin/assets/{stack-CIfOAAVf.js → stack-B2eszIiq.js} +1 -1
  179. package/core/built/admin/assets/{stats-B_YkF7bp.js → stats-C4reGh9O.js} +1 -1
  180. package/core/built/admin/assets/{stats-view-BOCp9RG8.js → stats-view-DP9pQ62k.js} +1 -1
  181. package/core/built/admin/assets/{step-1-CMta6YFO.js → step-1-DSRp2vBj.js} +1 -1
  182. package/core/built/admin/assets/{step-2-BG04nh5q.js → step-2-COqv2g0u.js} +1 -1
  183. package/core/built/admin/assets/{step-3-ZnMaVIPj.js → step-3-6W1NMVQc.js} +2 -2
  184. package/core/built/admin/assets/{stripe-button-DDoUKN5a.js → stripe-button-D2K42Uty.js} +1 -1
  185. package/core/built/admin/assets/{stripe-connect-modal-BeSukI8q.js → stripe-connect-modal-Z-UT_BGc.js} +1 -1
  186. package/core/built/admin/assets/{switch-C9djUIMO.js → switch-CI4gLWqb.js} +1 -1
  187. package/core/built/admin/assets/{table-CrqQtkR2.js → table-B2pIKjVh.js} +1 -1
  188. package/core/built/admin/assets/{tabs-CGisSbWq.js → tabs-SaW_UT-Q.js} +1 -1
  189. package/core/built/admin/assets/tag-detail-Dc0nTOtU.js +2 -0
  190. package/core/built/admin/assets/tags-BLaXBwnb.js +1 -0
  191. package/core/built/admin/assets/testimonials-modal-sFwRnNLh.js +1 -0
  192. package/core/built/admin/assets/{text-DU9Hv33_.js → text-BQDSDsKs.js} +1 -1
  193. package/core/built/admin/assets/{textarea-d9qEkMOP.js → textarea-DJ1Q5V39.js} +1 -1
  194. package/core/built/admin/assets/{tier-detail-modal-CxRwgTPR.js → tier-detail-modal-BCFpWwUS.js} +1 -1
  195. package/core/built/admin/assets/{toggle-group-CtKZURJd.js → toggle-group-EM9WpESu.js} +1 -1
  196. package/core/built/admin/assets/{topic-filter-D8JT8Tq1.js → topic-filter-DY4gNHn2.js} +1 -1
  197. package/core/built/admin/assets/{transistor-modal-6PUf0idx.js → transistor-modal-CpyPG-MH.js} +1 -1
  198. package/core/built/admin/assets/trend-badge-ByMkuAuH.js +1 -0
  199. package/core/built/admin/assets/{unsplash-modal-BPuDBPja.js → unsplash-modal-Cv2Q6GtY.js} +1 -1
  200. package/core/built/admin/assets/{use-analytics-data--opuzwcz.js → use-analytics-data-CHvjMYuT.js} +1 -1
  201. package/core/built/admin/assets/use-check-theme-limit-error-Qv4SVXqw.js +2 -0
  202. package/core/built/admin/assets/use-filter-params-CAvfDvf1.js +1 -0
  203. package/core/built/admin/assets/use-growth-stats-D6mZXGhK.js +1 -0
  204. package/core/built/admin/assets/{use-limiter-TDSNiHPB.js → use-limiter-cwJvsNBo.js} +1 -1
  205. package/core/built/admin/assets/{use-navigate-with-base-path-CK989MlC.js → use-navigate-with-base-path-BHPA228f.js} +1 -1
  206. package/core/built/admin/assets/{use-pintura-config-CnCGrDFk.js → use-pintura-config-CzTfnufz.js} +1 -1
  207. package/core/built/admin/assets/{use-pintura-editor-ntphvtUd.js → use-pintura-editor-BDBXWUYq.js} +1 -1
  208. package/core/built/admin/assets/{use-post-referrers-CbXLFIex.js → use-post-referrers-DbY-mzci.js} +1 -1
  209. package/core/built/admin/assets/{use-reply-chain-data-JYFKSO83.js → use-reply-chain-data-BeQwz8oF.js} +1 -1
  210. package/core/built/admin/assets/{use-router-history-entry-BwfQS2mq.js → use-router-history-entry-Bg6BhBQQ.js} +1 -1
  211. package/core/built/admin/assets/{use-setting-group-DQxV42-O.js → use-setting-group-VM7FQwMY.js} +1 -1
  212. package/core/built/admin/assets/{use-settings-navigation-BBzro2-V.js → use-settings-navigation-BbrSUVcf.js} +1 -1
  213. package/core/built/admin/assets/{use-simple-pagination-B2TdNX67.js → use-simple-pagination-Dum6Irbs.js} +1 -1
  214. package/core/built/admin/assets/{use-staff-users-QrR9voeC.js → use-staff-users-cZg4ugOF.js} +1 -1
  215. package/core/built/admin/assets/{use-tinybird-query-D2Aeoty5.js → use-tinybird-query-B1IMyAcv.js} +1 -1
  216. package/core/built/admin/assets/{use-tinybird-token-DBuwMmln.js → use-tinybird-token-Bow0Zwn8.js} +1 -1
  217. package/core/built/admin/assets/{use-unsaved-changes-guard-DpYJcj1d.js → use-unsaved-changes-guard-BAy0RANR.js} +1 -1
  218. package/core/built/admin/assets/{use-url-input-WnIqckzS.js → use-url-input-Df5QzNa7.js} +1 -1
  219. package/core/built/admin/assets/user-detail-modal-yipSoQfv.js +1 -0
  220. package/core/built/admin/assets/{virtual-list-D3MfPNOh.js → virtual-list-DEx8WgiO.js} +1 -1
  221. package/core/built/admin/assets/web-CKcXAu86.js +1 -0
  222. package/core/built/admin/assets/web-DR4TqM3E.js +2 -0
  223. package/core/built/admin/assets/{zapier-modal-BO6PS_Vd.js → zapier-modal-Cw3BTBUu.js} +1 -1
  224. package/core/built/admin/index.html +24 -25
  225. package/core/frontend/services/rendering/renderer.js +15 -0
  226. package/core/server/adapters/storage/LocalStorageBase.js +8 -5
  227. package/core/server/api/endpoints/db.js +19 -5
  228. package/core/server/api/endpoints/index.js +4 -0
  229. package/core/server/api/endpoints/member-custom-fields.js +4 -14
  230. package/core/server/api/endpoints/posts.js +1 -0
  231. package/core/server/api/endpoints/tiers-checkout-config.js +59 -0
  232. package/core/server/api/endpoints/utils/serializers/output/config.js +1 -0
  233. package/core/server/api/endpoints/utils/serializers/output/index.js +4 -0
  234. package/core/server/api/endpoints/utils/serializers/output/tiers-checkout-config.js +12 -0
  235. package/core/server/data/exporter/table-lists.js +3 -0
  236. package/core/server/data/importer/content-files.js +57 -0
  237. package/core/server/data/importer/handlers/image.js +2 -2
  238. package/core/server/data/importer/import-archive.js +131 -0
  239. package/core/server/data/importer/import-manager.js +18 -180
  240. package/core/server/data/importer/importers/content-file-importer.js +66 -4
  241. package/core/server/data/migrations/versions/6.61/2026-08-19-14-30-20-add-written-by-to-members-custom-field-values.js +42 -0
  242. package/core/server/data/migrations/versions/6.61/2026-08-19-14-38-53-add-members-custom-field-bindings-table.js +26 -0
  243. package/core/server/data/migrations/versions/6.61/2026-08-19-14-48-06-add-tier-checkout-field-tables.js +35 -0
  244. package/core/server/data/schema/schema.js +90 -0
  245. package/core/server/data/seeders/importers/automation-action-revisions-importer.js +3 -3
  246. package/core/server/data/seeders/importers/automation-actions-importer.js +3 -3
  247. package/core/server/data/seeders/importers/automation-run-steps-importer.js +3 -3
  248. package/core/server/data/seeders/importers/automation-runs-importer.js +5 -5
  249. package/core/server/data/seeders/importers/automations-importer.js +3 -3
  250. package/core/server/data/seeders/importers/comment-reports-importer.js +1 -1
  251. package/core/server/data/seeders/importers/comments-importer.js +1 -1
  252. package/core/server/data/seeders/importers/email-batches-importer.js +1 -1
  253. package/core/server/data/seeders/importers/email-recipients-importer.js +1 -1
  254. package/core/server/data/seeders/importers/emails-importer.js +1 -1
  255. package/core/server/data/seeders/importers/labels-importer.js +1 -1
  256. package/core/server/data/seeders/importers/members-click-events-importer.js +1 -1
  257. package/core/server/data/seeders/importers/members-created-events-importer.js +1 -1
  258. package/core/server/data/seeders/importers/members-feedback-importer.js +1 -1
  259. package/core/server/data/seeders/importers/members-importer.js +1 -1
  260. package/core/server/data/seeders/importers/members-login-events-importer.js +1 -1
  261. package/core/server/data/seeders/importers/members-products-importer.js +1 -1
  262. package/core/server/data/seeders/importers/members-status-events-importer.js +1 -1
  263. package/core/server/data/seeders/importers/members-stripe-customers-importer.js +1 -1
  264. package/core/server/data/seeders/importers/members-stripe-customers-subscriptions-importer.js +1 -1
  265. package/core/server/data/seeders/importers/members-subscribe-events-importer.js +1 -1
  266. package/core/server/data/seeders/importers/members-subscription-created-events-importer.js +1 -1
  267. package/core/server/data/seeders/importers/offer-redemptions-importer.js +1 -1
  268. package/core/server/data/seeders/importers/offers-importer.js +1 -1
  269. package/core/server/data/seeders/importers/posts-importer.js +1 -1
  270. package/core/server/data/seeders/importers/table-importer.js +2 -2
  271. package/core/server/data/seeders/importers/tags-importer.js +1 -1
  272. package/core/server/data/seeders/importers/users-importer.js +1 -1
  273. package/core/server/data/seeders/importers/web-mentions-importer.js +1 -1
  274. package/core/server/data/seeders/utils/random.js +3 -3
  275. package/core/server/ghost-server.js +3 -2
  276. package/core/server/lib/db-types/boolean.js +18 -0
  277. package/core/server/lib/promise-pool.js +31 -0
  278. package/core/server/services/automations/database-automations-repository.js +26 -26
  279. package/core/server/services/automations/poll.js +1 -0
  280. package/core/server/services/content-import/import/assets.js +74 -0
  281. package/core/server/services/content-import/import/importer.js +57 -14
  282. package/core/server/services/content-import/import/post-data.js +1 -0
  283. package/core/server/services/content-import/import/post-repository.js +78 -0
  284. package/core/server/services/content-import/import/relations.js +149 -0
  285. package/core/server/services/content-import/import/row.js +11 -0
  286. package/core/server/services/content-import/import/schema.js +29 -0
  287. package/core/server/services/content-import/import/source.js +125 -0
  288. package/core/server/services/content-import/index.js +6 -28
  289. package/core/server/services/email-analytics/email-analytics-service.js +8 -1
  290. package/core/server/services/email-analytics/lib/queries.js +7 -1
  291. package/core/server/services/gift-links/schema.js +3 -3
  292. package/core/server/services/gifts/CONTEXT.md +1 -1
  293. package/core/server/services/gifts/constants.js +1 -1
  294. package/core/server/services/gifts/gift-bookshelf-repository.js +2 -2
  295. package/core/server/services/gifts/gift-delivery-bookshelf-repository.js +18 -9
  296. package/core/server/services/gifts/gift-delivery-schema.js +5 -5
  297. package/core/server/services/gifts/gift-delivery-service.js +4 -0
  298. package/core/server/services/gifts/gift-schema.js +10 -10
  299. package/core/server/services/gifts/gift-service.js +4 -2
  300. package/core/server/services/jobs-service/register-job-handlers.js +5 -5
  301. package/core/server/services/lib/mailgun-client.js +44 -8
  302. package/core/server/services/media-inliner/external-media-inliner-job.js +12 -0
  303. package/core/server/services/media-inliner/external-media-inliner.js +103 -29
  304. package/core/server/services/media-inliner/service.js +13 -41
  305. package/core/server/services/media-inliner/types.js +2 -0
  306. package/core/server/services/members/import-export/export/exporter.js +4 -6
  307. package/core/server/services/members/import-export/import/importer.js +21 -5
  308. package/core/server/services/members/import-export/import/stripe-utils.js +6 -1
  309. package/core/server/services/members/import-export/index.js +6 -1
  310. package/core/server/services/members/members-api/members-api.js +5 -0
  311. package/core/server/services/members/members-api/services/member-bread-service.js +19 -1
  312. package/core/server/services/members/members-api/services/payments-service.js +47 -1
  313. package/core/server/services/members-custom-fields/actions.js +27 -1
  314. package/core/server/services/members-custom-fields/bindings-service.js +119 -0
  315. package/core/server/services/members-custom-fields/definitions-service.js +104 -13
  316. package/core/server/services/members-custom-fields/index.js +11 -4
  317. package/core/server/services/members-custom-fields/queries.js +5 -0
  318. package/core/server/services/members-custom-fields/schema.js +37 -6
  319. package/core/server/services/members-custom-fields/values-service.js +15 -3
  320. package/core/server/services/public-config/config.js +7 -0
  321. package/core/server/services/stripe/services/checkout/allowed-countries.js +267 -0
  322. package/core/server/services/stripe/services/checkout/completed-session.js +68 -0
  323. package/core/server/services/stripe/services/checkout/field-ports.js +34 -0
  324. package/core/server/services/stripe/services/checkout/session-options.js +97 -0
  325. package/core/server/services/stripe/services/webhook/checkout-session-event-service.js +49 -0
  326. package/core/server/services/stripe/stripe-api.js +29 -0
  327. package/core/server/services/stripe/stripe-service.js +7 -0
  328. package/core/server/services/tier-checkout-config/codec.js +95 -0
  329. package/core/server/services/tier-checkout-config/destinations.js +17 -0
  330. package/core/server/services/tier-checkout-config/index.js +26 -0
  331. package/core/server/services/tier-checkout-config/models.js +57 -0
  332. package/core/server/services/tier-checkout-config/queries.js +80 -0
  333. package/core/server/services/tier-checkout-config/schema.js +33 -0
  334. package/core/server/services/tier-checkout-config/serializers.js +122 -0
  335. package/core/server/services/tier-checkout-config/service.js +303 -0
  336. package/core/server/services/tiers/service.js +21 -0
  337. package/core/server/web/api/endpoints/admin/routes.js +24 -13
  338. package/core/server/web/api/middleware/upload.js +2 -2
  339. package/core/server/web/parent/app.js +5 -0
  340. package/core/server/web/parent/middleware/filter-query-parameters.js +94 -0
  341. package/core/server/web/parent/middleware/index.js +1 -0
  342. package/core/server/web/query-parameter-policy/index.js +9 -0
  343. package/core/server/web/query-parameter-policy/policy.json +58 -0
  344. package/core/server/web/query-parameter-policy/schema.js +38 -0
  345. package/core/shared/config/defaults.json +3 -0
  346. package/core/shared/config/env/config.testing-mysql.json +3 -0
  347. package/core/shared/config/env/config.testing.json +3 -0
  348. package/core/shared/config/overrides.json +4 -2
  349. package/core/shared/labs.js +5 -14
  350. package/package.json +12 -13
  351. package/pnpm-lock.yaml +44 -46
  352. package/pnpm-workspace.yaml +6 -6
  353. package/tsconfig.json +2 -3
  354. package/core/built/admin/assets/activitypub/layout-CXajhRsL.js +0 -1
  355. package/core/built/admin/assets/alert-dialog-wEbVxANM.js +0 -1
  356. package/core/built/admin/assets/app-utils-D2Wp7ZSS.js +0 -1
  357. package/core/built/admin/assets/audience-DTLMXAFH.js +0 -1
  358. package/core/built/admin/assets/chart-helpers-B3OqQ6Ez.js +0 -1
  359. package/core/built/admin/assets/command-DcLbSifC.js +0 -1
  360. package/core/built/admin/assets/comments-Bxy_3WyE.js +0 -1
  361. package/core/built/admin/assets/design-and-theme-modal-CZ-PkW7o.js +0 -23
  362. package/core/built/admin/assets/dialog-Db7c164G.js +0 -1
  363. package/core/built/admin/assets/edit-profile-By7v5XW5.js +0 -1
  364. package/core/built/admin/assets/growth-55vWlGT_.js +0 -1
  365. package/core/built/admin/assets/growth-DA5AluYw.js +0 -3
  366. package/core/built/admin/assets/history-modal-G1s5hHz7.js +0 -1
  367. package/core/built/admin/assets/html-field-BegxsWpw.js +0 -1
  368. package/core/built/admin/assets/index-CDP9tIOk.js +0 -4
  369. package/core/built/admin/assets/koenig-loader-DwVY_V-H.js +0 -1
  370. package/core/built/admin/assets/kpi-card-LERqWBoY.js +0 -1
  371. package/core/built/admin/assets/kpi-helpers-DB3ouhYF.js +0 -1
  372. package/core/built/admin/assets/kpi-tabs-BGvtMD8S.js +0 -1
  373. package/core/built/admin/assets/layout-Di5K7doM.js +0 -1
  374. package/core/built/admin/assets/member-detail-D7mZDDp3.js +0 -1
  375. package/core/built/admin/assets/member-route-0Aa52Ntz.js +0 -1
  376. package/core/built/admin/assets/members-DvZG9t69.js +0 -2
  377. package/core/built/admin/assets/navigation-modal-CI8Bx5vn.js +0 -1
  378. package/core/built/admin/assets/newsletter-Bg3cq5U-.js +0 -1
  379. package/core/built/admin/assets/newsletters-DMDfZbMS.js +0 -1
  380. package/core/built/admin/assets/notifications-psA_2Ph4.js +0 -1
  381. package/core/built/admin/assets/overview-C-6xOLaf.js +0 -1
  382. package/core/built/admin/assets/overview-DaLhpRrC.js +0 -1
  383. package/core/built/admin/assets/popover-CFgqFDvC.js +0 -1
  384. package/core/built/admin/assets/portal-modal-Cf0pBAk8.js +0 -1
  385. package/core/built/admin/assets/profile-D6dHYf2o.js +0 -1
  386. package/core/built/admin/assets/radio-group-CjtmsCPl.js +0 -1
  387. package/core/built/admin/assets/select-D_RQaXgt.js +0 -1
  388. package/core/built/admin/assets/settings-DIo_F-MF.js +0 -4
  389. package/core/built/admin/assets/sort-button-DMBXF7tP.js +0 -1
  390. package/core/built/admin/assets/tag-detail-2a3BfzTW.js +0 -2
  391. package/core/built/admin/assets/tags-Dp2_8UzL.js +0 -1
  392. package/core/built/admin/assets/testimonials-modal-C9nrypNo.js +0 -1
  393. package/core/built/admin/assets/use-check-theme-limit-error-C9-QhGdV.js +0 -1
  394. package/core/built/admin/assets/use-filter-params-CSpAvgD2.js +0 -1
  395. package/core/built/admin/assets/use-growth-stats-BOmoPDHJ.js +0 -1
  396. package/core/built/admin/assets/user-detail-modal-59mBJqxN.js +0 -1
  397. package/core/built/admin/assets/web-DUuX7nE2.js +0 -2
  398. package/core/built/admin/assets/web-N8ucs2aG.js +0 -1
  399. /package/core/server/lib/{db-date.js → db-types/date.js} +0 -0
@@ -0,0 +1,267 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.STRIPE_ALLOWED_COUNTRIES = void 0;
4
+ exports.isStripeAllowedCountry = isStripeAllowedCountry;
5
+ /**
6
+ * The countries Stripe Checkout will accept in `shipping_address_collection`.
7
+ *
8
+ * Not a general list of countries. This is not a question about which places exist, it is
9
+ * a question about where this payment processor will ship, and only the processor's answer
10
+ * decides whether a session can be created at all. A general ISO list gets it wrong in both
11
+ * directions: it omits places Stripe accepts, and it includes the sanctioned countries
12
+ * Stripe refuses.
13
+ *
14
+ * Measured against the live API at the pinned version by `e2e/scripts/probe-stripe-constraints.ts`,
15
+ * not read from the SDK's `AllowedCountry` union, because that union is wrong: it omits
16
+ * `SD`, which the live API accepts. Every other code the union carries was confirmed
17
+ * accepted, so the union is a subset of this list rather than a different one — which is
18
+ * what the accompanying test holds it to, so a country Stripe adds cannot pass unnoticed.
19
+ *
20
+ * A code Stripe rejects fails the whole session create, which is a publisher who cannot
21
+ * sell. So this is checked when a publisher chooses a country rather than when a member
22
+ * tries to buy.
23
+ */
24
+ exports.STRIPE_ALLOWED_COUNTRIES = [
25
+ 'AC',
26
+ 'AD',
27
+ 'AE',
28
+ 'AF',
29
+ 'AG',
30
+ 'AI',
31
+ 'AL',
32
+ 'AM',
33
+ 'AO',
34
+ 'AQ',
35
+ 'AR',
36
+ 'AT',
37
+ 'AU',
38
+ 'AW',
39
+ 'AX',
40
+ 'AZ',
41
+ 'BA',
42
+ 'BB',
43
+ 'BD',
44
+ 'BE',
45
+ 'BF',
46
+ 'BG',
47
+ 'BH',
48
+ 'BI',
49
+ 'BJ',
50
+ 'BL',
51
+ 'BM',
52
+ 'BN',
53
+ 'BO',
54
+ 'BQ',
55
+ 'BR',
56
+ 'BS',
57
+ 'BT',
58
+ 'BV',
59
+ 'BW',
60
+ 'BY',
61
+ 'BZ',
62
+ 'CA',
63
+ 'CD',
64
+ 'CF',
65
+ 'CG',
66
+ 'CH',
67
+ 'CI',
68
+ 'CK',
69
+ 'CL',
70
+ 'CM',
71
+ 'CN',
72
+ 'CO',
73
+ 'CR',
74
+ 'CV',
75
+ 'CW',
76
+ 'CY',
77
+ 'CZ',
78
+ 'DE',
79
+ 'DJ',
80
+ 'DK',
81
+ 'DM',
82
+ 'DO',
83
+ 'DZ',
84
+ 'EC',
85
+ 'EE',
86
+ 'EG',
87
+ 'EH',
88
+ 'ER',
89
+ 'ES',
90
+ 'ET',
91
+ 'FI',
92
+ 'FJ',
93
+ 'FK',
94
+ 'FO',
95
+ 'FR',
96
+ 'GA',
97
+ 'GB',
98
+ 'GD',
99
+ 'GE',
100
+ 'GF',
101
+ 'GG',
102
+ 'GH',
103
+ 'GI',
104
+ 'GL',
105
+ 'GM',
106
+ 'GN',
107
+ 'GP',
108
+ 'GQ',
109
+ 'GR',
110
+ 'GS',
111
+ 'GT',
112
+ 'GU',
113
+ 'GW',
114
+ 'GY',
115
+ 'HK',
116
+ 'HN',
117
+ 'HR',
118
+ 'HT',
119
+ 'HU',
120
+ 'ID',
121
+ 'IE',
122
+ 'IL',
123
+ 'IM',
124
+ 'IN',
125
+ 'IO',
126
+ 'IQ',
127
+ 'IS',
128
+ 'IT',
129
+ 'JE',
130
+ 'JM',
131
+ 'JO',
132
+ 'JP',
133
+ 'KE',
134
+ 'KG',
135
+ 'KH',
136
+ 'KI',
137
+ 'KM',
138
+ 'KN',
139
+ 'KR',
140
+ 'KW',
141
+ 'KY',
142
+ 'KZ',
143
+ 'LA',
144
+ 'LB',
145
+ 'LC',
146
+ 'LI',
147
+ 'LK',
148
+ 'LR',
149
+ 'LS',
150
+ 'LT',
151
+ 'LU',
152
+ 'LV',
153
+ 'LY',
154
+ 'MA',
155
+ 'MC',
156
+ 'MD',
157
+ 'ME',
158
+ 'MF',
159
+ 'MG',
160
+ 'MK',
161
+ 'ML',
162
+ 'MM',
163
+ 'MN',
164
+ 'MO',
165
+ 'MQ',
166
+ 'MR',
167
+ 'MS',
168
+ 'MT',
169
+ 'MU',
170
+ 'MV',
171
+ 'MW',
172
+ 'MX',
173
+ 'MY',
174
+ 'MZ',
175
+ 'NA',
176
+ 'NC',
177
+ 'NE',
178
+ 'NG',
179
+ 'NI',
180
+ 'NL',
181
+ 'NO',
182
+ 'NP',
183
+ 'NR',
184
+ 'NU',
185
+ 'NZ',
186
+ 'OM',
187
+ 'PA',
188
+ 'PE',
189
+ 'PF',
190
+ 'PG',
191
+ 'PH',
192
+ 'PK',
193
+ 'PL',
194
+ 'PM',
195
+ 'PN',
196
+ 'PR',
197
+ 'PS',
198
+ 'PT',
199
+ 'PY',
200
+ 'QA',
201
+ 'RE',
202
+ 'RO',
203
+ 'RS',
204
+ 'RU',
205
+ 'RW',
206
+ 'SA',
207
+ 'SB',
208
+ 'SC',
209
+ 'SD',
210
+ 'SE',
211
+ 'SG',
212
+ 'SH',
213
+ 'SI',
214
+ 'SJ',
215
+ 'SK',
216
+ 'SL',
217
+ 'SM',
218
+ 'SN',
219
+ 'SO',
220
+ 'SR',
221
+ 'SS',
222
+ 'ST',
223
+ 'SV',
224
+ 'SX',
225
+ 'SZ',
226
+ 'TA',
227
+ 'TC',
228
+ 'TD',
229
+ 'TF',
230
+ 'TG',
231
+ 'TH',
232
+ 'TJ',
233
+ 'TK',
234
+ 'TL',
235
+ 'TM',
236
+ 'TN',
237
+ 'TO',
238
+ 'TR',
239
+ 'TT',
240
+ 'TV',
241
+ 'TW',
242
+ 'TZ',
243
+ 'UA',
244
+ 'UG',
245
+ 'US',
246
+ 'UY',
247
+ 'UZ',
248
+ 'VA',
249
+ 'VC',
250
+ 'VE',
251
+ 'VG',
252
+ 'VN',
253
+ 'VU',
254
+ 'WF',
255
+ 'WS',
256
+ 'XK',
257
+ 'YE',
258
+ 'YT',
259
+ 'ZA',
260
+ 'ZM',
261
+ 'ZW',
262
+ 'ZZ',
263
+ ];
264
+ const ALLOWED = new Set(exports.STRIPE_ALLOWED_COUNTRIES);
265
+ function isStripeAllowedCountry(code) {
266
+ return ALLOWED.has(code);
267
+ }
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.collectedByPort = exports.CompletedSession = void 0;
4
+ const zod_1 = require("zod");
5
+ const field_ports_1 = require("./field-ports");
6
+ /**
7
+ * What Ghost reads off a completed session.
8
+ *
9
+ * `shipping` is where the address lives at Ghost's pinned Stripe API version; later
10
+ * versions moved it to `collected_information.shipping_details`. An Event is an immutable
11
+ * snapshot rendered at the account's version, so nothing in a payload would warn us if
12
+ * that pin ever changed.
13
+ *
14
+ * A tax number is deliberately not read: Stripe keeps it against the customer it invoices
15
+ * and Ghost never stores one.
16
+ */
17
+ const Collected = zod_1.z
18
+ .string()
19
+ .nullish()
20
+ .transform((given) => (given && given.trim() !== '' ? given : undefined));
21
+ exports.CompletedSession = zod_1.z
22
+ .object({
23
+ custom_fields: zod_1.z
24
+ .array(zod_1.z
25
+ .object({
26
+ key: zod_1.z.string().nullish(),
27
+ text: zod_1.z.object({ value: Collected }).nullish(),
28
+ })
29
+ .nullable())
30
+ .nullish(),
31
+ shipping: zod_1.z
32
+ .object({
33
+ name: Collected,
34
+ address: zod_1.z.record(zod_1.z.string(), Collected).nullish(),
35
+ })
36
+ .nullish(),
37
+ customer_details: zod_1.z.object({ phone: Collected }).nullish(),
38
+ })
39
+ .loose();
40
+ /** Our address type needs at least one part; an empty value would erase what is there. */
41
+ function addressValue(address) {
42
+ const value = Object.fromEntries(Object.entries(address ?? {}).filter((entry) => entry[1] !== undefined));
43
+ return Object.keys(value).length > 0 ? value : undefined;
44
+ }
45
+ const PORT_VALUES = {
46
+ // Stripe returns the recipient's name alongside the address rather than as part of it,
47
+ // while Ghost keeps a name and an address in two separate custom fields. So the name is
48
+ // carried back separately here, under its own name, to be routed to its own field.
49
+ shipping_name: (session) => session.shipping?.name,
50
+ shipping_address: (session) => addressValue(session.shipping?.address),
51
+ phone: (session) => session.customer_details?.phone,
52
+ };
53
+ /**
54
+ * Everything a completed checkout gives back, as a list of pairs: the name Stripe used for
55
+ * a value, and the value itself. Answers to questions and values Stripe collected on its
56
+ * own both come back this way, because both are saved by the same route afterwards.
57
+ *
58
+ * Order matters. The values Stripe collected come last, so that if a question's answer and
59
+ * a collected value are both saved into the same custom field, the collected value is the
60
+ * one the field ends up holding.
61
+ */
62
+ exports.collectedByPort = exports.CompletedSession.transform((session) => {
63
+ const answers = (session.custom_fields ?? [])
64
+ .filter((field) => Boolean(field?.key && field.text?.value))
65
+ .map((field) => ({ port: field.key, value: field.text.value }));
66
+ const ports = field_ports_1.STRIPE_PORTS.map((port) => ({ port, value: PORT_VALUES[port](session) })).filter((entry) => entry.value !== undefined);
67
+ return [...answers, ...ports];
68
+ });
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ /**
3
+ * What Stripe Checkout will render, measured against the live API at Ghost's pinned
4
+ * version rather than read from the reference — which disagreed with the API in three of
5
+ * five probes, missing the field cap and the key format entirely. A wrong bound here fails
6
+ * the session create, which fails the checkout.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.CHECKOUT_ELIGIBLE_FIELD_TYPES = exports.MAX_CHECKOUT_LABEL_LENGTH = exports.MAX_CHECKOUT_CUSTOM_FIELDS = exports.STRIPE_PORT = exports.STRIPE_PORTS = void 0;
10
+ exports.isStripePort = isStripePort;
11
+ exports.isCheckoutEligible = isCheckoutEligible;
12
+ /** The names Stripe returns values under, and the only ports a binding for it may use. */
13
+ exports.STRIPE_PORTS = ['shipping_name', 'shipping_address', 'phone'];
14
+ function isStripePort(key) {
15
+ return exports.STRIPE_PORTS.includes(key);
16
+ }
17
+ exports.STRIPE_PORT = {
18
+ shippingName: 'shipping_name',
19
+ shippingAddress: 'shipping_address',
20
+ phone: 'phone',
21
+ };
22
+ /** Stripe rejects a fourth. */
23
+ exports.MAX_CHECKOUT_CUSTOM_FIELDS = 3;
24
+ /** Stripe caps a custom label at 50, where a field name may be 191 — hence a question label. */
25
+ exports.MAX_CHECKOUT_LABEL_LENGTH = 50;
26
+ /**
27
+ * What Stripe Checkout can ask for. No `long_text`: its text input caps shorter than that
28
+ * type allows. No `address`: Stripe has no custom-field equivalent, so an address is
29
+ * collected through its own parameter instead.
30
+ */
31
+ exports.CHECKOUT_ELIGIBLE_FIELD_TYPES = ['short_text'];
32
+ function isCheckoutEligible(type) {
33
+ return exports.CHECKOUT_ELIGIBLE_FIELD_TYPES.includes(type);
34
+ }
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.stripeCheckoutCollectionOptions = stripeCheckoutCollectionOptions;
7
+ const logging_1 = __importDefault(require("@tryghost/logging"));
8
+ const field_ports_1 = require("./field-ports");
9
+ /** Keyed on the eligible types, so this and the configure-time rule cannot drift apart. */
10
+ const QUESTION_TYPES = {
11
+ short_text: 'text',
12
+ };
13
+ function askable(question) {
14
+ if (!(0, field_ports_1.isCheckoutEligible)(question.type)) {
15
+ logging_1.default.warn({
16
+ event: { name: 'stripe.checkout.question_skipped' },
17
+ customFieldKey: question.key,
18
+ fieldType: question.type,
19
+ reason: 'unsupported_type',
20
+ }, 'Skipping a Stripe checkout question');
21
+ return false;
22
+ }
23
+ if (question.prompt.length > field_ports_1.MAX_CHECKOUT_LABEL_LENGTH) {
24
+ logging_1.default.warn({
25
+ event: { name: 'stripe.checkout.question_skipped' },
26
+ customFieldKey: question.key,
27
+ promptLength: question.prompt.length,
28
+ reason: 'label_too_long',
29
+ }, 'Skipping a Stripe checkout question');
30
+ return false;
31
+ }
32
+ return true;
33
+ }
34
+ /**
35
+ * Build the collection parameters for a checkout, or nothing at all.
36
+ *
37
+ * Returns an object with no keys when a tier asks for nothing, so a caller can spread it
38
+ * over its session options unconditionally and change nothing.
39
+ */
40
+ function stripeCheckoutCollectionOptions(checkout) {
41
+ const options = {};
42
+ if (!checkout) {
43
+ return options;
44
+ }
45
+ const eligible = checkout.customFields.filter(askable);
46
+ const questions = eligible.slice(0, field_ports_1.MAX_CHECKOUT_CUSTOM_FIELDS);
47
+ if (questions.length < eligible.length) {
48
+ logging_1.default.warn({
49
+ event: { name: 'stripe.checkout.questions_trimmed' },
50
+ asked: questions.length,
51
+ configured: eligible.length,
52
+ }, 'Some Stripe checkout questions were not asked');
53
+ }
54
+ if (questions.length > 0) {
55
+ options.custom_fields = questions.map((question) => ({
56
+ // Ghost sends the custom field's own key as the question's identifier, and Stripe
57
+ // returns the buyer's answer labelled with that same key. Using it in both places
58
+ // means reading an answer is a direct lookup of the field it belongs to, with
59
+ // nothing in between that could map it to the wrong one.
60
+ key: question.key,
61
+ label: { type: 'custom', custom: question.prompt },
62
+ type: QUESTION_TYPES[question.type],
63
+ optional: question.optional,
64
+ }));
65
+ }
66
+ if (checkout.shipping) {
67
+ // The country list is what makes this reach Stripe at all. An empty
68
+ // `shipping_address_collection` form-encodes to nothing, so a request built that
69
+ // way carries no parameter and Stripe accepts it precisely because it was never
70
+ // asked to collect anything — which reads as success and collects no addresses.
71
+ //
72
+ // Defended again here rather than trusted from the settings screen: this is the
73
+ // checkout path, and a malformed configuration must cost the collection rather than
74
+ // throw inside a session build.
75
+ if (checkout.shipping.allowedCountries.length === 0) {
76
+ logging_1.default.warn({
77
+ event: { name: 'stripe.checkout.collection_skipped' },
78
+ port: 'shipping_address',
79
+ reason: 'no_allowed_countries',
80
+ }, 'Skipping a Stripe checkout collection');
81
+ }
82
+ else {
83
+ options.shipping_address_collection = {
84
+ allowed_countries: checkout.shipping.allowedCountries,
85
+ };
86
+ }
87
+ }
88
+ // Unioned with whatever automatic tax asks for. Both want the same thing, so a site
89
+ // running the 2024 tax beta keeps collecting and a site that asked for it starts.
90
+ if (checkout.taxNumber) {
91
+ options.tax_id_collection = { enabled: true };
92
+ }
93
+ if (checkout.phone) {
94
+ options.phone_number_collection = { enabled: true };
95
+ }
96
+ return options;
97
+ }
@@ -2,6 +2,7 @@ const _ = require('lodash');
2
2
  const errors = require('@tryghost/errors');
3
3
  const logging = require('@tryghost/logging');
4
4
  const { canWelcomeEmailReplaceSignupPaidEmail } = require('../../../lib/member-signup-contexts');
5
+ const { collectedByPort } = require('../checkout/completed-session');
5
6
  /** @typedef {import('../../../lib/member-signup-contexts').SignupContext} SignupContext */
6
7
 
7
8
  function isStripeMetadataTrue(value) {
@@ -422,6 +423,11 @@ module.exports = class CheckoutSessionEventService {
422
423
  }
423
424
  }
424
425
 
426
+ // After the subscription work, and deliberately not part of it: a value the member
427
+ // gave us for free must never be able to fail the webhook. A throw here would make
428
+ // Stripe retry the event and risk doing the payment work twice.
429
+ await this.writeCollectedFields(member.id, session);
430
+
425
431
  if (checkoutType !== 'upgrade') {
426
432
  const ghostSignupContext = /** @type {SignupContext | undefined} */ (
427
433
  session.metadata?.ghostSignupContext
@@ -440,4 +446,47 @@ module.exports = class CheckoutSessionEventService {
440
446
  }
441
447
  }
442
448
  }
449
+
450
+ /**
451
+ * This service knows how to read a completed Stripe session. It does not know, and must
452
+ * not know, which custom field any of those values belongs in — that is what a binding
453
+ * decides, so no field key appears anywhere in this code.
454
+ *
455
+ * Nothing here may be fatal: a throw fails the webhook, which makes Stripe retry it and
456
+ * risks doing the payment work twice.
457
+ *
458
+ * @param {string} memberId
459
+ * @param {import('stripe').Stripe.Checkout.Session} session
460
+ */
461
+ async writeCollectedFields(memberId, session) {
462
+ // Stamped at create time. A session predating this feature carries none. Read
463
+ // outside the try so a failure below can name the tier whose answers were lost.
464
+ const tierId = session.metadata?.ghostTierId;
465
+
466
+ try {
467
+ if (!this.deps.labsService.isSet('membersCustomFields')) {
468
+ return;
469
+ }
470
+
471
+ if (!tierId) {
472
+ return;
473
+ }
474
+
475
+ await this.deps.customFieldBindings.writeCollected(
476
+ memberId,
477
+ tierId,
478
+ collectedByPort.parse(session),
479
+ );
480
+ } catch (err) {
481
+ logging.error(
482
+ {
483
+ event: { name: 'stripe_checkout.collected_fields.write_failed' },
484
+ err,
485
+ memberId,
486
+ tierId,
487
+ },
488
+ 'Failed to store the fields a checkout collected',
489
+ );
490
+ }
491
+ }
443
492
  };
@@ -3,6 +3,7 @@ const debug = require('@tryghost/debug')('stripe');
3
3
  const ghostConfig = require('../../../shared/config');
4
4
  const stripe = require('stripe');
5
5
  const i18n = require('../i18n');
6
+ const { stripeCheckoutCollectionOptions } = require('./services/checkout/session-options');
6
7
 
7
8
  /* Stripe has the following rate limits:
8
9
  * - For most APIs, 100 read requests per second in live mode, 25 read requests per second in test mode
@@ -556,6 +557,8 @@ module.exports = class StripeAPI {
556
557
  * @param {string} options.customerEmail
557
558
  * @param {number} options.trialDays
558
559
  * @param {string} [options.coupon]
560
+ * @param {import('../tier-checkout-config').ResolvedCheckout} [options.checkout] What
561
+ * the tier's checkout asks for beyond the payment. Absent, or empty, adds nothing.
559
562
  *
560
563
  * @returns {Promise<ICheckoutSession>}
561
564
  */
@@ -636,6 +639,32 @@ module.exports = class StripeAPI {
636
639
  hasCustomer: Boolean(customerId),
637
640
  });
638
641
 
642
+ // Applied after automatic tax so the two agree about `tax_id_collection`: both ask
643
+ // for the same thing, and a site with either reason to collect gets it. Nothing is
644
+ // added for a tier that has configured nothing, so an unconfigured site's request
645
+ // is unchanged.
646
+ Object.assign(stripeSessionOptions, stripeCheckoutCollectionOptions(options.checkout));
647
+
648
+ // Stripe refuses to collect a tax id for a customer it may not rename:
649
+ //
650
+ // Tax ID collection requires updating business name on the customer. To enable tax
651
+ // ID collection for an existing customer, please set `customer_update[name]`.
652
+ //
653
+ // Measured against the live API rather than read — `pnpm --filter @tryghost/e2e
654
+ // stripe:probe` — because the same probe shows shipping and phone collection need no
655
+ // such thing. Every signed-in checkout carries a customer, so without this a tier
656
+ // that collects a tax number cannot be bought by an existing member.
657
+ //
658
+ // Merged rather than assigned: automatic tax sets this too, and whichever ran first
659
+ // must not lose its keys. Still never set without a customer, which is the shape
660
+ // that took the tax beta down.
661
+ if (stripeSessionOptions.tax_id_collection && customerId) {
662
+ stripeSessionOptions.customer_update = {
663
+ ...stripeSessionOptions.customer_update,
664
+ name: 'auto',
665
+ };
666
+ }
667
+
639
668
  const session = await this._stripe.checkout.sessions.create(stripeSessionOptions);
640
669
 
641
670
  return session;
@@ -10,6 +10,7 @@ const InvoiceEventService = require('./services/webhook/invoice-event-service');
10
10
  const CheckoutSessionEventService = require('./services/webhook/checkout-session-event-service');
11
11
  const ChargeRefundedEventService = require('./services/webhook/charge-refunded-event-service');
12
12
  const memberWelcomeEmailService = require('../member-welcome-emails/service');
13
+ const customFields = require('../members-custom-fields');
13
14
 
14
15
  /**
15
16
  * @typedef {object} IStripeServiceConfig
@@ -133,6 +134,12 @@ module.exports = class StripeService {
133
134
  memberWelcomeEmailService.init();
134
135
  return memberWelcomeEmailService.api.isMemberWelcomeEmailActive('paid');
135
136
  },
137
+ labsService: labs,
138
+ // A getter because the custom field services are built during boot: reading the
139
+ // binding at construction would capture the empty value it had beforehand.
140
+ get customFieldBindings() {
141
+ return customFields.bindings;
142
+ },
136
143
  });
137
144
 
138
145
  const chargeRefundedEventService = new ChargeRefundedEventService({