# 19-Apr-2026 — centralise worker secrets, harden paste flows, and bypass headless-bot detection

## [build 615](https://github.com/nbarrett/ngx-ramblers/actions/runs/24615893808) — [commit b70e39a](https://github.com/nbarrett/ngx-ramblers/commit/b70e39a18a89401e6673f5bd958a2c3744cfdb7c)

_____

## Centralise worker wiring in Global Application Secrets

`INTEGRATION_WORKER_URL`, `INTEGRATION_WORKER_SHARED_SECRET` and
`INTEGRATION_WORKER_ENCRYPTION_KEY` are the same value for every env —
they belong in the root `config.environments.value.secrets` section
(the Global Application Secrets panel in Admin), not sprinkled across
each `environments[].secrets`. `buildSecretsFromDatabaseConfig` already
merges root secrets into every env deploy, so no code change is needed
for the shared trio to propagate.

`INTEGRATION_WORKER_CALLBACK_BASE_URL` genuinely differs per env (each
website has its own fly URL). Auto-derive it in
`buildSecretsFromDatabaseConfig` from `envConfig.flyio.appName` when no
explicit value is set, so any new env is worker-ready on first deploy
without manual per-env secret curation.

Data already migrated in staging DB: three shared keys added under
globals; `staging`, `ekwg`, `ekwg-dev-2-staging` per-env duplicates
removed. Each now only carries `INTEGRATION_WORKER_CALLBACK_BASE_URL`.

## Paste-URL hardening (CMS dynamic content text field)

`isBase64Image` at `url.service.ts` already accepts any `data:` URI
(fixes GIF preview `GET /api/aws/s3/data:image/...` errors), and the
image cropper enables save for non-croppable files (GIFs) with
`awsFileName` falling back to `originalFile.name`.

`PageContentService.allAlbumIndexParents` now returns early for an
undefined `childPath` (happens during initial CMS page load before
`pageContent` resolves) and guards against non-string `contentPath`
values with `isString` from `es-toolkit/compat`, fixing
`TypeError: Cannot read properties of undefined (reading 'startsWith')`
reported in the dynamic content editor.

## Worker browser fingerprint

`integration-worker-browser-routes` now creates pages via a
`browser.newContext({ userAgent, viewport, locale, timezoneId,
extraHTTPHeaders })` helper rather than `browser.newPage()` directly,
so sites behind Cloudflare/Akamai (e.g. ramblers.org.uk) don't serve
403 Forbidden on fingerprint. Applied to both `html-fetch` and
`flickr-user-albums` routes.

## Misc

`navigate-with-dom-loaded` task added in the previous commit is used
declaratively from `walks-upload.ts`; removed the explanatory comment
block to comply with the project's no-comments rule.