# InternetPressure.io — repository guide **The real-time pressure gauge for the Internet.** Full product spec: `docs/SPEC.md` (authoritative). Architecture decisions: `docs/ARCHITECTURE.md`. Contracts: `docs/API.md` (public + admin API), `docs/PROBE-PROTOCOL.md` (probe ↔ ingestion). Deployment: `docs/DEPLOY.md`. ## Layout ``` apps/web Next 16 + React 19 + Tailwind 4 + MapLibre + ECharts (port 8351) apps/api Python 3.12 package `internetpressure` — FastAPI API/ingest, pressure engine, event engine, BGP ingestor, scheduler, corroboration connectors (api on port 8352) services/probe-agent Go probe agent (single static binary, darwin/arm64 + linux/amd64) packages/config pressure.yaml — weights, levels, engine/scheduler parameters (hot-reloaded, editable in /admin) data/regions.yaml region model · data/targets/targets.yaml target registry seed · data/seed/*.yaml services, probes infra/ Docker Compose (compose.yml), edge Caddy, ClickHouse/Postgres init, systemd/launchd units for probes deploy/bin deploy.sh (BHS64b), probes.sh (build + push probe binaries), lib.sh docs/ SPEC, ARCHITECTURE, API, PROBE-PROTOCOL, DEPLOY, RUNBOOK tests/ pytest (scoring, normalisation, events, ingest, api) ``` ## Non-negotiable rules (from the spec) 1. **No fake real-time.** Never animate random numbers, never synthesise events. If a value did not change, the UI does not move. Every visible movement originates from a real measurement or BGP message. 2. **Self-exclusion.** Our own outage must never inflate the index: the engine freezes and flags `internal_status` when probes/BGP/stores are unhealthy. See `internetpressure/engine/health.py`. 3. **Explainable.** Every score decomposes into components → signals → (scope, current, baseline, robust z, contribution). 4. **Config-driven weights.** Weights/levels/thresholds live in `packages/config/pressure.yaml` (or the Postgres `config` override) — never in code. 5. **Baseline-relative.** Robust z = (x − rolling median) / MAD, clipped. Absolute thresholds only where unavoidable (documented in `docs/ARCHITECTURE.md`). 6. **Ethical measurement.** Ordinary lightweight client traffic only: no scanning, no auth bypass, no bursts. 7. **UTC everywhere** in storage and APIs; the browser localises. 8. **No secrets in Git.** `.env` files are ignored; `deploy/.env.example` documents every variable. ## Dev quick start ```bash docker compose -f infra/compose.yml --profile dev up -d clickhouse postgres redis # stores only cd apps/api && uv sync && uv run ip migrate && uv run ip seed && uv run ip api # :8352 uv run ip engine # pressure engine loop · uv run ip bgp # RIS Live ingestor cd apps/web && pnpm install && pnpm dev # :8351 (rewrites /api → :8352) cd services/probe-agent && make build && ./dist/ip-probe-darwin-arm64 --config probe.dev.yaml pytest -q # from apps/api ``` ## Production **BHS128b** (OVH Beauharnois, ubuntu@51.161.112.85, since 2026-09-14) runs `infra/compose.yml` (project `ip`, edge Caddy :8350 bound to WireGuard 10.67.0.62). Public route: BHS64 gateway `https://www.internetpressure.io → 10.67.0.62:8350`. Probes run as launchd (macOS) / systemd (Linux) services on cluster nodes. `deploy/bin/deploy.sh` and `deploy/bin/probes.sh` (defaults in `deploy/bin/lib.sh`: `IP_SERVER=BHS128b`, `IP_WG_IP=10.67.0.62`). Nightly backup cron (04:10 UTC) → BHS128:/srv/backups/internetpressure. Until 2026-09-14 production was BHS64b (10.67.0.61); its stack is stopped (`docker compose down`, volumes `ip_*` kept as a cold copy).