Skip to content

feat(geo): GEO_FORCE_OFFLINE flag to suppress runtime ipinfo.io egress (#382) - #474

Merged
NotYuSheng merged 3 commits into
mainfrom
feature/geo-force-offline
Jul 6, 2026
Merged

feat(geo): GEO_FORCE_OFFLINE flag to suppress runtime ipinfo.io egress (#382)#474
NotYuSheng merged 3 commits into
mainfrom
feature/geo-force-offline

Conversation

@NotYuSheng

@NotYuSheng NotYuSheng commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Closes #382.

What

Adds a GEO_FORCE_OFFLINE global kill-switch (default off) that suppresses the one intentional runtime egress — ipinfo.io geolocation enrichment — for strict air-gapped / egress-monitored deployments.

When tracepcap.geo.force-offline=true, GeoIpService.isOnline() short-circuits to false before any network call, so both the connectivity probe and every ipinfo.io lookup are skipped. Geo resolves exclusively from the bundled DB-IP Lite MMDB (geo_source = mmdb). currentSource() reports mmdb too, since it routes through isOnline(). Default behaviour (online probe + graceful MMDB fallback) is unchanged.

Changes

  • GeoIpService.javatracepcap.geo.force-offline @Value + force-offline gate in isOnline() + a startup log line.
  • application.ymlgeo.force-offline: ${GEO_FORCE_OFFLINE:false}.
  • docker-compose.yml — passthrough, default false.
  • docker-compose.offline.yml — defaults to true for the air-gapped stack (overridable).
  • .env.example — new "Geolocation Egress" block documenting the flag and the one intentional egress.
  • docs/getting-started/offline-deployment.rst — "Suppressing Runtime Egress" section.

Acceptance criteria

  • GEO_FORCE_OFFLINE flag, default off, that skips the probe + ipinfo.io lookups and resolves from the MMDB only (geo_source = mmdb).
  • When set, no outbound ipinfo.io connections attempted.
  • Documented the flag + the one intentional runtime egress in the offline checklist.

Verification

Backend built cleanly. With GEO_FORCE_OFFLINE=true, startup logs:

GeoIP force-offline mode enabled (tracepcap.geo.force-offline=true) — no ipinfo.io egress will be attempted; resolving from bundled MMDB only

With the flag off (default), no force-offline line and MMDB loads as fallback — both paths confirmed at runtime.

Note: the issue referenced docs/production-readiness.md (finding P2-4), but that file isn't committed to the repo, so there was nothing to mark resolved there.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added an offline geolocation mode that uses the bundled database only and avoids external lookup attempts.
    • Added configuration options and deployment defaults for air-gapped environments.
  • Documentation

    • Expanded offline deployment guidance with setup steps for forcing offline geolocation and setting the database path when needed.
  • Bug Fixes

    • Improved geolocation behavior in restricted networks by preventing failed external connectivity checks and lookups.

#382)

Add a global kill-switch that suppresses the one intentional runtime egress
(ipinfo.io) for strict air-gapped / egress-monitored deployments.

When tracepcap.geo.force-offline=true, GeoIpService.isOnline() short-circuits
to false before any network call, skipping both the connectivity probe and all
ipinfo.io lookups. Geo resolves exclusively from the bundled DB-IP Lite MMDB
(geo_source = mmdb). Default off — the existing online/offline auto-fallback is
unchanged.

- GeoIpService: force-offline gate + startup log line
- application.yml: geo.force-offline (GEO_FORCE_OFFLINE, default false)
- docker-compose.yml: passthrough (default false)
- docker-compose.offline.yml: default true for the air-gapped stack
- .env.example: documented flag + the one intentional egress
- docs/offline-deployment.rst: egress-suppression section

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@NotYuSheng, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 52 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 55c4f9d8-083e-4c4c-b846-408554449463

📥 Commits

Reviewing files that changed from the base of the PR and between 10c6c3a and ce04c0b.

📒 Files selected for processing (2)
  • .env.example
  • backend/src/main/java/com/tracepcap/analysis/service/GeoIpService.java
📝 Walkthrough

Walkthrough

Adds a GEO_FORCE_OFFLINE configuration flag to GeoIpService that suppresses the ipinfo.io connectivity probe and lookups, forcing geo resolution exclusively from the bundled MMDB. Wires the flag through application.yml, .env.example, both docker-compose files, and updates offline deployment documentation.

Changes

GEO_FORCE_OFFLINE flag

Layer / File(s) Summary
Force-offline geo resolution logic
backend/src/main/java/com/tracepcap/analysis/service/GeoIpService.java
Adds forceOffline property bound via @Value, logs an info message when enabled during init(), and makes isOnline() return false immediately when force-offline is enabled.
Configuration wiring
backend/src/main/resources/application.yml, .env.example, docker-compose.yml, docker-compose.offline.yml
Adds tracepcap.analysis.geo.force-offline / GEO_FORCE_OFFLINE settings with explanatory comments; default false for standard config, default true for the offline compose stack.
Offline deployment docs
docs/getting-started/offline-deployment.rst
Documents GEO_FORCE_OFFLINE usage, GEO_MMDB_PATH override, and a new subsection explaining suppressed egress and MMDB-only resolution (geo_source = mmdb).

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Backend
  participant GeoIpService
  participant ipinfo_io

  Backend->>GeoIpService: init()
  alt forceOffline enabled
    GeoIpService->>GeoIpService: log force-offline mode
    GeoIpService->>GeoIpService: isOnline() returns false
    GeoIpService->>GeoIpService: resolve geo from bundled MMDB
  else forceOffline disabled
    GeoIpService->>ipinfo_io: connectivity probe / lookup
    ipinfo_io-->>GeoIpService: response or timeout
  end
Loading

Related issues: #382 (GEO_FORCE_OFFLINE flag to suppress runtime ipinfo.io egress)

Suggested labels: enhancement, backend, documentation

Suggested reviewers: NotYuSheng

🐰 A hop, a flag, an offline switch,
No pings to ipinfo, not one glitch,
The MMDB hums its local song,
Air-gapped and quiet, nothing wrong,
This bunny's egress dreams are rich.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly names the new GEO_FORCE_OFFLINE flag and its purpose of suppressing runtime ipinfo.io egress.
Linked Issues check ✅ Passed The changes add the offline flag, skip probe and lookup traffic, fall back to MMDB, and update docs/config as required.
Out of Scope Changes check ✅ Passed All changes stay within the geo offline-egress feature and its documentation/config wiring.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the GEO_FORCE_OFFLINE configuration option to suppress all outbound egress (connectivity probes and ipinfo.io lookups) for strict air-gapped or egress-monitored deployments, forcing the system to resolve geolocation exclusively from the bundled MMDB. The feedback suggests a security improvement to also short-circuit the connectivity check when GeoIP enrichment is disabled (geoEnabled is false) to prevent any accidental egress.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread backend/src/main/java/com/tracepcap/analysis/service/GeoIpService.java Outdated
Short-circuit isOnline() to false when geoEnabled is false, not just when
forceOffline is set — prevents the ipinfo.io connectivity probe from firing
via currentSource() when GeoIP enrichment is disabled.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/src/main/java/com/tracepcap/analysis/service/GeoIpService.java (1)

274-297: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Short-circuit correctly suppresses all egress.

isOnline() returning false before any network call correctly ensures lookupExternal()'s online ? lookupFromIpInfo(ip) : null branches always skip ipinfo.io, and currentSource() reports "mmdb". This matches the hybrid offline-fallback strategy required for GeoIpService. No test currently exercises this path — worth adding a unit test asserting isOnline() returns false and no HTTP connection is attempted when force-offline is set, given this is the crux of the air-gapped compliance guarantee.

As per path instructions, **/GeoIpService.java: "the application must function fully offline with no external API calls at runtime... hybrid strategy with ipinfo.io as primary... and DB-IP Lite MMDB... as automatic offline fallback."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/main/java/com/tracepcap/analysis/service/GeoIpService.java`
around lines 274 - 297, Add a unit test around GeoIpService.isOnline() that sets
forceOffline and verifies it returns false without attempting any HTTP
connection, so lookupExternal() continues to skip lookupFromIpInfo(ip) and
currentSource() stays on mmdb. Use the isOnline() path as the target behavior,
and mock or spy the network probe so the test asserts no
openConnection/getResponseCode interaction occurs when force-offline is enabled.

Source: Path instructions

♻️ Duplicate comments (1)
docs/getting-started/offline-deployment.rst (1)

66-77: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Step 2 should call out the GEO_FORCE_OFFLINE default trap.

Copying .env.example verbatim (as instructed here) sets GEO_FORCE_OFFLINE=false, which — per Docker Compose precedence — overrides docker-compose.offline.yml's intended true default. Given the new subsection below states this is "the recommended setting for the offline compose stack" (line 44), Step 2 should explicitly instruct setting GEO_FORCE_OFFLINE=true in the copied .env for air-gapped use. See linked comment on docker-compose.offline.yml.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/getting-started/offline-deployment.rst` around lines 66 - 77, The
offline setup instructions currently tell users to copy .env.example verbatim,
which can leave GEO_FORCE_OFFLINE set to false and override the offline compose
default. Update the Step 2 guidance in offline-deployment.rst to explicitly
instruct users to set GEO_FORCE_OFFLINE=true in the copied .env for air-gapped
deployments, and ensure the wording aligns with the offline compose stack
guidance already referenced in docker-compose.offline.yml.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.env.example:
- Around line 45-52: The offline template still hardcodes GEO_FORCE_OFFLINE to
false, which prevents docker-compose.offline.yml’s default fallback from taking
effect. Update the .env.example entry for GEO_FORCE_OFFLINE so the offline
template sets it to true by default, aligning with the intended air-gapped
behavior and the existing fallback logic.

---

Outside diff comments:
In `@backend/src/main/java/com/tracepcap/analysis/service/GeoIpService.java`:
- Around line 274-297: Add a unit test around GeoIpService.isOnline() that sets
forceOffline and verifies it returns false without attempting any HTTP
connection, so lookupExternal() continues to skip lookupFromIpInfo(ip) and
currentSource() stays on mmdb. Use the isOnline() path as the target behavior,
and mock or spy the network probe so the test asserts no
openConnection/getResponseCode interaction occurs when force-offline is enabled.

---

Duplicate comments:
In `@docs/getting-started/offline-deployment.rst`:
- Around line 66-77: The offline setup instructions currently tell users to copy
.env.example verbatim, which can leave GEO_FORCE_OFFLINE set to false and
override the offline compose default. Update the Step 2 guidance in
offline-deployment.rst to explicitly instruct users to set
GEO_FORCE_OFFLINE=true in the copied .env for air-gapped deployments, and ensure
the wording aligns with the offline compose stack guidance already referenced in
docker-compose.offline.yml.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 77a8593a-f688-4de1-8157-f270ec3b9f12

📥 Commits

Reviewing files that changed from the base of the PR and between b6cb5fd and 10c6c3a.

📒 Files selected for processing (6)
  • .env.example
  • backend/src/main/java/com/tracepcap/analysis/service/GeoIpService.java
  • backend/src/main/resources/application.yml
  • docker-compose.offline.yml
  • docker-compose.yml
  • docs/getting-started/offline-deployment.rst

Comment thread .env.example
An explicit GEO_FORCE_OFFLINE=false in a copied .env overrides the offline
compose file's ${GEO_FORCE_OFFLINE:-true} default, silently keeping air-gapped
deployments on the ipinfo.io probe path. Comment the line out so each compose
file's own default governs (base=false, offline=true).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@NotYuSheng
NotYuSheng merged commit 25abe78 into main Jul 6, 2026
7 checks passed
@NotYuSheng
NotYuSheng deleted the feature/geo-force-offline branch July 6, 2026 12:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: GEO_FORCE_OFFLINE flag to suppress runtime ipinfo.io egress

1 participant