Skip to content

fix(geoip): separate IPv6 size limit, accept unknown codes, gate live verification before publish - #118

Merged
hapheus merged 6 commits into
mainfrom
fix/issue-117-geoip-limit-prepublish-gate
Nov 7, 2026
Merged

hapheus merged 6 commits into
mainfrom
fix/issue-117-geoip-limit-prepublish-gate

Conversation

@hapheus

@hapheus hapheus commented Nov 7, 2026

Copy link
Copy Markdown
Owner

Closes #116
Closes #117

Problem

Daily Live Image Verification failed since PR #103/#114 because upstream geoip6 is ~16 MB but TORPROXY_GEOIP_MAX_BYTES defaulted to 10 MiB, so the IPv6 GeoIP download was always rejected. The live check only ran after publish, so the breakage shipped undetected. A second, latent breakage was found during local live verification: current upstream geoip files contain literal ?? unknown-origin country codes, which the validator rejected.

Changes

  • GeoIP size limits: per-file limits (geoip 16 MiB, geoip6 32 MiB). Legacy single TORPROXY_GEOIP_MAX_BYTES still caps both files unless TORPROXY_GEOIP6_MAX_BYTES explicitly overrides the IPv6 limit (backward compatible).
  • Validator: accept ?? unknown-origin codes (TDD, hermetic unit tests with real upstream lines).
  • Observability: auto-update records source/timestamps/last error/byte sizes to geoip-status.json; /status exposes it additively as geoip (GeoIpStatus port + file adapter, no core I/O), so silent fallbacks are visible.
  • Gate shift (ISSUE-117): new reusable .github/workflows/live-image-verification.yml (workflow_call) runs the full Tor canary suite against a locally built image (build_local) or a published image. PR gate, publish-dockerhub (needs verify-live) and release (needs verify-live) all run it before merge/publish/release. Daily keeps run_alerts against the published image as drift detector only. Includes an upstream Content-Length drift guard derived from shipped Settings defaults and a /status geoip.source==downloaded assertion.
  • Branch protection on main: 1 approval, dismiss stale reviews, required checks include Lint & Static Analysis, Hermetic Unit Tests (3.10/3.11/3.14), Docker Build & Container Smoke Test, Live Image Verification (Pre-Publish Gate).
  • Docs updated (.env.example, docs/configuration.md, docs/compatibility.md, README.md).

Verification (local)

  • uv run ruff check . : clean
  • uv run ruff format --check . : clean (74 files)
  • uv run mypy : clean
  • bash -n docker/.sh tests/integration/.sh : clean
  • shellcheck docker/.sh tests/integration/.sh : clean
  • uv run pytest tests/unit/ -q --cov=torproxy --cov-fail-under=85 : 350 passed, coverage 86.88%
  • Live local Docker test: image built; container with TORPROXY_GEOIP_AUTO_UPDATE=1 + TORPROXY_COUNTRY=DE downloaded geoip (9,855,249 B) and geoip6 (16,075,127 B); /status = connected, geoip.source=downloaded, exit IP 185.220.101.16
  • GitHub Actions runs: pending (this PR)

… verification before publish

Fixes #116, closes #117

- Per-file GeoIP size limits: geoip 16 MiB, geoip6 32 MiB;
  legacy TORPROXY_GEOIP_MAX_BYTES still caps both unless
  TORPROXY_GEOIP6_MAX_BYTES overrides the IPv6 limit.
- Accept upstream '??' unknown-origin country codes in the
  GeoIP payload validator.
- Record auto-update outcome to geoip-status.json and expose
  it additively as geoip in /status via GeoIpStatus port +
  file adapter, so silent fallbacks are visible.
- Shift live Tor verification left: reusable
  live-image-verification workflow now gates PRs, publish
  and release against a locally built image; daily canary
  keeps alerting against the published image as drift
  detector only. Includes upstream Content-Length drift
  guard from shipped Settings defaults.
- Branch protection on main requires the live gate.
Comment thread src/torproxy/runtime/geoip.py Fixed
Relative reusable-workflow paths fail on pull_request events
(startup_failure, 0 jobs): GitHub resolves them against the
simulated merge commit. Referencing the reusable workflow by
repo@head_ref tests the PR's own version of the workflow.
…le workflow

The reusable-workflow form failed with startup_failure (0 jobs)
on pull_request events: GitHub resolves relative reusable paths
against the simulated merge commit. A composite action under
.github/actions/live-verification is resolved from the checkout
and works on every event (PR, push, tag, schedule). Same steps,
same inputs; callers now check out first and invoke the action.
- shell: bash on every run step (required by composite actions)
- Docker Hub token passed as input (secrets context is not
  available inside composite actions)
- drop timeout-minutes (unsupported in composite steps; the
  bootstrap loop is self-bounded at 36x5s)
…tion

The gateway step polled the published host port through the
kill switch, which never returns connected (ISSUE-19 pattern):
PR #118 burned 8m50s in this step although the container's Tor
bootstrapped in 8s. Poll over loopback inside the container
with a 180s wall-clock cap, mirroring the PR gate fix.

@MustermenschAlex MustermenschAlex left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for this — a clean fix on both levels. The per-file GeoIP limits keep the legacy single-var behavior intact (good for the compatibility contract), the new /status geoip field is purely additive, and the hermetic tests pin the real upstream sizes plus the ?? codes. Shifting the live check into a pre-publish gate via the composite action is the right structural answer to the 'detected only after release' problem. All required checks green, including the new live gate. Approving.

@kuenstlichedummheit-sys kuenstlichedummheit-sys left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nice catch on the double root cause — the ?? codes would have kept this red even after the size fix, classic whack-a-mole otherwise. Also glad the gateway poll got the in-container treatment; 8m50s of kill-switch ping-pong was never going to flip to connected. Live gate at 1m35s now, that is the way it should feel. Ship it.

majorungustl
majorungustl previously approved these changes Nov 7, 2026

@majorungustl majorungustl left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Honestly the best part is how boring this got: one shared action, clear inputs, no reusable-workflow merge-commit weirdness, and /status finally tells you when geoip silently fell back instead of making you grep container logs at 4am. The drift guard reading limits from Settings instead of copy-pasted numbers is a nice touch too. LGTM, merge away.

Addresses the CodeQL empty-except alert on PR #118: the
except clause intentionally ignores a missing/corrupt previous
status file; document that instead of a bare pass.

@MustermenschAlex MustermenschAlex left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Re-reviewed after the CodeQL follow-up: the explanatory comment on the empty except resolves the alert properly, and all checks are green again on the new head. The compatibility story (additive /status field, legacy env var still capping both files) remains solid. Approving.

@kuenstlichedummheit-sys kuenstlichedummheit-sys left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Second look after the tiny CodeQL comment fix: still all green, live gate still fast (1m28s), sanity restored. Nothing else to poke at from the edge-case department. Good to go.

@majorungustl majorungustl left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Re-checked post-comment-fix: no new complexity snuck in, just a two-line comment, CI all green. Still the same boring-in-a-good-way change. Merge it.

@hapheus
hapheus merged commit 81471d0 into main Nov 7, 2026
12 checks passed
@hapheus
hapheus deleted the fix/issue-117-geoip-limit-prepublish-gate branch November 10, 2026 08:12
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.

fix(geoip): separate IPv6 size limit and gate live verification before publish 🚨 Daily Live Image Verification Failed

5 participants