[pull] main from TryGhost:main - #1441
Merged
Merged
Conversation
ref https://linear.app/ghost/issue/BER-3852 Gift checkout was only discoverable through direct Portal links, leaving eligible visitors and members without an in-product path. This adds guarded promotion entry points while keeping checkout availability independent from merchandising controls. - Added independent signup and account promotion settings with Admin controls and live preview support - Showed promotions only when the feature, persisted setting, and a giftable paid offering are available - Limited account promotion to paid and complimentary members, excluding gift recipients - Preserved direct `#/portal/gift` access when either promotion setting is disabled - Added settings persistence coverage and translator context for the new Portal copy
) no ref Moves the gift flush scheduler into the scheduling adapter layer as `SignedFlushScheduler`. It keeps time deduplication, delayed flush timing, and queue rebuilds at boot and after scheduler-key rotation in one place, while gift delivery and reminder scheduling provide their endpoint and pending times. Extracts `buildSignedJob` for constructing signed Admin API callbacks and reuses it in automations without changing its polling, jitter, or idempotency behaviour.
Ref https://ghost.slack.com/archives/C09D3RD4M88/p1787592510553609 Kept the gift delivery calendar anchored and consistently sized when it flips above the field and buyers browse between months.
no-issue With reuseConnection enabled (the default), every Redis cache adapter in the process shares one singleton store, created with whichever adapter happened to be instantiated first at boot. Because writes never passed a per-call TTL, cache-manager fell back to that store's creation-time TTL, so the first adapter's TTL was silently applied to every cache feature.
ref https://linear.app/ghost/issue/HKG-1975 The cleanup body lived in a closure over the gifts service's init() locals, so it couldn't be handed to a job handler. GiftService already owns three of the four phases and the delivery service dependency, so the only wiring change is widening its Pick to include recoverPending. The phases are moved verbatim - this is preparation for the jobs-service migration, not a behaviour change.
ref https://linear.app/ghost/issue/HKG-1975 The legacy bree worker did no work: it posted a domain event back to the main thread and reported "done" immediately, so job success and duration were meaningless. Dispatching a CleanGiftsJob through the jobs service runs the same code on the same thread, but job.completed now fires when cleanup actually finishes. The worker, the domain event and the legacy registration go in the same commit so the job is never registered in both systems. Scheduling moves to initBackgroundServices because gifts init() runs before the jobs service exists. The old started/completed logs are replaced by a structured clean_gifts.completed event whose counts start at null, not zero, so a phase whose swallowed error skipped it doesn't look idle.
ref https://linear.app/ghost/issue/GVA-911/ This commit wires up the async 1-click export to a configurable webhook url, behind a feature flag. When `hostSettings.export.webhookUrl` is configured, `POST /ghost/api/admin/exports/` posts a signed export event to the host's webhook and returns 202; the host builds a full archive and emails the site owner a download link. ## API contract **Endpoint**: `POST /ghost/api/admin/exports/` Available to Owner + Administrator staff users. ### Request #### Body ```json { "type": "export", "siteId": "<hostSettings:siteId>", "components": {"content": true, "members": true, "analytics": true, "themes": true, "routes": true, "media": false} } ``` - `{"components": {...}}`: keys a subset of `content | members | analytics | themes | routes | media`, boolean values, at least one true - the host emails the download link to the site owner; the payload carries no recipient #### Auth headers | Header | Value | |---|---| | `X-Ghost-Request-Timestamp` | `Date.now().toString()` (ms) | | `X-Ghost-Signature` | `base64( HMAC-SHA256( secret, "{timestamp}:{rawBody}" ) )` | The signing key lives at `hostSettings:export:webhookSecret`. ### Responses - 202 Accepted (empty body) on success - 404 when the webhook URL isn't configured - 400 when the URL is set but the secret is missing - 502 when the forward fails
ref https://linear.app/ghost/issue/BER-3892/ Gift emails currently use the default sender without a reply-to address, so replies do not reliably reach site owners. This uses the configured member support address, including its existing default-address fallback, for buyer confirmations, recipient deliveries, and reminder emails. It covers both transactional mail and direct bulk Mailgun delivery.
ref https://linear.app/ghost/issue/BER-3888/ui-fixup Gift subscriptions now display one year instead of twelve months, emphasise the full duration, and omit the colon from the redemption email button.
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 : )