From 5b04b6c5baeb73815e6dc5f812eb81e490c15ba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Fri, 15 May 2026 22:21:58 +0200 Subject: [PATCH] docs(release): document the resilient GeoLite2 fallback in v1.4.27 notes Rewrites the `MAXMIND_LICENSE_KEY` entry in the v1.4.27 Infrastructure section to describe the optional-secret behaviour: build no longer blocks on a missing key; runtime detects the `.empty` marker, falls back to `ipwho.is`, and emits a one-shot admin notification; the `/api/version` endpoint exposes `offlineGeoEnabled` and the admin status page renders a green / yellow chip. Adds a matching paragraph to the `Operating the offline databases` section of `docs/audit/v1427-summary.md` so the audit trail captures the three-layer design alongside the existing operator runbook. --- CHANGELOG.md | 20 ++++++++++++++------ docs/audit/v1427-summary.md | 11 +++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf856a224..e96d83735 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -405,12 +405,20 @@ is additive, `IF NOT EXISTS`-guarded, and forward-only. - **`MAXMIND_LICENSE_KEY` wired into the GHCR build workflow.** A new `Fetch GeoLite2 databases` step in `.github/workflows/docker-publish.yml` between the metadata-action - and the buildx build-push exports the secret from repo secrets and - fails the workflow with an `::error::` line when unset (instead of - silently exiting 0 and producing an empty `assets/geolite2/` - directory). The Dockerfile `COPY assets/geolite2/ /opt/geolite2/` - step now lands the real MMDB files and the runtime resolver - populates the carrier column on the production image. + and the buildx build-push exports the secret from repo secrets. + Offline GeoLite2 is **optional** in this release: when the secret + is unset the workflow emits a `::warning::`, drops an `.empty` + marker into `assets/geolite2/`, and continues so the Dockerfile + `COPY` still has a non-empty source. The runtime resolver in + `src/lib/geo.ts` detects the marker on first lookup, falls back + to the existing `ipwho.is` provider, and sends a one-shot admin + notification (`notifications.admin.offlineGeoUnavailable*`) with + a pointer to the GitHub Actions secrets page so the maintainer + hears about the gap from the running app. The `/api/version` + endpoint exposes `offlineGeoEnabled: boolean`; the `/admin` + overview snapshot and the full `/admin/system-status` page render + a green / yellow chip from that flag. Setting the secret and + redeploying lights the feature up without code changes. - **Migration `0061_audit_log_carrier`.** Additive, `IF NOT EXISTS`-guarded, forward-only. Adds two columns to `AuditLog`: `asn` (`bigint`) + `carrier` (`text`). Safe to diff --git a/docs/audit/v1427-summary.md b/docs/audit/v1427-summary.md index a2e23f3b2..50d390c0d 100644 --- a/docs/audit/v1427-summary.md +++ b/docs/audit/v1427-summary.md @@ -39,6 +39,17 @@ The script writes `GeoLite2-City.mmdb` and `GeoLite2-ASN.mmdb` to If the script is skipped the image builds cleanly, and the resolver falls back to the online `ipwho.is` provider — the v1.4.26 behaviour. +The offline tier is **optional** as of v1.4.27 R5. When +`MAXMIND_LICENSE_KEY` is unset the `Fetch GeoLite2 databases` step in +`.github/workflows/docker-publish.yml` emits a `::warning::`, drops an +`.empty` marker into `assets/geolite2/`, and continues — the build no +longer blocks on a missing secret. The runtime resolver detects the +marker on the first public-IP lookup, sends a one-shot admin +notification with the GitHub Actions secrets URL, and continues to +serve audits from the `ipwho.is` fallback. `/api/version` exposes +`offlineGeoEnabled: boolean` so the admin status page can render the +state at a glance. + MaxMind reissues the databases on the first Tuesday of each month; re-run the script before each release to pick up new ASN allocations and city renames.