All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
- Non-routable IPv4 filtering: all IANA special-purpose, multicast, and reserved ranges are excluded from route tables
NON_ROUTABLE_RANGESconstant inoptimizer.pywith 18 CIDR blocks covering RFC 1918, RFC 6598 (CGNAT), RFC 1122 (loopback), RFC 3927 (link-local), RFC 5737 (documentation), RFC 5771 (multicast), RFC 1112 (reserved), and morefilter_non_routable()function removes private/reserved ranges from merged routesROUTABLE_UNIVERSEconstant:0.0.0.0/0minus all non-routable ranges- 9 new tests for non-routable filtering (RFC 1918, CGNAT, loopback, link-local, multicast, reserved, documentation nets, complement exclusion, routable universe integrity)
- Repository-local
allowlists/anddenylists/directories with--allowlist-dirand--denylist-diroverrides for IPv4 route additions and exclusions - Strict HTTPS
@include <URL>directives for local route files, with non-recursive parsing, redirect rejection, response size limits, and IPv6 skipping - Telegram's official CIDR source in
denylists/telegram.txtfor automatic IPv4 deny routing - A reviewed Telegram IPv4 scope that fails closed when the upstream source returns an unapproved route
compute_complement()now subtracts fromROUTABLE_UNIVERSEinstead of0.0.0.0/0, ensuring inverse route tables never contain private/reserved rangescli.pypipeline appliesfilter_non_routable()after merge, before optimize/annotate/complement- Forward routes are defensively filtered to catch upstream data errors from APNIC or GitHub sources
- Local allowlists are merged with remote routes before denylists are subtracted; final routes now drive optimized, annotated, and inverse outputs
- Operator annotations are intersected with final routes, preventing denied or non-routable operator CIDRs from appearing in annotated output
- Scheduled route generation passes explicit workspace paths for output, allowlists, and denylists
fetch_chnroutes2()now uses SukkaW's optimized chnroutes2 endpoint first and falls back to Misaka's original source only if the primary fetch fails
- Route output files now sorted numerically by IP address instead of lexicographically (e.g.
2.xbefore10.x) - Nightly release workflow now correctly deletes the date-specific tag before re-creating, fixing same-day manual re-trigger failures
- Retry with exponential backoff for HTTP fetches (3 attempts, 1s/2s/4s waits)
- Concurrent operator fetching via
ThreadPoolExecutor(4 workers) - Input validation in
apnic_entry_to_cidrs(): rejects invalid IPs, zero/negative counts, clamps IPv4 overflow - CLI test suite: 15 tests covering argument parsing, skip modes, e2e pipeline, error paths, exit codes
- Parser edge case tests: invalid IP, zero count, negative count, overflow clamping
- Fetcher retry tests: connection error recovery, retry exhaustion, HTTP error retry
- Output timestamp test: verifies shared timestamp across all three files
- CI test+lint workflow (
.github/workflows/test.yml): Python 3.9–3.12 matrix, ruff lint and format checks - Shared test fixtures in
tests/conftest.py - Ruff configuration in
pyproject.toml(line-length 100, isort, pyflakes, pycodestyle) - Package classifiers and keywords in
pyproject.toml - Dynamic User-Agent from package metadata with graceful fallback
- CONTRIBUTING.md and CHANGELOG.md
fetch_operator()raisesValueErrorinstead of catch-and-reraiseKeyErrorcli.pycatches(requests.RequestException, ValueError, OSError)instead of bareExceptionoptimizer.pycatches(ValueError, TypeError, AddrFormatError)instead of bareException- Output writers accept optional
timestampparameter;cli.pypasses a shared timestamp - Removed redundant
os.makedirs()from output writers (handled once incli.py) - Removed unused
cidr_mergeimport fromoptimizer.py annotate_routes()sorts byIPNetworkobjects directly instead of re-parsing strings- CI update-routes workflow uses
pip install -e .anddobby-routesCLI instead ofPYTHONPATHhack - Updated AGENTS.md with current test count (88), CI/CD docs, and new conventions
- Ruff lint violations: import sorting, unused imports, ambiguous variable names, long lines
- Initial release
- APNIC delegated file parsing with IPv4 support
- GitHub operator IP list fetching (China Telecom, China Unicom, China Mobile, CERNET)
- chnroutes2 BGP feed integration
- Route merging and optimization via netaddr
IPSet - Complement route table generation (inverse of forward routes)
- Operator annotation system with ASN labels
- CLI with
--output-dir,--skip-github,--skip-apnic,-vflags - Three output files: annotated, optimized, and inverse route tables
- Daily route table generation via GitHub Actions
- Nightly releases with attached route table files
databranch with latest pre-built route tables- 64 unit tests with full HTTP mocking
- Type hints on all public functions
- README.md with installation, usage, and data source documentation
- AGENTS.md with architecture and technical decision documentation