01-Mar-2026 — admin: stale-while-revalidate area cache, skip migration check on password reset, and centralise admin paths #146
build 506 — commit 089a5e8
- Fix Fly.io shared IPv4 allocation using sharedIpAddress fallback for known GraphQL API bug
- Wire notification configs to built-in processes (forgot-password, walks, expenses, contact-us)
- Assign admin user to committee roles (membership, support) for email sender resolution
- Register admin as Brevo sender during environment creation
- Add admin password reset button to Modify Environment flow
- Allow password reset route to bypass maintenance mode guard
- Add seed endpoints for sample pages, notification configs, and Brevo templates
- Extract shared helpers: toGroupShortName, cleanIncorrectPageContent, runMigrations, registerBrevoSender
- Make notification config seeding idempotent with upsert pattern
- Fix arrow-parens lint violations across all server TypeScript files
Platform admin gating
- Backup & Restore and Environment Setup now check
PLATFORM_ADMIN_ENABLEDon 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=truein its secrets block so the flag survives future deploys vialoadSecretsForEnvironmentFromDatabase
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-keyheader, enabling logged-in admins to use the page without a separate setup key isAdminRequest()added to server routes — verifies the Bearer token withjsonwebtokenand checks any admin-role claim before granting accessEnvironmentSetupServicegains asetupApiKeyfield and anoptsgetter; all HTTP calls now forward the key inx-setup-api-keywhen present- Component gains
requiresApiKey/setupApiKeyValue/setupApiKeyEnteredstate and asubmitSetupApiKey()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
- and then loads environment defaults separately so a 401 on the defaults endpoint does not prevent the Ramblers API key from being pre-filled
EnvironmentDefaultsmodel extended withramblers.apiKeyfield/defaultsendpoint populatesramblers.apiKeyfromnational.walksManager.apiKeyin the system config so the Ramblers API key is offered as a default without manual entry
Mongoose reconnection fix
closeMigrationConnection()callsmongoose.disconnect()after running migrations, which left subsequent operations (seedBrevoTemplatesFromLocal->configuredBrevo->config.findOne) failing with "Client must be connected before running operations"- Added
ensureMongoConnection()afterinitialiseDatabase()returns so mongoose reconnects to the main database before Brevo template population runs
GitHub Secrets panel (Environment Settings → GitHub Secrets sub-tab)
- New
EnvironmentGitHubSecretsstandalone component shows the GitHubCONFIGS_JSONsecret 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/statuscompares DB environments against the liveCONFIGS_JSONvalue; matches by name first then appName fallback to avoid cross-matching where multiple DB documents share the same fly.io appPOST /api/environment-setup/github/pushpushes DB → GitHub directly without touching configs.json; after a successful push,process.env.CONFIGS_JSONis updated in-process so subsequent status checks reflect what was pushed- On first status check locally (no
CONFIGS_JSONenv 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 transformDatabaseToDeployConfignow filters out orphan DB environment documents (no flyio config), deduplicates by appName (first occurrence wins), and is exported for reuse in the status routeEnvironmentSettingsSubTab.GITHUBadded; heading useswith-vendor-logostyle with the GitHub FA brand icon;.thumbnail-heading.with-vendor-logotop offset corrected to -34px in frames.sass
Dockerfile: GitHub CLI
ghCLI installed in Docker image so the GitHub Secrets panel can fetch secret metadata and pushCONFIGS_JSONfrom the deployed environmentGH_TOKENandPLATFORM_ADMIN_ENABLED=trueset as fly.io secrets on the ngx-ramblers (staging) app to authenticateghand enable the admin pages
admin: stale-while-revalidate area cache, skip migration check on password reset, and centralise admin paths (#146)
Area cache now always serves cached data immediately and refreshes in the background when expired, preventing visible loading delays. Replace banned Date.now() with dateTimeNowAsValue(). Skip migration status check when navigating to set-password URLs so password resets work on newly provisioned environments with pending migrations. Centralise admin/set-password and admin/maintenance path strings as shared constants in system.model.ts and update all TypeScript references across frontend guards, services, and backend routes.