{"id":"69fd1f5e4c4c5172dd7c757b","title":"2026 05 08","path":"how-to/committee/release-notes/2026-05-08","contentMarkdown":"# 08-May-2026 — GPX downloads, per-list unsubscribe redirect, drop runtime zone warning [#18](https://github.com/nbarrett/ngx-ramblers/issues/18)\n\n## [build 640](https://github.com/nbarrett/ngx-ramblers/actions/runs/25527166309) — [commit 2ba17f6](https://github.com/nbarrett/ngx-ramblers/commit/2ba17f6ac4b9ec21ef0c4c31913ca0ae2bc6ba55)\n\n_____\n\nThree independent strands bundled per request.\n\n## Walks: GPX route download in related links\n\nAdds a `relatedLinkShowGpx` toggle on the Walk Config \"Related Links\" tab (default true) and renders a \"Download GPX route\" link when a walk has a `gpxFile`. The link resolves remote URLs vs `resourceRelativePathForAWSFileName` correctly and uses `originalFileName` (or `awsFileName` fallback) as the download attribute, sitting alongside the existing OS Maps / Meetup / What3Words / Venue links.\n\n## Mail: branded unsubscribe per-list redirect (ref #18)\n\nReplaces Brevo's default footer unsubscribe placeholder with a server-issued `UNSUBSCRIBE_URL` injected into `memberMergeFields` at campaign-creation time. The URL points at a new `GET /api/mail/unsubscribe/from-list` endpoint that:\n\n- looks the email up in Brevo to confirm it is on the target list (rejecting stale links cleanly with a 400)\n- builds a signed unsubscribe token tied to the listId via `buildUnsubscribeToken`\n- redirects to the site's branded unsubscribe page with the token\n\n\\`contactUsParentSegment\\` is now exported so create-campaign can use it to derive the redirect path. The previous footer template (\"If you wish to unsubscribe from our emails, click {here}\") is no longer set, since campaigns now carry the URL via the merge field, giving recipients a one-click route into the branded flow that keeps the listId context.\n\n## Cloudflare: drop runtime zone warning (ref #256)\n\nThe Inbound Forwarding tab carried two runtime warnings (domain mismatch, stale deploy) added in #256. Both relied on \\`cloudflareZoneBaseDomain\\` and \\`perEnvironmentDbZoneId\\` exposed via \\`nonSensitiveCloudflareConfig\\`, but the underlying signal was never truthful: \\`secrets.ts:117\\` always pins the encrypted env var's \\`baseDomain\\` to the global, and the deployed child's own Mongo doesn't carry a copy of staging's \\`environments\\` doc, so \\`perEnvironmentDbZoneIdForRunningApp\\` returned empty in production anyway. Setting a per-env zoneId in staging didn't clear the warning even after several deploys.\n\nThe presence or absence of a per-env Cloudflare zoneId is itself the whole contract:\n\n- per-env zoneId set -> standalone domain -> rules go to that zone\n- no per-env zoneId -> subdomain of the central baseDomain -> rules go to the central zone\n\nBoth states are correct by construction; the only invalid configuration (\"standalone domain but no per-env zoneId\") is a setup-time mistake, not a runtime concern, and belongs in Environment Management validation (follow-up).","contentHtml":"<h1>08-May-2026 — GPX downloads, per-list unsubscribe redirect, drop runtime zone warning <a href=\"https://github.com/nbarrett/ngx-ramblers/issues/18\">#18</a></h1>\n<h2><a href=\"https://github.com/nbarrett/ngx-ramblers/actions/runs/25527166309\">build 640</a> — <a href=\"https://github.com/nbarrett/ngx-ramblers/commit/2ba17f6ac4b9ec21ef0c4c31913ca0ae2bc6ba55\">commit 2ba17f6</a></h2>\n<hr>\n<p>Three independent strands bundled per request.</p>\n<h2>Walks: GPX route download in related links</h2>\n<p>Adds a <code>relatedLinkShowGpx</code> toggle on the Walk Config &quot;Related Links&quot; tab (default true) and renders a &quot;Download GPX route&quot; link when a walk has a <code>gpxFile</code>. The link resolves remote URLs vs <code>resourceRelativePathForAWSFileName</code> correctly and uses <code>originalFileName</code> (or <code>awsFileName</code> fallback) as the download attribute, sitting alongside the existing OS Maps / Meetup / What3Words / Venue links.</p>\n<h2>Mail: branded unsubscribe per-list redirect (ref #18)</h2>\n<p>Replaces Brevo&#39;s default footer unsubscribe placeholder with a server-issued <code>UNSUBSCRIBE_URL</code> injected into <code>memberMergeFields</code> at campaign-creation time. The URL points at a new <code>GET /api/mail/unsubscribe/from-list</code> endpoint that:</p>\n<ul>\n<li>looks the email up in Brevo to confirm it is on the target list (rejecting stale links cleanly with a 400)</li>\n<li>builds a signed unsubscribe token tied to the listId via <code>buildUnsubscribeToken</code></li>\n<li>redirects to the site&#39;s branded unsubscribe page with the token</li>\n</ul>\n<p>`contactUsParentSegment` is now exported so create-campaign can use it to derive the redirect path. The previous footer template (&quot;If you wish to unsubscribe from our emails, click {here}&quot;) is no longer set, since campaigns now carry the URL via the merge field, giving recipients a one-click route into the branded flow that keeps the listId context.</p>\n<h2>Cloudflare: drop runtime zone warning (ref #256)</h2>\n<p>The Inbound Forwarding tab carried two runtime warnings (domain mismatch, stale deploy) added in #256. Both relied on `cloudflareZoneBaseDomain` and `perEnvironmentDbZoneId` exposed via `nonSensitiveCloudflareConfig`, but the underlying signal was never truthful: `secrets.ts:117` always pins the encrypted env var&#39;s `baseDomain` to the global, and the deployed child&#39;s own Mongo doesn&#39;t carry a copy of staging&#39;s `environments` doc, so `perEnvironmentDbZoneIdForRunningApp` returned empty in production anyway. Setting a per-env zoneId in staging didn&#39;t clear the warning even after several deploys.</p>\n<p>The presence or absence of a per-env Cloudflare zoneId is itself the whole contract:</p>\n<ul>\n<li>per-env zoneId set -&gt; standalone domain -&gt; rules go to that zone</li>\n<li>no per-env zoneId -&gt; subdomain of the central baseDomain -&gt; rules go to the central zone</li>\n</ul>\n<p>Both states are correct by construction; the only invalid configuration (&quot;standalone domain but no per-env zoneId&quot;) is a setup-time mistake, not a runtime concern, and belongs in Environment Management validation (follow-up).</p>\n"}