Skip to content

[pull] main from TryGhost:main - #1404

Merged
pull[bot] merged 7 commits into
code:mainfrom
TryGhost:main
Aug 11, 2026
Merged

pull[bot] merged 7 commits into
code:mainfrom
TryGhost:main

Conversation

@pull

@pull pull Bot commented Aug 11, 2026 •

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

9larsons and others added 7 commits August 10, 2026 17:22
no ref

First slice of the settings NiceModal burn-down (follows the router swap
#29780 and un-portal #29789).

`ConfirmationModal` and `LimitModal` were NiceModal-shown from **54 call
sites across 27 files** — the bulk of settings' remaining NiceModal
usage. They now go through a settings-local `ConfirmationProvider`:
ref https://linear.app/ghost/issue/BER-3816

A member import too large to run inside the request is accepted straight away and
reported by email once the background job finishes, and when that job failed no
email was ever sent. The publisher was told to expect one and nothing ever came,
leaving a failed import indistinguishable from one still running. Nobody else
found out either, since a queued import runs in-process where a thrown error
never reaches the error tracker.

The import now runs in three phases and each says what it may do. Gathering what
the rows are written against is the only phase allowed to throw, so a throw
means nothing was written; writing reports rather than throws, since once a row
has committed an import that failed halfway is not one that never ran; and
settling up afterwards guards each step on its own, so a failed lookup cannot
skip archiving a Stripe price that nothing else will ever clean up. The job then
always tells the publisher something, sending a distinct email for an import
that could not be completed at all.

Whether a row failed for a reason the publisher can act on is not asked. A row
that failed is a row that failed, and it goes into the report they receive with
the reason beside it. Nothing inspects those errors, which is also why a row's
values -- which a database driver inlines into the message of the statement that
failed -- cannot reach a log or an error tracker from here. What does reach them
is the run itself failing, a cleanup that did not finish, or a notification that
could not be sent, none of which carry a row.
no ref
- Added an additive Shade `CodeEditor` with lazy CodeMirror loading.
- Adopted it only for the header and footer fields on the flagged React
tag-details screen.
- Added Storybook states for default, focused, error, and disabled
behavior.
- Portalled Shade autocomplete into a transparent body-level host so
suggestions escape clipped editor and accordion containers.
- Connected hint and error copy to the editable element and reset shared
focus state when a focused editor unmounts.
- Added real-browser coverage for editing, saving, autocomplete
visibility, positioning stability, and portal paint safety.
ref BER-3863

An investigation into whether a member could reach custom fields through the
members API found that they cannot, and never could. Every member-facing
surface serialises from a field whitelist that predates the feature, and the
member update path drops unknown keys twice before it reaches any custom-field
code. Nothing asserted that, so these two tests pin it: a member's own response
carries no custom fields, and custom fields a member sends are dropped while the
rest of the update still applies, the same way email already behaves on that
endpoint.
ref https://linear.app/ghost/issue/BER-3862

A key is typed by hand into member filters, CSV columns, email replacement
strings and, before long, themes and editor cards. The hyphen a slug separates
with is the one character those readers disagree about: NQL will not parse a
hyphen in a property path, and a replacement string matches word characters
only, so a hyphenated field reaches the reader as literal text with nothing to
say it was never substituted. The convention contradicted itself as well, since
the parts of a composite field were already underscored and a name typed with
underscores kept them, leaving a single export column carrying both.

Underneath that the format had no definition of its own. It was whatever slugify
produced, so a rule a growing number of surfaces depend on lived in a helper that
answers to URLs and could widen on a version bump. The characters a key may
contain are now stated where its readers are known, as an allowlist rather than a
list of things to strip out, and the libraries keep only the transliteration and
invisible-character stripping they own. Trimming the ends falls out of that rule
and makes __proto__ unmintable under every spelling, so it no longer needs
reserving alongside constructor.

A key is minted once and never changes, so a definition created earlier keeps its
old key for good, and rewriting one in place would leave its stored values and
every reference to it pointing somewhere else. Those definitions are discarded
with their values instead: custom fields sit behind a private flag and have never
been released, so only a site that deliberately opted in can hold one, and
re-creating the field re-mints the key. The migration measures a key against the
shape this release mints rather than looking for a hyphen, because the previous
minting passed underscores through untouched and the definitions endpoint shipped
four days before the reserved-key guard did.
no ref
- Clear populated CodeMirror fields through their own `ControlOrMeta+A`
and Backspace key handling.
- Wait for the empty document before filling each replacement, then
verify the rendered value before saving.
- Reuse the expected replacement values in the exact request-body
assertions.
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [@tanstack/react-query](https://tanstack.com/query)
([source](https://redirect.github.com/TanStack/query/tree/HEAD/packages/react-query))
| [`5.101.2` →
`5.101.4`](https://renovatebot.com/diffs/npm/@tanstack%2freact-query/5.101.2/5.101.4)
|
![age](https://developer.mend.io/api/mc/badges/age/npm/@tanstack%2freact-query/5.101.4?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@tanstack%2freact-query/5.101.2/5.101.4?slim=true)
|

---

### Release Notes

<details>
<summary>TanStack/query (@&#8203;tanstack/react-query)</summary>

###
[`v5.101.4`](https://redirect.github.com/TanStack/query/blob/HEAD/packages/react-query/CHANGELOG.md#51014)

[Compare
Source](https://redirect.github.com/TanStack/query/compare/@tanstack/react-query@5.101.3...@tanstack/react-query@5.101.4)

##### Patch Changes

- Updated dependencies \[]:
-
[@&#8203;tanstack/query-core](https://redirect.github.com/tanstack/query-core)@&#8203;5.101.4

###
[`v5.101.3`](https://redirect.github.com/TanStack/query/blob/HEAD/packages/react-query/CHANGELOG.md#51013)

[Compare
Source](https://redirect.github.com/TanStack/query/compare/@tanstack/react-query@5.101.2...@tanstack/react-query@5.101.3)

##### Patch Changes

- Updated dependencies
\[[`7e3c822`](https://redirect.github.com/TanStack/query/commit/7e3c822a10896f41a8f1031c16b85096277af677)]:
-
[@&#8203;tanstack/query-core](https://redirect.github.com/tanstack/query-core)@&#8203;5.101.3

</details>

---

### Configuration

📅 **Schedule**: (in timezone Etc/UTC)

- Branch creation
  - Only on Sunday and Saturday (`* * * * 0,6`)
- Between 11:00 PM and 11:59 PM, Monday through Friday (`* 23 * * 1-5`)
- Between 12:00 AM and 04:59 AM, Monday through Saturday (`* 0-4 * *
1-6`)
- Automerge
  - Only on Sunday and Saturday (`* * * * 0,6`)
- Between 11:00 PM and 11:59 PM, Monday through Friday (`* 23 * * 1-5`)
- Between 12:00 AM and 04:59 AM, Monday through Saturday (`* 0-4 * *
1-6`)

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Mend
Renovate](https://redirect.github.com/renovatebot/renovate).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yODAuMyIsInVwZGF0ZWRJblZlciI6IjQzLjI4MC4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: tryghost-renovate[bot] <269725441+tryghost-renovate[bot]@users.noreply.github.com>
@pull pull Bot locked and limited conversation to collaborators Aug 11, 2026
@pull pull Bot added the ⤵️ pull label Aug 11, 2026
@pull
pull Bot merged commit de65389 into code:main Aug 11, 2026
1 check passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants