[pull] main from TryGhost:main - #1458
Merged
Merged
Conversation
refs https://linear.app/ghost/issue/DES-1482 https://linear.app/ghost/issue/DES-1483 https://linear.app/ghost/issue/DES-1484 https://linear.app/ghost/issue/DES-1485 Admin 7.0 → Page chrome, delivered incrementally behind a private flag. --------- Co-authored-by: Steve Larson <9larsons@gmail.com>
Subscription attribution URLs come from public signup and checkout URL history, which the server does not scheme-validate, so a member can end up with a javascript: URL stored as their own attribution. The member detail view rendered it straight into an anchor, unlike the sidebar and activity feed, which already pass attribution URLs through the isSafeHref guard. Current browsers refuse to run a javascript: URL opened in a new tab, which is how this link opens, so it was not exploitable in practice, but the page URL now takes the same guard for consistency: unsafe URLs render as text while site-relative and http(s) URLs stay links.
closes https://linear.app/ghost/issue/NY-1549 This is a dev-only change. Tinybird data is now persisted across restarts. This is adapted from [Tinybird Local's docs][0]. Manual test ----------- I did the following twice (after running `pnpm docker:clean`): 1. `pnpm dev:analytics` 1. `pnpm data:analytics:generate 100` 1. Verify that analytics appear in the UI 1. Stop the server started in Step 1 1. `pnpm dev:analytics` (again) 1. Look at the analytics in the UI Before this change, the analytics disappeared in the final step. After this change, the analytics persist. [0]: https://www.tinybird.co/docs/forward/core-concepts/tinybird-local#run-with-docker-compose
no ref - tinybird local is a huge docker image, building a distilled one allows us to save on runner disk space
ref https://linear.app/ghost/issue/BER-3872 A Stripe checkout can be started with nothing but an email address, and typing an email is not proof of owning it. The webhook wrote whatever the checkout collected onto whichever member the address resolved to, so anyone could overwrite a real member's stored answers by checking out with that member's email. The write is now gated: values still land on the member the webhook itself just created, since that record holds nothing the buyer didn't supply, but a pre-existing member is only written when the session was started by a signed-in member.
no ref - skip lockfile trust verification in jobs downstream of setup - cache lockfile verification file to speed up verification - reduce duplicate steps across jobs with standardized composite action
no ref - increase max worker count when possible in github action runners - speed up theme editor codemirror tests
ref BER-3869 A filterable field carried one hand-written translator that decided three things at once: where its value sits in the query, what the comparison means, and how that gets written down. The three varied independently but had to be re-implemented together, so "what contains means" was written out again for every field offering it, and any drift between the writing and reading halves went unnoticed until a value came back wrong. A field now names an addressing and a vocabulary, and the pairing is composed rather than restated. Declaring a field also carried only part of what a field is. Its icon lived in a switch in the picker, its place in the menu was an append somewhere else, and its operator wording came from a map shared by every field whatever its type. All of that moved into the declaration, where the compiler can check it: an operator a field's vocabulary cannot write is rejected where it is written rather than dropped later, an icon nobody drew fails the build, and a field nobody placed in a group fails naming the field. Three rules the engine keeps rather than asks anyone to remember. A key is a path, so a question about it is asked in steps and `newsletters.slug` is not a prefix of `newsletters.slugfoo`. Whether a filter names a field is answered by parsing it, because only the parser knows which characters are structure and which are somebody's data. And a filter is only read once the site's own definitions have arrived, since reading one early answers a wider question than was asked and then saves that answer over what the publisher wrote.
ref BER-3869 The unit tests prove a predicate survives being written and read back, but not that the filter a publisher builds in the picker is the one the members list answers. These drive the real UI: define a custom field, filter on it, save the filter as a segment, reopen it, and check the pill and the results both come back saying what was asked. That is the trip a saved segment actually makes, and nothing below this level covers it.
ref BER-3869 Subscribing to a newsletter is written as being on the list and not having bounced, joined by and; unsubscribing is the denial of exactly that, joined by or. Reading one only looked at whether the list was named and negated, and took any arrangement of the remaining parts to mean the same thing. Being on the list or having bounced is a wider set of members than being on it and not having bounced, so a filter written that way was answered as though it said something narrower, and saving the page then wrote that narrower version over it. The pair is now recognised only as one of the two shapes that mean it, which is what the subscription vocabulary next door already required of the same three parts. Anything else is left unread, the way any clause this build does not recognise is.
no ref All I did was run this: ```sh npx skills add tinybirdco/tinybird-agent-skills ```
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 : )