# 25-Feb-2026 — secure and harden Environment Setup and Backup & Restore [ref #146](https://github.com/nbarrett/ngx-ramblers/issues/146)

## [build 499](https://github.com/nbarrett/ngx-ramblers/actions/runs/22418830262) — [commit 8ea4a2e](https://github.com/nbarrett/ngx-ramblers/commit/8ea4a2efc262baadd2710c339b333cdc869b463f)

_____

## Platform admin gating
- Backup & Restore and Environment Setup now check `PLATFORM_ADMIN_ENABLED` on
init and display a consistent "Not Available" alert (icon + bold title) when
the flag is absent, matching the alert style used across the admin section
- Backup & Restore skips loading environments, backups, sessions and the
WebSocket connection when the flag is absent, avoiding unnecessary API calls
- Added the ngx-ramblers environment entry to the EnvironmentsConfig DB document
with `PLATFORM_ADMIN_ENABLED=true` in its secrets block so the flag survives
future deploys via `loadSecretsForEnvironmentFromDatabase`
## Setup API-key authentication
- Environment Setup routes now accept requests authenticated by either a valid
admin JWT (member/content/file/walk/social/treasury/finance admin roles) or
the `x-setup-api-key` header, enabling logged-in admins to use the page
without a separate setup key
- `isAdminRequest()` added to server routes — verifies the Bearer token with
`jsonwebtoken` and checks any admin-role claim before granting access
- `EnvironmentSetupService` gains a `setupApiKey` field and an `opts` getter;
all HTTP calls now forward the key in `x-setup-api-key` when present
- Component gains `requiresApiKey` / `setupApiKeyValue` / `setupApiKeyEntered`
state and a `submitSetupApiKey()` method so the UI can prompt for the key
when the server signals it is required (`status.requiresApiKey`)
## Defaults loading improvements
- `loadDefaults()` now loads system config first (normal session auth, never
401) and then loads environment defaults separately so a 401 on the defaults
endpoint does not prevent the Ramblers API key from being pre-filled
- `EnvironmentDefaults` model extended with `ramblers.apiKey` field
- `/defaults` endpoint populates `ramblers.apiKey` from
`national.walksManager.apiKey` in the system config so the Ramblers API key
is offered as a default without manual entry
## Mongoose reconnection fix
- `closeMigrationConnection()` calls `mongoose.disconnect()` after running
migrations, which left subsequent operations (`seedBrevoTemplatesFromLocal` ->
`configuredBrevo` -> `config.findOne`) failing with "Client must be connected
before running operations"
- Added `ensureMongoConnection()` after `initialiseDatabase()` returns so
mongoose reconnects to the main database before Brevo template population runs
## GitHub Secrets panel (Environment Settings → GitHub Secrets sub-tab)
- New `EnvironmentGitHubSecrets` standalone component shows the GitHub
`CONFIGS_JSON` secret staleness relative to the database, with per-environment
diff detail (new / removed / changed fields) and a one-click Push button
- `GET /api/environment-setup/github/status` compares DB environments against
the live `CONFIGS_JSON` value; matches by name first then appName fallback to
avoid cross-matching where multiple DB documents share the same fly.io app
- `POST /api/environment-setup/github/push` pushes DB → GitHub directly without
touching configs.json; after a successful push, `process.env.CONFIGS_JSON` is
updated in-process so subsequent status checks reflect what was pushed
- On first status check locally (no `CONFIGS_JSON` env var), the value is
initialised from the DB — same runtime behaviour as production where fly.io
injects it at startup — eliminating configs.json as a third piece of state
- `transformDatabaseToDeployConfig` now filters out orphan DB environment
documents (no flyio config), deduplicates by appName (first occurrence wins),
and is exported for reuse in the status route
- `EnvironmentSettingsSubTab.GITHUB` added; heading uses `with-vendor-logo`
style with the GitHub FA brand icon; `.thumbnail-heading.with-vendor-logo`
top offset corrected to -34px in frames.sass
## Dockerfile: GitHub CLI
- `gh` CLI installed in Docker image so the GitHub Secrets panel can fetch
secret metadata and push `CONFIGS_JSON` from the deployed environment
- `GH_TOKEN` and `PLATFORM_ADMIN_ENABLED=true` set as fly.io secrets on the
ngx-ramblers (staging) app to authenticate `gh` and enable the admin pages