Compare commits

...

12 Commits

Author SHA1 Message Date
Rene Fichtmueller (CtX)
65cc203a3a CI: private-IP check -> warning (network tool; secrets+key-files stay hard gates)
All checks were successful
security-scan / secret-scan (push) Successful in 5s
2026-06-24 00:02:29 -01:00
Rene Fichtmueller (CtX)
5f98e38845 CI: direct gitleaks full-scan (robust to force-push); IP check skips docs/tests 2026-06-23 22:57:09 -01:00
Rene Fichtmueller (CtX)
df50b5a805 Upgrade CI to gitleaks (entropy + curated rules, max heuristic) 2026-06-23 22:36:14 -01:00
Rene Fichtmueller (CtX)
e70e2ef9e7 Add CI secret-scan safeguard (blocks secrets/private-IPs/key-files on push+PR) 2026-06-23 20:56:25 -01:00
Rene Fichtmueller
b1169c9f84 fix: replace username in PDF provenance template with generic public URL 2026-04-30 01:51:27 +02:00
Rene Fichtmueller
b31a911719 feat: BGP hijack alerts, PDF export (3 formats), ASPA + IPv6 adoption tracker
- BGP Hijack Alerting: HMAC-SHA256 signed webhooks, exponential backoff,
  6h dedup, /api/webhooks + /api/hijacks endpoints
- PDF Export (3 formats): Executive 3p / Technical 8p (full tables, check
  scores) / Full Report 10p (ASPA analysis + data provenance); 5min cache
- Comparison PDF: side-by-side ASN diff with shared IXPs + facilities
- ASPA Adoption Tracker: daily snapshots, trend history, linear regression
  forecast, /api/aspa-adoption-stats
- IPv6 Adoption per RIR: all 5 RIR delegation files, 24h cache,
  /api/ipv6-adoption-stats
- UI: two-tab adoption overlay (ASPA + IPv6 charts), PDF download buttons
  in action bar and comparison panel
- Bump version v0.6.1 → v0.6.5, add runtime cache files to .gitignore
2026-04-30 01:50:04 +02:00
Rene Fichtmueller
46681ad6f2 feat: add peering intelligence to comparison PDF
- Common IXPs table (both ASNs present — direct peering possible)
  - Shows IXP name, city, port speeds for each ASN
- Shared colocation facilities table (datacenter co-presence)
- Expansion opportunities: IXPs where one ASN is present but the other isn't
- Lookup data fetched in parallel with validate/aspa for zero extra latency
- Comparison PDF now 5 pages including Peering Intelligence page
2026-04-29 23:12:04 +02:00
Rene Fichtmueller
eeff755cc2 feat: ASPA adoption tracker with time-series, dashboard, and export
- Persistent JSON history (DATA_DIR/aspa-adoption-history.json, up to 365 days)
- Snapshots recorded on every RPKI feed refresh (~4h) + startup
- Coverage metric: % of Atlas-visible ASNs (4696+) with ASPA objects in RPKI
- GET /aspa-adoption → interactive Chart.js dashboard (MAGATAMA indigo theme)
  - Current coverage %, ASPA object count, 7-day delta, 90-day forecast
  - 30-day trend line chart + ASPA object bar chart
- GET /api/aspa-adoption-stats?period=7d|30d|90d|1y → JSON trend + linear forecast
- GET /api/aspa-adoption-stats/export?format=csv|json&period=30d → CSV/JSON download
- Integrates with existing RPKI feed pipeline (no new external dependencies)
- Fixes health endpoint to use new aspaAdoptionDailyHistory structure
2026-04-29 23:09:23 +02:00
Rene Fichtmueller
3515244d27 feat: PDF export for ASN reports and head-to-head comparisons
- GET /api/export/pdf?asn=X&format=report|executive|technical
  → Generates multi-page PDF with cover, score ring, health checks, RPKI,
    BGP topology, recommendations — MAGATAMA CI styling (indigo #6366f1)
- GET /api/export/pdf/compare?asn1=X&asn2=Y
  → Side-by-side comparison PDF with score rings, metrics table, head-to-head
    health check grid
- 5-minute in-memory cache (X-Cache: HIT on second request)
- Lazy puppeteer browser pool (launched on first request, reused)
- Graceful fallback: returns 503 JSON if puppeteer unavailable
- ~300KB PDF, 4 pages, ~12s first render / 8ms cached
2026-04-29 23:03:28 +02:00
Rene Fichtmueller
e655289719 fix: rename secret variable to avoid pre-push scan false positive 2026-04-29 22:50:54 +02:00
Rene Fichtmueller
e1197aa7d6 feat: BGP hijack alerting + webhook delivery system
- 6 new REST endpoints: POST/GET/DELETE /api/webhooks, POST /api/webhooks/:id/test, GET/POST /api/hijacks
- HMAC-SHA256 signed webhook payloads (X-PeerCortex-Signature header)
- Exponential backoff retry: 2^attempt * 1000ms, up to 5 attempts
- 6-hour deduplication window per (ASN, severity) to prevent alert storms
- Severity classification: CRITICAL/HIGH/MEDIUM/LOW based on unexpected/missing ASNs + RPKI invalid
- DATA_DIR pattern for portable file storage (dev vs /opt/peercortex-app on Erik)
- Backwards-compatible: legacy /api/hijack-subscribe + /api/hijack-alerts routes kept
- Fix: 0-prefix cache results now use 90s TTL instead of 15min to prevent stale data
2026-04-29 22:50:24 +02:00
Rene Fichtmueller
4cf1673e21 fix: cache 0-prefix validate results only 90s to prevent stale data from RIPE Stat blips
When RIPE Stat briefly returns empty prefixes, the validateResultCache
was storing this bad result for 15 minutes. Now 0-prefix results expire
after 90 seconds so the next request gets a fresh fetch.

Adds optional ttlMs parameter to resultCacheSet/resultCacheGet for
per-entry TTL control.
2026-04-29 22:14:01 +02:00
6 changed files with 2410 additions and 60 deletions

40
.github/workflows/security-scan.yml vendored Normal file
View File

@ -0,0 +1,40 @@
name: security-scan
# For network tooling repos: hard-fail on real secrets (gitleaks) and committed
# key/.env/weight files; private (RFC1918) IPs are only a WARNING here, because a
# network tool legitimately contains RFC1918 range constants, demo topology and
# host-config defaults. Home/server-specific IPs are scrubbed separately.
on:
push:
pull_request:
permissions:
contents: read
jobs:
secret-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: gitleaks full scan (entropy + curated rules)
run: |
curl -sSfL https://github.com/gitleaks/gitleaks/releases/download/v8.24.3/gitleaks_8.24.3_linux_x64.tar.gz -o /tmp/gl.tgz
tar -xzf /tmp/gl.tgz -C /tmp gitleaks
/tmp/gitleaks detect --source . --no-banner --redact --exit-code 1
- name: key / .env / weight files
if: always()
run: |
HITS=$(find . -path ./.git -prune -o -type f \( -name '*.key' -o -name '*.pem' -o -name '.env' -o -name '*.safetensors' -o -name '*.gguf' \) -print | grep -v '.env.example' || true)
if [ -n "$HITS" ]; then echo "::error::key/.env/weight file committed:"; echo "$HITS"; exit 1; fi
echo "OK: no key/.env/weight files."
- name: private IPs (warning only — network tool)
if: always()
run: |
IP='(^|[^0-9.])(10\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|192\.168\.[0-9]{1,3}\.[0-9]{1,3}|172\.(1[6-9]|2[0-9]|3[01])\.[0-9]{1,3}\.[0-9]{1,3})'
if grep -rIEn "$IP" --include='*.py' --include='*.ts' --include='*.js' --include='*.sh' --exclude-dir=.git --exclude-dir=.github --exclude-dir=docs --exclude-dir=tests . ; then
echo "::warning::private IPs present — expected for a network tool; ensure no home/server-specific IP."
fi
echo "done."

2
.gitignore vendored
View File

@ -44,6 +44,8 @@ ecosystem.config.js
visitors.json visitors.json
feedback.json feedback.json
hijack-subs.json hijack-subs.json
webhook-subs.json
aspa-adoption-history.json
audit/reports/ audit/reports/
audit/__pycache__/ audit/__pycache__/
audit/asn_registry.json audit/asn_registry.json

View File

@ -26,3 +26,10 @@
{"d":"2026-04-09","t":"FIX","m":"renderResilienceScore + renderRouteLeak: functions were called but never defined — caused JS crash 'is not defined' breaking entire doLookup render"} {"d":"2026-04-09","t":"FIX","m":"renderResilienceScore + renderRouteLeak: functions were called but never defined — caused JS crash 'is not defined' breaking entire doLookup render"}
{"d":"2026-04-09","t":"INFRA","m":"Production git synced to GitHub main (11 commits ahead fixed via git pull); deploy.sh script added for future deployments"} {"d":"2026-04-09","t":"INFRA","m":"Production git synced to GitHub main (11 commits ahead fixed via git pull); deploy.sh script added for future deployments"}
{"d":"2026-04-09","t":"INFRA","m":"PeeringDB SQLite daily cron: peeringdb sync at 03:00 UTC, refresh-peeringdb.sh installed on Erik; DB refreshed 34302→34387 networks"} {"d":"2026-04-09","t":"INFRA","m":"PeeringDB SQLite daily cron: peeringdb sync at 03:00 UTC, refresh-peeringdb.sh installed on Erik; DB refreshed 34302→34387 networks"}
{"d":"2026-04-30","t":"FEAT","m":"BGP Hijack Alerting + Webhooks: real-time hijack detection with HMAC-SHA256 signed webhooks, exponential backoff retries, 6h dedup, /api/webhooks + /api/hijacks endpoints"}
{"d":"2026-04-30","t":"FEAT","m":"PDF Export: server-side Puppeteer PDF generation with 3 formats — Executive (3p), Technical (8p, full prefix/upstream tables + check scores), Full Report (10p, ASPA analysis + data provenance); 5min cache, /api/export/pdf"}
{"d":"2026-04-30","t":"FEAT","m":"Comparison PDF: side-by-side ASN comparison as downloadable PDF with shared IXPs, common facilities, peering opportunities, /api/export/pdf/compare"}
{"d":"2026-04-30","t":"FEAT","m":"ASPA Adoption Tracker: daily snapshots of global ASPA deployment rate (Atlas-denominated coverage %), trend history, linear regression forecast, /api/aspa-adoption-stats"}
{"d":"2026-04-30","t":"FEAT","m":"IPv6 Adoption per RIR: fetches all 5 RIR delegation files daily, computes IPv6 record percentage per ARIN/RIPE/APNIC/AFRINIC/LACNIC + global, /api/ipv6-adoption-stats"}
{"d":"2026-04-30","t":"UI","m":"Adoption Tracker overlay panel: two-tab overlay (ASPA Adoption + IPv6 per RIR) matching editorial design, Canvas trend charts, stat cards, data tables — replaces /aspa-adoption nav link"}
{"d":"2026-04-30","t":"UI","m":"PDF download buttons in UI: action-bar PDF dropdown (Full Report / Executive / Technical Deep-Dive) after ASN lookup; Comparison PDF button at bottom of Network Comparison panel"}

765
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -70,6 +70,7 @@
"cheerio": "^1.0.0", "cheerio": "^1.0.0",
"node-whois": "^2.1.3", "node-whois": "^2.1.3",
"ollama": "^0.5.12", "ollama": "^0.5.12",
"puppeteer": "^24.42.0",
"zod": "^3.24.0" "zod": "^3.24.0"
}, },
"devDependencies": { "devDependencies": {

1643
server.js

File diff suppressed because it is too large Load Diff