Skip to content

[pull] main from TryGhost:main - #1448

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

[pull] main from TryGhost:main#1448
pull[bot] merged 4 commits into
code:mainfrom
TryGhost:main

Conversation

@pull

@pull pull Bot commented Aug 27, 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 : )

A tier could say what its checkout should collect and where each answer
belongs, and nothing acted on it. This connects the two ends: the
session Ghost creates now asks for what the tier configured, and the
completed session's answers are written into the member's fields.

What comes back is read as ports and values, so nothing outside the
bindings knows a field key, and each value is written in its own
transaction — atomic across the parts of an address, but no wider,
because a postcode a processor formatted differently must not cost the
phone number beside it. None of it may fail the webhook, which is busy
creating the member and linking the subscription.

The limits a checkout page enforces were measured against the live API
rather than read from the reference, which disagreed with it in three of
five probes. One of those measurements matters on its own: Stripe will
not collect a tax number for a customer it may not rename, so a tier
that asked for one could not be bought by a member who already had a
Stripe customer.

A site that has configured nothing sends a request identical to the one
it sent before, and the whole path stays behind the members custom
fields flag.

ref https://linear.app/ghost/issue/BER-3872
The scripts that capture fixtures from Stripe and probe what it accepts
import the request builder out of ghost/core, so that they send what
Ghost sends. Nothing typechecked them, and they had already rotted
against a change to that builder without anything noticing. The e2e
package now declares the dependency it typechecks against, so the build
that runs before the fixture check pulls it in, and the check itself
runs through nx rather than as steps written into one workflow. A rule
about how a package is built belongs in the package rather than in the
one place that happens to build it. Rewriting the capture script leaves
the checkout session it used to record behind, unread by anything, so
it goes too.

ref https://linear.app/ghost/issue/BER-3872
ref https://linear.app/ghost/issue/BER-3872

A log line is only worth writing if an operator can find it again, and
these could not be found. Each glued its context into a sentence, so a
decode regression dropping a stored value on every member read, an import
that rejected half a file, and an export that had slowed down all read as
prose rather than as one named event with numbers hanging off it. Two said
less than that, handing an error straight to the logger with nothing to
say what had been swallowed, which is the whole difficulty with a
best-effort write: it is invisible unless the line that gives it up says
what it gave up. All of them now carry a dotted event name, a static
message, and their context in named fields, so the question can be put to
a fleet rather than read out of one server's scrollback.
A row's custom field values are validated before its transaction opens, so
by the time they are written there is nothing left in them that can be
refused. A write that fails there is the database saying no to us, not to
the publisher, and it was being handled as though it were the publisher's:
the driver's message, query text and all, went into the error file they open
next to their spreadsheet, and nobody who could act on it was told. The
failure still fails the row, because half a member is worse than none, but
the publisher now reads a sentence about what did not save and the original
goes to the error tracker, where a lock timeout or a constraint is something
someone can go and look at.

ref https://linear.app/ghost/issue/BER-3872
@pull pull Bot locked and limited conversation to collaborators Aug 27, 2026
@pull pull Bot added the ⤵️ pull label Aug 27, 2026
@pull
pull Bot merged commit 0deb391 into code:main Aug 27, 2026
3 checks 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.

1 participant