From 50dc4e6b6ab38be7319063b6a51c75b72bbe85af Mon Sep 17 00:00:00 2001 From: Rene Fichtmueller Date: Sat, 18 Jul 2026 07:03:06 +0000 Subject: [PATCH] fix: network.country was always empty -- both its data sources were dead stubs /api/lookup's deriveRirAndCountry() can only populate country from two inputs: rirEntries (RIPE Stat rir-stats-country) and bgpHeData.country_code (bgp.he.net). Both of their fetches in the Phase 1 Promise.all are hardcoded to Promise.resolve(null) (see the timedFetch("RIPE Stat RIR", ...) and timedFetch("bgp.he.net", ...) lines), so country has been unpopulated for every single lookup regardless of ASN. rir stayed populated separately via the RDAP port43/links fallback, which masked the issue -- rir looked fine, country silently didn't. Confirmed via today's rotating_audit.py run: 100/100 sampled ASNs flagged country_empty. Fix: fall back to PeeringDB's org-level country (pdbOrgState, loaded at startup from /api/org, already used successfully by lia.js's coverage endpoint for the same purpose) when the RIR-derived country is empty. Does not touch the two dead stubs -- those look like deliberate stand-ins for sources that were never wired up, out of scope here. Verified live post-deploy: AS680 DE, AS847 US, AS1251 BR now populated (previously all three were empty). AS4628 still empty -- its PeeringDB org itself has no country set, a genuine upstream data gap, not something this fallback can fix. npm test: 215/215 passing. --- server/routes/lookup/index.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/server/routes/lookup/index.js b/server/routes/lookup/index.js index 25be038..6bae168 100644 --- a/server/routes/lookup/index.js +++ b/server/routes/lookup/index.js @@ -14,6 +14,7 @@ const { enrichNeighbours } = require("./enrich-neighbours"); const { deriveRirAndCountry } = require("./rir-country"); const { computeRoutingInfo } = require("./routing-info"); const { computeCrossChecks } = require("./cross-check"); +const { pdbOrgState } = require("../../pdb-org-countries"); // Main lookup endpoint: /api/lookup?asn=X async function handleLookup(req, res, url) { @@ -177,7 +178,12 @@ async function handleLookup(req, res, url) { downstreams = enriched.downstreams; peers = enriched.peers; - const { rir, country } = deriveRirAndCountry(rirEntries, rirData, rdapData, bgpHeData); + const { rir, country: derivedCountry } = deriveRirAndCountry(rirEntries, rirData, rdapData, bgpHeData); + // "RIPE Stat RIR" and "bgp.he.net" sources above are stubbed to always + // resolve null (see Phase 1 promises), so derivedCountry is currently + // never populated -- fall back to PeeringDB's org-level country map + // (pdbOrgState, loaded at startup), the same source lia.js already uses. + const country = derivedCountry || (pdbOrgState.map.get(net.org_id) || {}).country || ""; const duration = Date.now() - start;