spb/internetpressure
Public
TypeScript 36.3%
Python 31.8%
Go 18%
JavaScript 9.8%
Shell 1.9%
SQL 1.4%
CSS 0.5%
1#!/usr/bin/env node2/**3 * InternetPressure.io — DEV-ONLY mock of the public + admin API (docs/API.md), plain Node, no dependencies.4 *5 * node mock/server.mjs # http://127.0.0.1:83526 * MOCK_DEGRADED=1 node mock/… # simulates internal_status="degraded" + stale score (spec §57 banner)7 * MOCK_ADMIN_TOKEN=… # admin token (default "dev-admin-token")8 *9 * Every value is a plausible, self-consistent fixture derived from a seeded generator so pages look real while the10 * FastAPI backend is being written. This file never ships in the Docker image and is never used in production.11 * Fixtures drift very slightly on each engine "cycle" (10 s) so the live layer can be exercised; the SSE stream only12 * emits on those cycles — never between them — mirroring the real contract ("nothing without a computation").13 */14import http from 'node:http';15import { URL } from 'node:url';1617const PORT = Number(process.env.PORT ?? 8352);18const ADMIN_TOKEN = process.env.MOCK_ADMIN_TOKEN ?? 'dev-admin-token';19const DEGRADED = process.env.MOCK_DEGRADED === '1';20const START = Date.now();2122// ---------------------------------------------------------------- deterministic pseudo-random23let seed = 20260912;24const rnd = () => {25 seed = (seed * 1664525 + 1013904223) % 4294967296;26 return seed / 4294967296;27};28const r = (a, b, d = 1) => Number((a + rnd() * (b - a)).toFixed(d));29const pick = (arr) => arr[Math.floor(rnd() * arr.length)];30const iso = (t) => new Date(t).toISOString().replace(/\.\d{3}Z$/, 'Z');31const now = () => Date.now();32const minutesAgo = (m) => iso(now() - m * 60_000);33const clamp = (v, lo = 0, hi = 100) => Math.max(lo, Math.min(hi, v));3435const LEVELS = [36 { max: 10, id: 'calm', label: 'Exceptionally calm' },37 { max: 25, id: 'normal', label: 'Normal' },38 { max: 40, id: 'elevated', label: 'Elevated' },39 { max: 55, id: 'stressed', label: 'Stressed' },40 { max: 70, id: 'high', label: 'Highly stressed' },41 { max: 85, id: 'severe', label: 'Severe disruption' },42 { max: 100, id: 'extreme', label: 'Extreme Internet event' },43];44const levelOf = (p) => LEVELS.find((l) => p <= l.max) ?? LEVELS[LEVELS.length - 1];45const trendOf = (d) => (d > 1.5 ? 'rising' : d < -1.5 ? 'falling' : 'stable');46const WEIGHTS = { routing: 0.25, latency: 0.2, dns: 0.15, availability: 0.15, http_tls: 0.1, path: 0.1, corroboration: 0.05 };47const COMP_LABEL = { routing: 'Routing', latency: 'Latency', dns: 'DNS', availability: 'Availability', http_tls: 'HTTP/TLS', path: 'Path', corroboration: 'Corroboration' };4849// ---------------------------------------------------------------- regions (data/regions.yaml)50const REGION_DEFS = [51 ['na-east', 'North America East', 'North America', 43, -76],52 ['na-central', 'North America Central', 'North America', 41, -95],53 ['na-west', 'North America West', 'North America', 40, -120],54 ['latam', 'Latin America', 'South America', -15, -55],55 ['eu-west', 'Western Europe', 'Europe', 49, 3],56 ['eu-north', 'Northern Europe', 'Europe', 60, 18],57 ['eu-east', 'Eastern Europe', 'Europe', 50, 22],58 ['eu-east-med', 'Eastern Mediterranean', 'Europe', 38, 30],59 ['mena', 'Middle East & North Africa', 'Asia', 26, 45],60 ['africa', 'Sub-Saharan Africa', 'Africa', -5, 22],61 ['asia-south', 'South Asia', 'Asia', 22, 78],62 ['asia-se', 'Southeast Asia', 'Asia', 5, 108],63 ['asia-east', 'East Asia', 'Asia', 35, 125],64 ['oceania', 'Oceania', 'Oceania', -30, 140],65];66const REGION_PRESSURE = {67 'na-east': 51.3, 'na-central': 27.4, 'na-west': 22.8, latam: 19.5, 'eu-west': 31.2, 'eu-north': 14.9, 'eu-east': 21.7,68 'eu-east-med': 33.6, mena: 24.1, africa: 18.3, 'asia-south': 26.9, 'asia-se': 16.4, 'asia-east': 12.7, oceania: 9.8,69};70const REGION_DELTA = {71 'na-east': 12.1, 'na-central': 3.4, 'na-west': 0.8, latam: -1.2, 'eu-west': 4.9, 'eu-north': -0.4, 'eu-east': 1.1,72 'eu-east-med': 6.2, mena: 0.3, africa: -2.6, 'asia-south': 2.2, 'asia-se': -0.9, 'asia-east': -1.8, oceania: 0.1,73};74const PROBE_REGIONS = new Set(['na-east', 'eu-west', 'eu-east-med', 'asia-se', 'oceania']);7576// ---------------------------------------------------------------- probes77const PROBES = [78 ['ca-qc-01', 'Québec City (Bell)', 'na-east', 'CA', 'Québec', 'Bell Canada', 577, 46.8, -71.2],79 ['ca-qc-02', 'Québec City (Vidéotron)', 'na-east', 'CA', 'Québec', 'Vidéotron', 5769, 46.8, -71.3],80 ['ca-bhs-01', 'Beauharnois (OVHcloud)', 'na-east', 'CA', 'Beauharnois', 'OVHcloud', 16276, 45.3, -73.9],81 ['fr-gra-01', 'Gravelines (OVHcloud)', 'eu-west', 'FR', 'Gravelines', 'OVHcloud', 16276, 51.0, 2.1],82 ['ie-dub-01', 'Dublin (MacStadium)', 'eu-west', 'IE', 'Dublin', 'MacStadium', 41064, 53.3, -6.3],83 ['tr-ist-01', 'Istanbul (Macly)', 'eu-east-med', 'TR', 'Istanbul', 'Macly', 34984, 41.0, 29.0],84 ['sg-sin-01', 'Singapore (Vultr)', 'asia-se', 'SG', 'Singapore', 'Vultr', 20473, 1.3, 103.8],85 ['au-syd-01', 'Sydney (Vultr)', 'oceania', 'AU', 'Sydney', 'Vultr', 20473, -33.9, 151.2],86].map(([probe_id, name, region, country, city, provider, asn, lat, lon], i) => ({87 probe_id, name, region, country, city, provider, asn, lat, lon,88 status: 'online', last_seen: minutesAgo(0), version: i === 6 ? '0.1.0-rc3' : '0.1.0',89 measurements_1h: 4200 + i * 137, uptime_24h: Number((0.991 + i * 0.001).toFixed(3)),90 clock_offset_ms: [-14, 3, -2, 8, -21, 5, 11, -6][i],91 capabilities: ['http', 'dns', 'ping', 'traceroute'],92}));9394// ---------------------------------------------------------------- ASNs & services & targets95const ASNS = [96 [13335, 'Cloudflare, Inc.', 'US', 5, 18.2, 1200], [15169, 'Google LLC', 'US', 5, 11.4, 980], [16509, 'Amazon.com, Inc.', 'US', 5, 24.6, 3100],97 [8075, 'Microsoft Corporation', 'US', 5, 20.1, 1450], [20940, 'Akamai International B.V.', 'NL', 5, 14.0, 610], [54113, 'Fastly, Inc.', 'US', 4, 22.7, 210],98 [32934, 'Meta Platforms, Inc.', 'US', 4, 12.3, 320], [2906, 'Netflix Streaming Services', 'US', 3, 9.7, 95], [36459, 'GitHub, Inc.', 'US', 4, 27.9, 40],99 [16276, 'OVH SAS', 'FR', 4, 21.5, 890], [577, 'Bell Canada', 'CA', 4, 44.8, 1720], [5769, 'Videotron Ltee', 'CA', 3, 38.2, 260],100 [6453, 'TATA Communications (America) Inc', 'US', 5, 58.4, 7400], [3356, 'Lumen (Level 3)', 'US', 5, 31.6, 12400], [1299, 'Arelion (Telia Carrier)', 'SE', 5, 19.9, 6900],101 [174, 'Cogent Communications', 'US', 5, 26.2, 9800], [2914, 'NTT America', 'US', 5, 17.3, 5600], [3320, 'Deutsche Telekom AG', 'DE', 4, 13.8, 2300],102 [12876, 'Scaleway S.a.s.', 'FR', 3, 15.2, 140], [19551, 'Incapsula (Imperva)', 'US', 3, 16.6, 75], [14061, 'DigitalOcean, LLC', 'US', 3, 18.9, 330],103 [20473, 'The Constant Company (Vultr)', 'US', 3, 14.4, 410], [9121, 'Turk Telekom', 'TR', 3, 36.1, 1100], [7922, 'Comcast Cable', 'US', 4, 15.7, 3700],104 [4134, 'China Telecom', 'CN', 4, 23.3, 8100], [9498, 'Bharti Airtel', 'IN', 3, 28.6, 2900], [4766, 'Korea Telecom', 'KR', 3, 10.9, 1400],105 [4837, 'China Unicom', 'CN', 3, 21.8, 4300], [7545, 'TPG Telecom', 'AU', 3, 12.6, 620], [1221, 'Telstra', 'AU', 3, 8.9, 940],106].map(([asn, name, country, importance, pressure, prefixes]) => ({ asn, name, country, importance, pressure, prefixes_observed: prefixes }));107const asnById = Object.fromEntries(ASNS.map((a) => [a.asn, a]));108109const SERVICES = [110 ['cloudflare', 'Cloudflare', 'cdn', 13335, 'status.cloudflare.com', 'none'], ['aws', 'Amazon Web Services', 'cloud', 16509, 'health.aws.amazon.com', 'minor'],111 ['google', 'Google', 'search', 15169, 'status.cloud.google.com', 'none'], ['azure', 'Microsoft Azure', 'cloud', 8075, 'azure.status.microsoft', 'none'],112 ['github', 'GitHub', 'developer', 36459, 'www.githubstatus.com', 'none'], ['akamai', 'Akamai', 'cdn', 20940, null, null],113 ['fastly', 'Fastly', 'cdn', 54113, 'status.fastly.com', 'none'], ['netflix', 'Netflix', 'streaming', 2906, null, null],114 ['meta', 'Meta (Facebook, Instagram, WhatsApp)', 'social', 32934, 'metastatus.com', 'none'], ['openai', 'OpenAI', 'ai', 13335, 'status.openai.com', 'none'],115 ['anthropic', 'Anthropic', 'ai', 13335, 'status.anthropic.com', 'none'], ['apple', 'Apple', 'commerce', 714, 'www.apple.com/support/systemstatus', 'none'],116 ['stripe', 'Stripe', 'finance', 13335, 'status.stripe.com', 'none'], ['shopify', 'Shopify', 'commerce', 13335, 'www.shopifystatus.com', 'none'],117 ['zoom', 'Zoom', 'messaging', 16509, 'status.zoom.us', 'none'], ['slack', 'Slack', 'messaging', 16509, 'slack-status.com', 'none'],118 ['discord', 'Discord', 'messaging', 13335, 'discordstatus.com', 'none'], ['reddit', 'Reddit', 'social', 54113, 'www.redditstatus.com', 'none'],119 ['wikipedia', 'Wikimedia', 'news', 14907, 'www.wikimediastatus.net', 'none'], ['spotify', 'Spotify', 'streaming', 15169, null, null],120 ['canada-gc', 'Government of Canada', 'government', 577, null, null], ['quad9', 'Quad9', 'dns', 19281, null, null],121 ['ovhcloud', 'OVHcloud', 'cloud', 16276, 'www.status-ovhcloud.com', 'none'], ['digitalocean', 'DigitalOcean', 'cloud', 14061, 'status.digitalocean.com', 'none'],122];123const SERVICE_PRESSURE = { cloudflare: 12.0, aws: 41.7, google: 9.2, azure: 17.8, github: 33.4, akamai: 11.1, fastly: 21.3, netflix: 8.4, meta: 10.6, openai: 15.9, anthropic: 14.2, apple: 7.9, stripe: 9.8, shopify: 13.5, zoom: 16.0, slack: 29.1, discord: 12.8, reddit: 19.4, wikipedia: 6.3, spotify: 8.8, 'canada-gc': 35.2, quad9: 5.1, ovhcloud: 20.7, digitalocean: 18.6 };124125const HOSTS = {126 cloudflare: ['www.cloudflare.com', 'api.cloudflare.com', 'one.one.one.one', 'cdnjs.cloudflare.com', 'dash.cloudflare.com', 'workers.dev'],127 aws: ['aws.amazon.com', 's3.amazonaws.com', 'ec2.us-east-1.amazonaws.com', 's3.ca-central-1.amazonaws.com', 'dynamodb.us-east-1.amazonaws.com', 'lambda.eu-west-1.amazonaws.com', 'sts.amazonaws.com', 'cloudfront.net', 'ec2.us-west-2.amazonaws.com', 'ec2.eu-west-3.amazonaws.com'],128 google: ['www.google.com', 'www.googleapis.com', 'dns.google', 'storage.googleapis.com', 'www.youtube.com', 'accounts.google.com', 'fonts.googleapis.com', 'mail.google.com', 'maps.googleapis.com', 'play.google.com'],129 azure: ['azure.microsoft.com', 'login.microsoftonline.com', 'management.azure.com', 'blob.core.windows.net', 'outlook.office365.com', 'graph.microsoft.com', 'teams.microsoft.com', 'www.microsoft.com', 'update.microsoft.com', 'xbox.com'],130 github: ['github.com', 'api.github.com', 'raw.githubusercontent.com', 'codeload.github.com', 'ghcr.io', 'objects.githubusercontent.com', 'pages.github.com', 'copilot.github.com'],131 akamai: ['www.akamai.com', 'akamaihd.net', 'akamaized.net', 'edgekey.net', 'akamaitechnologies.com', 'edgesuite.net'],132 fastly: ['www.fastly.com', 'api.fastly.com', 'fastly.net', 'global.ssl.fastly.net', 'pypi.org', 'files.pythonhosted.org'],133 netflix: ['www.netflix.com', 'api-global.netflix.com', 'nflxvideo.net', 'assets.nflxext.com'],134 meta: ['www.facebook.com', 'www.instagram.com', 'web.whatsapp.com', 'graph.facebook.com', 'www.threads.net', 'static.xx.fbcdn.net', 'www.messenger.com', 'developers.facebook.com'],135 openai: ['api.openai.com', 'chat.openai.com', 'platform.openai.com', 'cdn.openai.com', 'auth.openai.com', 'chatgpt.com'],136 anthropic: ['api.anthropic.com', 'claude.ai', 'www.anthropic.com', 'console.anthropic.com', 'docs.anthropic.com', 'status.anthropic.com'],137 apple: ['www.apple.com', 'www.icloud.com', 'apps.apple.com', 'swcdn.apple.com', 'gsa.apple.com', 'developer.apple.com', 'idmsa.apple.com', 'mesu.apple.com', 'ocsp.apple.com', 'push.apple.com'],138 stripe: ['api.stripe.com', 'js.stripe.com', 'dashboard.stripe.com', 'checkout.stripe.com', 'files.stripe.com', 'hooks.stripe.com'],139 shopify: ['www.shopify.com', 'cdn.shopify.com', 'shop.app', 'admin.shopify.com', 'myshopify.com', 'shopifycloud.com'],140 zoom: ['zoom.us', 'api.zoom.us', 'us02web.zoom.us', 'zoomgov.com', 'us04web.zoom.us', 'zoom.com'],141 slack: ['slack.com', 'api.slack.com', 'app.slack.com', 'files.slack.com', 'edgeapi.slack.com', 'wss-primary.slack.com', 'a.slack-edge.com', 'status.slack.com'],142 discord: ['discord.com', 'gateway.discord.gg', 'cdn.discordapp.com', 'media.discordapp.net', 'discordapp.com', 'discord.gg'],143 reddit: ['www.reddit.com', 'oauth.reddit.com', 'i.redd.it', 'old.reddit.com', 'styles.redditmedia.com', 'gateway.reddit.com'],144 wikipedia: ['en.wikipedia.org', 'fr.wikipedia.org', 'upload.wikimedia.org', 'www.wikidata.org', 'commons.wikimedia.org', 'api.wikimedia.org', 'de.wikipedia.org', 'ja.wikipedia.org', 'es.wikipedia.org', 'meta.wikimedia.org'],145 spotify: ['open.spotify.com', 'api.spotify.com', 'accounts.spotify.com', 'i.scdn.co', 'spclient.wg.spotify.com', 'www.spotify.com'],146 'canada-gc': ['www.canada.ca', 'www.cra-arc.gc.ca', 'www.quebec.ca', 'www.servicecanada.gc.ca', 'www.tpsgc-pwgsc.gc.ca', 'www.ic.gc.ca', 'www.weather.gc.ca', 'www.statcan.gc.ca', 'www.elections.ca', 'www.parl.ca'],147 quad9: ['dns.quad9.net', 'www.quad9.net', 'dns9.quad9.net', 'dns10.quad9.net', 'dns11.quad9.net', 'on.quad9.net'],148 ovhcloud: ['www.ovhcloud.com', 'api.ovh.com', 'www.ovh.com', 'ca.api.ovh.com', 'eu.api.ovh.com', 'kimsufi.com', 'soyoustart.com', 'www.ovhtelecom.fr', 'mail.ovh.net', 'docs.ovh.com', 'help.ovhcloud.com', 'partners.ovhcloud.com'],149 digitalocean: ['www.digitalocean.com', 'api.digitalocean.com', 'cloud.digitalocean.com', 'digitaloceanspaces.com', 'nyc3.digitaloceanspaces.com', 'docs.digitalocean.com', 'registry.digitalocean.com', 'droplets.digitalocean.com', 'community.digitalocean.com', 'marketplace.digitalocean.com'],150};151const COUNTRY_OF_SERVICE = { cloudflare: 'US', aws: 'US', google: 'US', azure: 'US', github: 'US', akamai: 'NL', fastly: 'US', netflix: 'US', meta: 'US', openai: 'US', anthropic: 'US', apple: 'US', stripe: 'US', shopify: 'CA', zoom: 'US', slack: 'US', discord: 'US', reddit: 'US', wikipedia: 'US', spotify: 'SE', 'canada-gc': 'CA', quad9: 'CH', ovhcloud: 'FR', digitalocean: 'US' };152const COUNTRY_REGION = { CA: 'na-east', US: 'na-east', FR: 'eu-west', IE: 'eu-west', GB: 'eu-west', DE: 'eu-west', NL: 'eu-west', CH: 'eu-west', SE: 'eu-north', PL: 'eu-east', TR: 'eu-east-med', AE: 'mena', ZA: 'africa', IN: 'asia-south', SG: 'asia-se', JP: 'asia-east', KR: 'asia-east', HK: 'asia-east', AU: 'oceania', BR: 'latam', MX: 'latam' };153const ANCHOR = ['ca-central-1', 'us-east-1', 'eu-west-3', 'eu-west-1', 'ap-southeast-1', 'ap-southeast-2', 'sa-east-1', 'ap-south-1', 'eu-north-1', 'ap-northeast-1', 'me-central-1', 'af-south-1', 'eu-central-1', 'ap-east-1', 'eu-west-2', 'ap-northeast-2', 'eu-south-1', 'mx-central-1'];154const ANCHOR_CC = ['CA', 'US', 'FR', 'IE', 'SG', 'AU', 'BR', 'IN', 'SE', 'JP', 'AE', 'ZA', 'DE', 'HK', 'GB', 'KR', 'CH', 'MX'];155156const TARGETS = [];157let anchorIdx = 0;158for (const [slug, name, category, asn] of SERVICES) {159 HOSTS[slug].forEach((hostname, i) => {160 const cc = i === 0 ? COUNTRY_OF_SERVICE[slug] : ANCHOR_CC[anchorIdx++ % ANCHOR_CC.length];161 const region = COUNTRY_REGION[cc];162 const regional = REGION_PRESSURE[region] ?? 20;163 const base = SERVICE_PRESSURE[slug];164 const pressure = Number(clamp(base * 0.6 + regional * 0.3 + r(-6, 6)).toFixed(1));165 TARGETS.push({166 target_id: `${slug}-${hostname.split('.').slice(0, -1).join('-').replace(/[^a-z0-9-]/g, '-').replace(/^-+|-+$/g, '') || slug}`.slice(0, 48),167 name: i === 0 ? name : `${name} · ${hostname}`, hostname, category, provider: name, service_id: slug, country: cc, region,168 importance: i === 0 ? 5 : i < 3 ? 4 : 3, tier: i === 0 ? 1 : i < 3 ? 2 : 3, asn,169 pressure, ok_ratio_1h: Number(clamp(1 - pressure / 400 - (pressure > 40 ? r(0.01, 0.05, 3) : 0), 0, 1).toFixed(4)),170 ttfb_ms_median_1h: r(40, 260, 0),171 });172 });173}174// dedupe ids175const seenIds = new Set();176for (const t of TARGETS) { let id = t.target_id, n = 2; while (seenIds.has(id)) id = `${t.target_id}-${n++}`; t.target_id = id; seenIds.add(id); }177const targetById = Object.fromEntries(TARGETS.map((t) => [t.target_id, t]));178const TARGETS_TOTAL = TARGETS.length; // 212 with the lists above179180// ---------------------------------------------------------------- countries with coverage181const COUNTRY_NAMES = { CA: 'Canada', US: 'United States', FR: 'France', IE: 'Ireland', GB: 'United Kingdom', DE: 'Germany', NL: 'Netherlands', CH: 'Switzerland', SE: 'Sweden', TR: 'Türkiye', AE: 'United Arab Emirates', ZA: 'South Africa', IN: 'India', SG: 'Singapore', JP: 'Japan', KR: 'South Korea', HK: 'Hong Kong', AU: 'Australia', BR: 'Brazil', MX: 'Mexico' };182const COUNTRY_CENTROID = { CA: [56.1, -106.3], US: [39.8, -98.6], FR: [46.6, 2.2], IE: [53.4, -8.2], GB: [55.4, -3.4], DE: [51.2, 10.4], NL: [52.1, 5.3], CH: [46.8, 8.2], SE: [60.1, 18.6], TR: [39.0, 35.2], AE: [23.4, 53.8], ZA: [-30.6, 22.9], IN: [20.6, 79.0], SG: [1.35, 103.8], JP: [36.2, 138.3], KR: [35.9, 127.8], HK: [22.4, 114.1], AU: [-25.3, 133.8], BR: [-14.2, -51.9], MX: [23.6, -102.6] };183const COUNTRY_PRESSURE = { CA: 34.0, US: 47.8, FR: 29.6, IE: 27.1, GB: 30.4, DE: 28.7, NL: 26.9, CH: 24.2, SE: 14.9, TR: 33.6, AE: 24.1, ZA: 18.3, IN: 26.9, SG: 16.4, JP: 12.7, KR: 11.9, HK: 15.3, AU: 9.8, BR: 19.5, MX: 21.0 };184const COUNTRY_DELTA = { CA: 2.0, US: 11.4, FR: 4.1, IE: 3.9, GB: 4.4, DE: 3.2, NL: 2.8, CH: 1.9, SE: -0.4, TR: 6.2, AE: 0.3, ZA: -2.6, IN: 2.2, SG: -0.9, JP: -1.8, KR: -1.1, HK: -0.6, AU: 0.1, BR: -1.2, MX: 0.6 };185186function regionComponents(id, p) {187 const routing = PROBE_REGIONS.has(id) || ['na-central', 'na-west', 'eu-north'].includes(id) ? Number(clamp(p * 1.1 + r(-8, 8)).toFixed(1)) : null;188 return {189 routing, latency: Number(clamp(p * 1.2 + r(-5, 5)).toFixed(1)), dns: Number(clamp(p * 0.35 + r(-3, 3)).toFixed(1)),190 availability: Number(clamp(p * 0.7 + r(-4, 4)).toFixed(1)), http_tls: Number(clamp(p * 0.45 + r(-4, 4)).toFixed(1)), path: Number(clamp(p * 1.05 + r(-6, 6)).toFixed(1)),191 };192}193const REGION_COMPONENTS = Object.fromEntries(REGION_DEFS.map(([id]) => [id, regionComponents(id, REGION_PRESSURE[id])]));194const COUNTRY_COMPONENTS = Object.fromEntries(Object.keys(COUNTRY_PRESSURE).map((cc) => [cc, regionComponents(COUNTRY_REGION[cc], COUNTRY_PRESSURE[cc])]));195196// ---------------------------------------------------------------- live engine state (drifts per cycle)197let cycle = 0;198const GLOBAL_BASE = 42.7;199function drift() { return DEGRADED ? 0 : Math.sin(cycle / 7) * 0.9 + Math.sin(cycle / 3.1) * 0.3; }200function currentGlobal() { return Number((GLOBAL_BASE + drift()).toFixed(1)); }201function engineTs() { return DEGRADED ? iso(START - 14 * 60_000) : iso(now() - (now() % 10_000)); }202const internalStatus = () => (DEGRADED ? 'degraded' : 'ok');203204// 24 h history shape: diurnal baseline around 28–34, dip overnight, spike in the last ~45 minutes.205function pressureAt(tsMs, base = GLOBAL_BASE) {206 const ageMin = (now() - tsMs) / 60_000;207 const hour = new Date(tsMs).getUTCHours() + new Date(tsMs).getUTCMinutes() / 60;208 const diurnal = 30 + 4 * Math.sin(((hour - 6) / 24) * 2 * Math.PI);209 const noise = 1.6 * Math.sin(tsMs / 1_730_000) + 0.9 * Math.sin(tsMs / 610_000) + 0.4 * Math.sin(tsMs / 97_000);210 const spike = ageMin < 48 ? (base - diurnal) * (1 - ageMin / 48) ** 0.7 : 0;211 const bump = ageMin > 600 && ageMin < 700 ? 18 * Math.sin(((ageMin - 600) / 100) * Math.PI) : 0; // the resolved DNS incident 10–11.6 h ago212 return Number(clamp(diurnal + noise + spike + bump, 3, 97).toFixed(1));213}214function scaleFor(scopeType, scopeId) {215 if (scopeType === 'global' || !scopeId) return 1;216 if (scopeType === 'region') return (REGION_PRESSURE[scopeId] ?? 25) / GLOBAL_BASE;217 if (scopeType === 'country') return (COUNTRY_PRESSURE[scopeId.toUpperCase()] ?? 25) / GLOBAL_BASE;218 if (scopeType === 'asn') return (asnById[Number(scopeId)]?.pressure ?? 20) / GLOBAL_BASE;219 if (scopeType === 'service') return (SERVICE_PRESSURE[scopeId] ?? 15) / GLOBAL_BASE;220 return 1;221}222const STEP = { '1h': 10, '6h': 60, '24h': 60, '7d': 300, '30d': 3600, '1y': 86400 };223const RANGE_S = { '1h': 3600, '6h': 21600, '24h': 86400, '7d': 604800, '30d': 2592000, '1y': 31536000 };224function history(scopeType, scopeId, range) {225 const step = STEP[range] ?? 60;226 const span = RANGE_S[range] ?? 86400;227 const scale = scaleFor(scopeType, scopeId);228 const end = now() - (now() % (step * 1000));229 const points = [];230 for (let t = end - span * 1000; t <= end; t += step * 1000) {231 const p = Number(clamp(pressureAt(t) * scale).toFixed(1));232 points.push({ ts: iso(t), pressure: p, components: {233 routing: Number(clamp(p * 1.3 - 2).toFixed(1)), latency: Number(clamp(p * 1.05).toFixed(1)), dns: Number(clamp(p * 0.42).toFixed(1)),234 availability: Number(clamp(p * 0.8).toFixed(1)), http_tls: Number(clamp(p * 0.6).toFixed(1)), path: Number(clamp(p * 1.15).toFixed(1)), corroboration: Number(clamp(p * 0.1).toFixed(1)) },235 confidence: 0.85 });236 }237 const ps = points.map((x) => x.pressure);238 const maxI = ps.indexOf(Math.max(...ps));239 return { scope_type: scopeType, scope_id: scopeId ?? null, range, step_seconds: step, points,240 summary: { min: Math.min(...ps), max: Math.max(...ps), avg: Number((ps.reduce((a, b) => a + b, 0) / ps.length).toFixed(1)), max_ts: points[maxI].ts } };241}242const history24 = (scopeType, scopeId) => { const h = history(scopeType, scopeId, '24h'); return { step_seconds: 60, points: h.points.map((p) => ({ ts: p.ts, pressure: p.pressure })) }; };243244// ---------------------------------------------------------------- global pressure245function componentsGlobal(p) {246 const scores = { routing: 57.1, latency: 44.3, dns: 19.2, availability: 37.4, http_tls: 28.0, path: 51.2, corroboration: 22.0 };247 const deltas = { routing: 11.0, latency: 8.4, dns: -0.6, availability: 4.1, http_tls: 2.2, path: 9.7, corroboration: 6.0 };248 const conf = { routing: 0.9, latency: 0.88, dns: 0.82, availability: 0.85, http_tls: 0.8, path: 0.76, corroboration: 0.6 };249 const drivers = {250 routing: [{ label: 'BGP withdrawals/s 4.8× baseline', points: 9.1, scope_type: 'bgp', scope_id: 'withdrawals' }, { label: 'Origin ASN changes 3× baseline', points: 2.9, scope_type: 'bgp', scope_id: 'origin_changes' }, { label: 'Collector disagreement (rrc00 vs rrc11)', points: 2.3, scope_type: 'bgp', scope_id: 'collectors' }],251 latency: [{ label: 'TTFB +43 % from North America East', points: 5.8, scope_type: 'region', scope_id: 'na-east' }, { label: 'Packet loss 3.1 % on transatlantic pairs', points: 2.6, scope_type: 'region', scope_id: 'na-east' }],252 dns: [{ label: 'SERVFAIL rate 1.2× baseline (resolver 9.9.9.9)', points: 1.4, scope_type: 'signal', scope_id: 'dns_fail_rate' }],253 availability: [{ label: '4 targets failing from ≥2 probe regions', points: 3.9, scope_type: 'signal', scope_id: 'target_down_corroborated' }, { label: 'AWS us-east-1 endpoints failure rate 2.1×', points: 1.7, scope_type: 'service', scope_id: 'aws' }],254 http_tls: [{ label: 'TLS handshake failures 1.6× baseline', points: 1.6, scope_type: 'signal', scope_id: 'tls_fail_rate' }, { label: 'HTTP 5xx 1.3× (github, slack)', points: 1.2, scope_type: 'signal', scope_id: 'http_5xx_rate' }],255 path: [{ label: 'Route fingerprints changed on 62 % of NA→EU paths', points: 3.4, scope_type: 'signal', scope_id: 'route_change_rate' }, { label: 'Paths crossing AS6453 +12 ms', points: 1.7, scope_type: 'asn', scope_id: '6453' }],256 corroboration: [{ label: 'AWS reports a minor incident (health.aws.amazon.com)', points: 1.1, scope_type: 'service', scope_id: 'aws' }],257 };258 const d = drift();259 return Object.keys(WEIGHTS).map((id) => {260 const score = Number(clamp(scores[id] + d * (id === 'routing' ? 1.6 : id === 'latency' ? 1.1 : 0.4)).toFixed(1));261 return { id, label: COMP_LABEL[id], score, weight: WEIGHTS[id], contribution: Number((score * WEIGHTS[id]).toFixed(1)), trend: trendOf(deltas[id]), delta_1h: deltas[id], confidence: conf[id], drivers: drivers[id] };262 });263}264function sparkline1h() {265 const pts = [];266 const end = now() - (now() % 60_000);267 for (let i = 59; i >= 0; i--) pts.push(i === 23 ? null : pressureAt(end - i * 60_000));268 pts[59] = currentGlobal();269 return pts;270}271function globalPressure() {272 const p = currentGlobal();273 const lvl = levelOf(p);274 const comps = componentsGlobal(p);275 return {276 ts: engineTs(), pressure: p, level: lvl.id, level_label: lvl.label,277 delta_1h: 6.3, delta_24h: -2.1, velocity_per_h: 7.2, acceleration_per_h2: 3.1, volatility_1h: 2.4, trend: 'rising',278 confidence: 0.86, stale: DEGRADED, internal_status: internalStatus(),279 coverage: { probes_active: DEGRADED ? 1 : 8, probes_total: 8, probe_regions: DEGRADED ? 1 : 5, targets: TARGETS_TOTAL, measurements_5m: 41200, bgp_collectors: 12, baseline_days: 6.2 },280 components: comps,281 explain: [282 { text: '+14.3 points from elevated BGP route churn', points: comps[0].contribution, component: 'routing', scope_type: 'global', scope_id: null },283 { text: '+11.0 from North America East packet loss and latency', points: 11.0, component: 'latency', scope_type: 'region', scope_id: 'na-east' },284 { text: '+5.1 from route changes on North America → Western Europe paths', points: 5.1, component: 'path', scope_type: 'region', scope_id: 'eu-west' },285 { text: '+3.9 from 4 corroborated target failures (AWS us-east-1)', points: 3.9, component: 'availability', scope_type: 'service', scope_id: 'aws' },286 { text: '+1.6 from TLS handshake failures', points: 1.6, component: 'http_tls', scope_type: 'global', scope_id: null },287 { text: '−3.1 because Western Europe latency remains within baseline', points: -3.1, component: 'latency', scope_type: 'region', scope_id: 'eu-west' },288 { text: '−2.4 because East Asia and Oceania are calm', points: -2.4, component: 'availability', scope_type: 'region', scope_id: 'asia-east' },289 ],290 sparkline_1h: sparkline1h(),291 };292}293294// ---------------------------------------------------------------- regions / countries295function regionObj(id) {296 const [, name, continent, lat, lon] = REGION_DEFS.find((d) => d[0] === id);297 const p = Number(clamp(REGION_PRESSURE[id] + drift() * (id === 'na-east' ? 1.4 : 0.3)).toFixed(1));298 const lvl = levelOf(p);299 const probes = PROBES.filter((x) => x.region === id).length;300 const targets = TARGETS.filter((t) => t.region === id).length;301 return { id, name, continent, lat, lon, pressure: p, level: lvl.id, level_label: lvl.label, delta_1h: REGION_DELTA[id], trend: trendOf(REGION_DELTA[id]), confidence: probes ? 0.8 : 0.62,302 components: REGION_COMPONENTS[id], probes, targets, incidents: id === 'na-east' ? 1 : id === 'eu-west' ? 1 : 0, coverage_ok: probes > 0 || targets >= 8, role: probes && targets ? 'both' : probes ? 'probe' : 'target' };303}304const regionsList = () => REGION_DEFS.map(([id]) => regionObj(id));305function countryObj(cc) {306 const [lat, lon] = COUNTRY_CENTROID[cc];307 const p = Number(clamp(COUNTRY_PRESSURE[cc] + drift() * 0.4).toFixed(1));308 const lvl = levelOf(p);309 const probes = PROBES.filter((x) => x.country === cc).length;310 const targets = TARGETS.filter((t) => t.country === cc).length;311 return { cc, name: COUNTRY_NAMES[cc], region: COUNTRY_REGION[cc], lat, lon, pressure: p, level: lvl.id, level_label: lvl.label, delta_1h: COUNTRY_DELTA[cc], trend: trendOf(COUNTRY_DELTA[cc]),312 components: COUNTRY_COMPONENTS[cc], probes, targets, role: probes && targets ? 'both' : probes ? 'probe' : 'target', coverage_ok: probes > 0 || targets >= 4 };313}314const countriesList = () => Object.keys(COUNTRY_PRESSURE).map(countryObj);315316// ---------------------------------------------------------------- incidents317const INCIDENT_START = START - 21 * 60_000;318function incidentNaEast() {319 const p = Number(clamp(71.2 + drift() * 1.5).toFixed(1));320 return {321 event_id: 'evt_01J7QX3M8K2ZP9V4N6B1C0D5EF', slug: '2026-09-12-north-america-east-latency-anomaly', type: 'regional_latency',322 title: 'North America East latency anomaly', summary: 'Elevated latency and packet loss observed from 3 probes toward 41 targets.', status: 'active',323 scope_type: 'region', scope_id: 'na-east', scope_label: 'North America East',324 started_at: iso(INCIDENT_START), updated_at: engineTs(), ended_at: null, duration_s: Math.round((now() - INCIDENT_START) / 1000),325 peak_pressure: 76.0, current_pressure: p, confidence: 0.93, affected_probes: 3, affected_targets: 41, affected_asns: [577, 16276, 6453], affected_services: ['aws', 'github', 'slack'],326 hypotheses: [327 { text: 'Possible upstream transit issue on AS6453 (TATA) transatlantic segment', confidence: 0.6, evidence: ['Route fingerprints changed on 62 % of paths', 'Latency rose on paths crossing AS6453', 'BGP withdrawals 4.8× baseline from rrc00/rrc11'] },328 { text: 'Congestion at a Montréal/New York interconnection', confidence: 0.3, evidence: ['Loss concentrated on ca-qc-01 and ca-bhs-01', 'No change on ie-dub-01 → NA paths'] },329 ],330 };331}332function incidentRouting() {333 return {334 event_id: 'evt_01J7QX7A2B3C4D5E6F7G8H9J0K', slug: '2026-09-12-as6453-routing-instability', type: 'routing_instability',335 title: 'Routing instability around AS6453', summary: 'Withdrawal rate 4.8× baseline and 62 % of transatlantic route fingerprints changed.', status: 'developing',336 scope_type: 'asn', scope_id: '6453', scope_label: 'AS6453 TATA Communications',337 started_at: iso(START - 16 * 60_000), updated_at: engineTs(), ended_at: null, duration_s: Math.round((now() - (START - 16 * 60_000)) / 1000),338 peak_pressure: 58.4, current_pressure: Number(clamp(58.4 + drift()).toFixed(1)), confidence: 0.71, affected_probes: 4, affected_targets: 63, affected_asns: [6453, 3356, 1299], affected_services: ['aws', 'fastly'],339 hypotheses: [{ text: 'Transit reconfiguration or link failure inside AS6453', confidence: 0.55, evidence: ['Origin changes stable (no hijack pattern)', 'Withdrawals concentrated on prefixes with AS6453 in path'] }],340 };341}342const RESOLVED = [343 { event_id: 'evt_01J7Q1A0B1C2D3E4F5G6H7J8K9', slug: '2026-09-12-dns-resolver-disruption-eu-west', type: 'dns_disruption', title: 'DNS resolver disruption in Western Europe', summary: 'SERVFAIL rate 6× baseline on two public resolvers from fr-gra-01 and ie-dub-01.', status: 'resolved', scope_type: 'region', scope_id: 'eu-west', scope_label: 'Western Europe', started_at: iso(START - 690 * 60_000), updated_at: iso(START - 590 * 60_000), ended_at: iso(START - 590 * 60_000), duration_s: 6000, peak_pressure: 48.9, current_pressure: 14.2, confidence: 0.84, affected_probes: 2, affected_targets: 27, affected_asns: [19281, 15169], affected_services: ['quad9', 'google'], hypotheses: [{ text: 'Resolver-side outage at Quad9 European POPs', confidence: 0.7, evidence: ['Disagreement between 9.9.9.9 and 1.1.1.1 answers', 'Authoritative servers answered normally'] }] },344 { event_id: 'evt_01J7P9Z8Y7X6W5V4U3T2S1R0Q9', slug: '2026-09-11-github-service-degradation', type: 'service_degradation', title: 'GitHub service degradation', summary: 'HTTP 5xx on api.github.com from 6 probes for 34 minutes; vendor confirmed 18 minutes later.', status: 'resolved', scope_type: 'service', scope_id: 'github', scope_label: 'GitHub', started_at: iso(START - 31 * 3600_000), updated_at: iso(START - 30.4 * 3600_000), ended_at: iso(START - 30.4 * 3600_000), duration_s: 2040, peak_pressure: 44.1, current_pressure: 33.4, confidence: 0.91, affected_probes: 6, affected_targets: 5, affected_asns: [36459], affected_services: ['github'], hypotheses: [{ text: 'Provider-side API degradation', confidence: 0.85, evidence: ['5xx from all probe regions simultaneously', 'No routing or latency anomaly toward AS36459'] }] },345 { event_id: 'evt_01J7N5M4L3K2J1H0G9F8E7D6C5', slug: '2026-09-09-turkiye-availability-loss', type: 'availability_loss', title: 'Availability loss observed from Türkiye', summary: '38 % of targets unreachable from tr-ist-01 for 52 minutes; probe not excluded (local uplink healthy).', status: 'resolved', scope_type: 'country', scope_id: 'TR', scope_label: 'Türkiye', started_at: iso(START - 70 * 3600_000), updated_at: iso(START - 69.1 * 3600_000), ended_at: iso(START - 69.1 * 3600_000), duration_s: 3120, peak_pressure: 66.8, current_pressure: 33.6, confidence: 0.77, affected_probes: 1, affected_targets: 81, affected_asns: [9121], affected_services: ['meta', 'discord', 'wikipedia'], hypotheses: [{ text: 'National-scale filtering or upstream failure at AS9121', confidence: 0.5, evidence: ['Failures limited to a single probe region', 'TCP resets rather than timeouts on 71 % of failures'] }] },346 { event_id: 'evt_01J7M2B3C4D5E6F7G8H9J0K1L2', slug: '2026-09-08-global-pressure-spike', type: 'global_pressure', title: 'Global pressure spike', summary: 'Global index reached 61.4 for 27 minutes driven by simultaneous routing churn and CDN degradation.', status: 'resolved', scope_type: 'global', scope_id: null, scope_label: 'Global', started_at: iso(START - 97 * 3600_000), updated_at: iso(START - 96.5 * 3600_000), ended_at: iso(START - 96.5 * 3600_000), duration_s: 1620, peak_pressure: 61.4, current_pressure: 42.7, confidence: 0.88, affected_probes: 8, affected_targets: 112, affected_asns: [3356, 54113, 13335], affected_services: ['fastly', 'cloudflare', 'reddit'], hypotheses: [{ text: 'Large transit event at AS3356 propagating to CDN edges', confidence: 0.6, evidence: ['Withdrawals 7× baseline', 'Path changes on 48 % of sampled traceroutes'] }] },347 { event_id: 'evt_01J7K8A9B0C1D2E3F4G5H6J7K8', slug: '2026-09-06-path-instability-asia-se', type: 'path_instability', title: 'Path instability toward Southeast Asia', summary: 'Route fingerprints changed on 71 % of paths to ap-southeast-1 anchored targets.', status: 'resolved', scope_type: 'region', scope_id: 'asia-se', scope_label: 'Southeast Asia', started_at: iso(START - 140 * 3600_000), updated_at: iso(START - 138 * 3600_000), ended_at: iso(START - 138 * 3600_000), duration_s: 7200, peak_pressure: 39.7, current_pressure: 16.4, confidence: 0.66, affected_probes: 5, affected_targets: 22, affected_asns: [2914, 4134], affected_services: ['aws'], hypotheses: [{ text: 'Submarine cable maintenance rerouting via NTT', confidence: 0.4, evidence: ['Hop count +3 on affected paths', 'Latency shift +38 ms'] }] },348];349const activeIncidents = () => [incidentNaEast(), incidentRouting()];350const allIncidents = () => [...activeIncidents(), ...RESOLVED];351function incidentDetail(inc) {352 const start = new Date(inc.started_at).getTime();353 const end = inc.ended_at ? new Date(inc.ended_at).getTime() : now();354 const step = Math.max(60, Math.round((end - start + 30 * 60_000) / 1000 / 180 / 60) * 60);355 const points = [];356 for (let t = start - 30 * 60_000; t <= end; t += step * 1000) {357 const frac = clamp((t - start) / Math.max(1, end - start), 0, 1);358 const shape = t < start ? 0 : inc.ended_at ? Math.sin(frac * Math.PI) : 1 - Math.exp(-frac * 4);359 points.push({ ts: iso(t), pressure: Number(clamp(inc.current_pressure * 0.3 + (inc.peak_pressure - inc.current_pressure * 0.3) * shape + r(-1.2, 1.2)).toFixed(1)), global_pressure: Number(clamp(pressureAt(t)).toFixed(1)) });360 }361 const scope = inc.scope_type;362 return {363 ...inc,364 timeline: [365 { ts: iso(start), status: 'detected', pressure: 46.1, note: 'Component score crossed detect threshold (45) on 2 consecutive cycles' },366 { ts: iso(start + 2 * 60_000), status: 'developing', pressure: 52.3, note: 'Corroborated by 3 probes; BGP withdrawals rising' },367 { ts: iso(start + 6 * 60_000), status: 'active', pressure: inc.peak_pressure, note: 'Peak pressure reached' },368 ...(inc.status === 'resolved' ? [{ ts: iso(end - 10 * 60_000), status: 'recovering', pressure: 24.0, note: 'Below recover threshold (30)' }, { ts: iso(end), status: 'resolved', pressure: inc.current_pressure, note: '10 minutes continuously below threshold' }] : []),369 ],370 evidence: [371 { signal_id: 'ttfb_z', label: 'HTTP time-to-first-byte vs baseline', scope_type: scope, scope_id: inc.scope_id, current: 161.0, baseline: 110.0, robust_z: 5.6, samples: 412, ts: inc.updated_at },372 { signal_id: 'loss', label: 'Packet loss', scope_type: scope, scope_id: inc.scope_id, current: 3.1, baseline: 0.2, robust_z: 4.9, samples: 380, ts: inc.updated_at },373 { signal_id: 'route_change_rate', label: 'Route fingerprint changes vs baseline churn', scope_type: scope, scope_id: inc.scope_id, current: 0.62, baseline: 0.08, robust_z: 6.8, samples: 96, ts: inc.updated_at },374 { signal_id: 'bgp_withdrawals_z', label: 'BGP withdrawals/s vs baseline', scope_type: 'bgp', scope_id: 'withdrawals', current: 52.4, baseline: 11.0, robust_z: 4.76, samples: 60, ts: inc.updated_at },375 { signal_id: 'rtt_z', label: 'ICMP round-trip time vs baseline', scope_type: scope, scope_id: inc.scope_id, current: 47.8, baseline: 39.0, robust_z: 2.7, samples: 512, ts: inc.updated_at },376 ],377 series: { step_seconds: step, points },378 probes: PROBES.filter((p) => inc.scope_type !== 'region' || p.region === inc.scope_id || inc.scope_type === 'asn').slice(0, inc.affected_probes).map((p) => ({ probe_id: p.probe_id, region: p.region, observation: p.region === 'na-east' ? 'TTFB +43 %, loss 3.1 % toward 41 targets' : 'Route change on 12 paths, latency shift +12 ms' })),379 targets: TARGETS.filter((t) => inc.affected_services.includes(t.service_id)).slice(0, 8).map((t) => ({ target_id: t.target_id, name: t.name, service_id: t.service_id, observation: `TTFB ${Math.round(t.ttfb_ms_median_1h * 1.4)} ms (baseline ${t.ttfb_ms_median_1h} ms)` })),380 bgp: inc.type === 'dns_disruption' || inc.type === 'service_degradation' ? null : { withdrawals_ratio: 4.76, announcements_ratio: 1.19, origin_changes: 3 },381 annotations: inc.status === 'resolved' ? [{ ts: iso(end), author: 'spb', text: 'Confirmed by vendor status page; matches submarine cable maintenance notice.' }] : [],382 };383}384385// ---------------------------------------------------------------- fronts386function fronts() {387 return [388 { id: 'front_na-east_eu-west', name: 'North Atlantic Pressure Front', status: 'developing', intensity: Number(clamp(74.0 + drift() * 2).toFixed(1)), confidence: 0.89, direction: 'east', since: iso(START - 19 * 60_000),389 from: { region: 'na-east', name: 'North America East', lat: 43, lon: -76 }, to: { region: 'eu-west', name: 'Western Europe', lat: 49, lon: 3 },390 observed: { latency_pct: 43.0, churn_x: 4.8, loss_pct: 3.1, pairs: 17, targets: 17, route_changes: 9 } },391 { id: 'front_na-east_na-central', name: 'Great Lakes Pressure Front', status: 'active', intensity: Number(clamp(41.5 + drift()).toFixed(1)), confidence: 0.64, direction: 'west', since: iso(START - 11 * 60_000),392 from: { region: 'na-east', name: 'North America East', lat: 43, lon: -76 }, to: { region: 'na-central', name: 'North America Central', lat: 41, lon: -95 },393 observed: { latency_pct: 18.0, churn_x: 1.9, loss_pct: 0.8, pairs: 6, targets: 9, route_changes: 3 } },394 ];395}396397// ---------------------------------------------------------------- bgp / latency / ticker398function bgpStats() {399 const d = DEGRADED ? 0 : drift();400 const w = Number((52.4 + d * 3).toFixed(1));401 const a = Number((760.0 + d * 20).toFixed(1));402 const collectors = [['rrc00', 'Amsterdam', 120.1, 8.0, 210], ['rrc01', 'London', 84.3, 6.1, 96], ['rrc03', 'Amsterdam (AMS-IX)', 96.7, 7.4, 180], ['rrc04', 'Geneva', 41.2, 2.9, 44], ['rrc05', 'Vienna', 38.8, 2.4, 61], ['rrc06', 'Otemachi', 52.0, 3.3, 30], ['rrc10', 'Milan', 47.5, 3.0, 58], ['rrc11', 'New York', 88.9, 9.8, 74], ['rrc12', 'Frankfurt', 71.4, 4.2, 130], ['rrc13', 'Moscow', 22.6, 1.1, 27], ['rrc14', 'Palo Alto', 59.0, 3.4, 52], ['rrc15', 'São Paulo', 37.5, 0.8, 41]]403 .map(([id, location, ann, wd, peers], i) => ({ id, location, announcements_per_s: ann, withdrawals_per_s: wd, peers, last_message: minutesAgo(DEGRADED ? 14 : 0), fresh: !DEGRADED && i !== 9 }));404 const series = [];405 const end = now() - (now() % 60_000);406 for (let i = 59; i >= 0; i--) { const boost = i < 22 ? 1 + (22 - i) / 22 * 3.5 : 1; series.push({ ts: iso(end - i * 60_000), announcements: Math.round(38400 + Math.sin(i / 4) * 2200 + (boost - 1) * 2600), withdrawals: Math.round(660 * boost + Math.sin(i / 3) * 60) }); }407 return { ts: engineTs(), fresh: !DEGRADED, updates_per_s: Number((a + w).toFixed(1)), announcements_per_s: a, withdrawals_per_s: w,408 baseline: { announcements_per_s: 640.0, withdrawals_per_s: 11.0 }, ratio: { announcements: Number((a / 640).toFixed(2)), withdrawals: Number((w / 11).toFixed(2)) },409 unique_prefixes_1m: 14211, unique_origins_1m: 2210, origin_changes_1m: 3, peers: 1450, collectors, series_1h: series,410 top_origins_1h: [[13335, 'Cloudflare', 340, 12], [6453, 'TATA Communications', 2210, 1840], [16509, 'Amazon', 690, 44], [3356, 'Lumen', 1120, 210], [9498, 'Bharti Airtel', 880, 96], [4134, 'China Telecom', 760, 71], [174, 'Cogent', 540, 48], [8075, 'Microsoft', 310, 9], [20940, 'Akamai', 220, 6], [1299, 'Arelion', 480, 130]].map(([asn, name, announcements, withdrawals]) => ({ asn, name, announcements, withdrawals })) };411}412const LAT_PAIRS = [['na-east', 'eu-west', 92.1, 88.0, 0.0, 0.6, 37], ['na-east', 'na-east', 18.4, 12.1, 3.1, 4.9, 44], ['na-east', 'eu-east-med', 131.0, 121.0, 1.2, 2.3, 21], ['na-east', 'asia-se', 226.0, 219.0, 0.4, 0.8, 19], ['na-east', 'oceania', 211.5, 208.0, 0.1, 0.4, 17], ['eu-west', 'eu-west', 9.8, 9.5, 0.0, 0.1, 61], ['eu-west', 'na-east', 94.3, 87.0, 0.9, 2.1, 40], ['eu-west', 'eu-east-med', 48.2, 47.0, 0.0, 0.3, 24], ['eu-west', 'asia-se', 168.7, 166.0, 0.2, 0.5, 22], ['eu-west', 'oceania', 258.0, 255.0, 0.0, 0.3, 14], ['eu-east-med', 'eu-west', 49.9, 47.0, 0.3, 0.9, 25], ['eu-east-med', 'na-east', 139.4, 121.0, 1.8, 3.2, 20], ['eu-east-med', 'mena', 71.0, 69.0, 0.0, 0.4, 12], ['asia-se', 'asia-east', 68.1, 67.0, 0.0, 0.2, 18], ['asia-se', 'na-east', 231.0, 219.0, 0.6, 1.4, 19], ['asia-se', 'asia-south', 61.3, 60.0, 0.1, 0.3, 15], ['asia-se', 'oceania', 96.0, 95.0, 0.0, 0.2, 13], ['oceania', 'na-west', 148.0, 146.0, 0.0, 0.3, 16], ['oceania', 'asia-se', 95.4, 95.0, 0.0, 0.1, 13], ['oceania', 'eu-west', 259.2, 255.0, 0.1, 0.4, 14]];413function latency() {414 return { ts: engineTs(), global: { rtt_ms_median: 41.2, rtt_ms_baseline: 39.0, ttfb_ms_median: 118.0, ttfb_ms_baseline: 110.0, packet_loss_pct: 0.3 },415 matrix: LAT_PAIRS.map(([from, to, rtt, base, loss, z, pairs]) => ({ from, to, rtt_ms: rtt, rtt_ms_baseline: base, ttfb_ms: Number((rtt * 1.7 + 20).toFixed(1)), loss_pct: loss, z, pairs })),416 by_probe: PROBES.map((p, i) => ({ probe_id: p.probe_id, rtt_ms_median: [30.1, 31.4, 27.9, 22.0, 24.6, 44.8, 52.0, 61.3][i], ttfb_ms_median: [90.0, 96.2, 84.1, 71.0, 77.3, 118.0, 131.0, 140.5][i], loss_pct: [3.1, 2.8, 2.4, 0.0, 0.1, 0.9, 0.2, 0.0][i], z: [4.9, 4.4, 3.8, 0.2, 0.3, 1.1, 0.4, 0.1][i] })) };417}418function ticker() {419 const b = bgpStats();420 const regs = regionsList();421 const byLevel = (ids) => regs.filter((x) => ids.includes(x.level)).length;422 return { ts: iso(now() - (now() % 5000)), bgp_updates_per_s: b.updates_per_s, bgp_withdrawals_per_s: b.withdrawals_per_s, bgp_updates_per_min: Math.round(b.updates_per_s * 60),423 probes_active: DEGRADED ? 1 : 8, probes_total: 8, measurements_per_s: DEGRADED ? 1.4 : 12.3, measurements_per_min: DEGRADED ? 84 : 738,424 targets_degraded: TARGETS.filter((t) => t.pressure > 40).length, targets_total: TARGETS_TOTAL, regions_elevated: byLevel(['elevated', 'stressed', 'high']), regions_normal: byLevel(['calm', 'normal']), regions_severe: byLevel(['severe', 'extreme']),425 dns_failures_per_min: 2, median_global_rtt_ms: 41.2, route_changes_per_min: 1.2, active_incidents: activeIncidents().length, internal_status: internalStatus() };426}427428// ---------------------------------------------------------------- routes429const PAIRS = [['ca-qc-01', 'cloudflare-www-cloudflare', 3, false], ['ca-qc-01', 'aws-aws-amazon', 4, false], ['ca-bhs-01', 'github-github', 2, false], ['fr-gra-01', 'aws-s3-amazonaws', 1, false], ['ie-dub-01', 'google-www-google', 0, true], ['tr-ist-01', 'meta-www-facebook', 1, false], ['sg-sin-01', 'openai-api-openai', 0, true], ['au-syd-01', 'cloudflare-www-cloudflare', 0, true], ['ca-qc-02', 'slack-slack', 2, false], ['fr-gra-01', 'anthropic-api-anthropic', 0, true]];430function hash(s) { let h = 0; for (const c of s) h = (h * 31 + c.charCodeAt(0)) >>> 0; return h.toString(16).padStart(8, '0') + (h * 7).toString(16).slice(0, 8); }431function routes(probeId, targetId) {432 const probe = PROBES.find((p) => p.probe_id === probeId) ?? PROBES[0];433 const target = targetById[targetId] ?? TARGETS[0];434 const changed = (PAIRS.find(([p, t]) => p === probe.probe_id && t === target.target_id)?.[2] ?? 0) > 0;435 const transitAsn = probe.region === 'na-east' ? 6453 : probe.region === 'eu-west' ? 1299 : 2914;436 const hopsBase = [437 { n: 1, ip: '192.168.2.1', asn: null, asn_name: null, rtt_ms: 1.2, private: true },438 { n: 2, ip: '10.170.0.1', asn: null, asn_name: null, rtt_ms: 4.8, private: true },439 { n: 3, ip: '64.230.99.13', asn: probe.asn, asn_name: asnById[probe.asn]?.name ?? probe.provider, rtt_ms: 8.9, private: false },440 { n: 4, ip: '64.230.79.112', asn: probe.asn, asn_name: asnById[probe.asn]?.name ?? probe.provider, rtt_ms: 12.4, private: false },441 { n: 5, ip: '4.68.71.173', asn: 3356, asn_name: 'Lumen (Level 3)', rtt_ms: 18.7, private: false },442 { n: 6, ip: '4.69.140.46', asn: 3356, asn_name: 'Lumen (Level 3)', rtt_ms: 22.3, private: false },443 { n: 7, ip: '141.101.72.22', asn: target.asn, asn_name: asnById[target.asn]?.name ?? target.provider, rtt_ms: 28.1, private: false },444 { n: 8, ip: '104.16.132.229', asn: target.asn, asn_name: asnById[target.asn]?.name ?? target.provider, rtt_ms: 30.2, private: false },445 ];446 const hopsCur = changed ? [447 ...hopsBase.slice(0, 4),448 { n: 5, ip: '209.58.86.13', asn: transitAsn, asn_name: asnById[transitAsn]?.name, rtt_ms: 21.9, private: false },449 { n: 6, ip: '66.110.59.21', asn: transitAsn, asn_name: asnById[transitAsn]?.name, rtt_ms: 33.7, private: false },450 { n: 7, ip: '80.231.153.53', asn: transitAsn, asn_name: asnById[transitAsn]?.name, rtt_ms: 38.9, private: false },451 { n: 8, ip: '141.101.72.22', asn: target.asn, asn_name: asnById[target.asn]?.name ?? target.provider, rtt_ms: 41.0, private: false },452 { n: 9, ip: '104.16.132.229', asn: target.asn, asn_name: asnById[target.asn]?.name ?? target.provider, rtt_ms: 42.6, private: false },453 ] : hopsBase;454 const hBase = hash(`${probe.probe_id}|${target.target_id}|base`);455 const hCur = changed ? hash(`${probe.probe_id}|${target.target_id}|cur`) : hBase;456 const hAlt = hash(`${probe.probe_id}|${target.target_id}|alt`);457 const hist = [];458 const end = now() - (now() % 900_000);459 for (let i = 95; i >= 0; i--) { const cur = changed && i < 6; hist.push({ ts: iso(end - i * 900_000), route_hash: cur ? hCur : i % 17 === 5 ? hAlt : hBase, hop_count: cur ? hopsCur.length : i % 17 === 5 ? 9 : hopsBase.length, total_ms: cur ? 42.6 + r(-1, 1) : 30.2 + r(-0.8, 0.8) }); }460 return {461 probe: { probe_id: probe.probe_id, name: probe.name, asn: probe.asn }, target: { target_id: target.target_id, name: target.name, hostname: target.hostname, asn: target.asn },462 current: { ts: iso(end), route_hash: hCur, reached: true, total_ms: hopsCur[hopsCur.length - 1].rtt_ms, hops: hopsCur },463 baseline: { route_hash: hBase, share_7d: changed ? 0.82 : 0.94, first_seen: iso(START - 6.4 * 86400_000), last_seen: changed ? iso(end - 6 * 900_000) : iso(end), hops: hopsBase },464 diff: { changed, added: changed ? hopsCur.slice(4, 7).map((h) => ({ n: h.n, ip: h.ip, asn: h.asn })) : [], removed: changed ? hopsBase.slice(4, 6).map((h) => ({ n: h.n, ip: h.ip, asn: h.asn })) : [],465 asn_path_current: changed ? [probe.asn, transitAsn, target.asn] : [probe.asn, 3356, target.asn], asn_path_baseline: [probe.asn, 3356, target.asn], latency_shift_ms: changed ? 12.4 : 0.0, hop_delta: changed ? 1 : 0 },466 history_24h: hist,467 route_share_7d: changed ? [{ route_hash: hBase, share: 0.82, asn_path: [probe.asn, 3356, target.asn] }, { route_hash: hCur, share: 0.11, asn_path: [probe.asn, transitAsn, target.asn] }, { route_hash: hAlt, share: 0.07, asn_path: [probe.asn, 174, target.asn] }]468 : [{ route_hash: hBase, share: 0.94, asn_path: [probe.asn, 3356, target.asn] }, { route_hash: hAlt, share: 0.06, asn_path: [probe.asn, 174, target.asn] }],469 };470}471472// ---------------------------------------------------------------- history summary473function historySummary(year, month) {474 const top_events = allIncidents().sort((a, b) => b.peak_pressure - a.peak_pressure);475 const top_asns = [[6453, 'TATA Communications', 3, 58.4], [3356, 'Lumen (Level 3)', 2, 61.4], [577, 'Bell Canada', 2, 76.0], [9121, 'Turk Telekom', 1, 66.8], [36459, 'GitHub', 1, 44.1]].map(([asn, name, events, max_pressure]) => ({ asn, name, events, max_pressure }));476 const top_regions = [['na-east', 'North America East', 3, 76.0, 9.4], ['eu-west', 'Western Europe', 2, 48.9, 4.1], ['eu-east-med', 'Eastern Mediterranean', 1, 66.8, 2.7], ['asia-se', 'Southeast Asia', 1, 39.7, 1.2]].map(([id, name, events, max_pressure, hours_elevated]) => ({ id, name, events, max_pressure, hours_elevated }));477 const byType = (t) => top_events.find((e) => e.type === t) ?? null;478 const largest = { pressure: top_events[0], routing: byType('routing_instability'), dns: byType('dns_disruption'), latency: byType('regional_latency') };479 const base = { top_events, top_asns, top_regions, largest, available_months: ['2026-09'] };480 if (year && month) {481 const days = [];482 const dim = new Date(Date.UTC(year, month, 0)).getUTCDate();483 const today = new Date();484 for (let d = 1; d <= dim; d++) {485 const dt = new Date(Date.UTC(year, month - 1, d));486 if (dt > today) break;487 if (dt < new Date(Date.UTC(2026, 8, 6))) { continue; } // observatory started 2026-09-06488 const dayEvents = allIncidents().filter((e) => e.started_at.startsWith(dt.toISOString().slice(0, 10))).length;489 const max = Number(clamp(31 + r(-4, 6) + (dayEvents ? r(8, 30) : 0)).toFixed(1));490 days.push({ date: dt.toISOString().slice(0, 10), min: Number(clamp(max - r(14, 22)).toFixed(1)), max, avg: Number(clamp(max - r(6, 12)).toFixed(1)), events: dayEvents });491 }492 return { year, month, days, ...base };493 }494 const months = [{ month: '2026-09', min: 18.0, max: 76.0, avg: 30.2, events: allIncidents().length, days_observed: 7 }];495 return year ? { year, months, ...base } : { years: [2026], months, ...base };496}497498// ---------------------------------------------------------------- explain / methodology499function explain() {500 const g = globalPressure();501 const sig = (component) => ({502 routing: [{ signal_id: 'bgp_withdrawals_z', label: 'BGP withdrawals/s vs baseline', scope_type: 'global', scope_id: null, current: 52.4, baseline_median: 11.0, mad: 2.1, robust_z: 8.0, samples: 60, stress: 0.92, contribution: 9.1 }, { signal_id: 'bgp_announcements_z', label: 'BGP announcements/s vs baseline', scope_type: 'global', scope_id: null, current: 760.0, baseline_median: 640.0, mad: 48.0, robust_z: 2.5, samples: 60, stress: 0.31, contribution: 2.0 }, { signal_id: 'bgp_origin_changes_z', label: 'Origin ASN changes vs baseline', scope_type: 'global', scope_id: null, current: 3, baseline_median: 1, mad: 0.7, robust_z: 2.9, samples: 60, stress: 0.36, contribution: 2.9 }, { signal_id: 'bgp_collector_disagreement', label: 'Collector disagreement', scope_type: 'global', scope_id: null, current: 0.21, baseline_median: 0.06, mad: 0.02, robust_z: 7.5, samples: 12, stress: 0.6, contribution: 0.3 }],503 latency: [{ signal_id: 'ttfb_z', label: 'HTTP time-to-first-byte vs baseline', scope_type: 'region', scope_id: 'na-east', current: 161.0, baseline_median: 110.0, mad: 9.0, robust_z: 5.6, samples: 412, stress: 0.71, contribution: 6.2 }, { signal_id: 'loss', label: 'Packet loss', scope_type: 'region', scope_id: 'na-east', current: 3.1, baseline_median: 0.2, mad: 0.2, robust_z: 8.0, samples: 380, stress: 0.66, contribution: 2.6 }, { signal_id: 'rtt_z', label: 'ICMP round-trip time vs baseline', scope_type: 'global', scope_id: null, current: 41.2, baseline_median: 39.0, mad: 1.4, robust_z: 1.6, samples: 2048, stress: 0.12, contribution: 0.4 }, { signal_id: 'tcp_z', label: 'TCP connect latency vs baseline', scope_type: 'region', scope_id: 'eu-west', current: 24.1, baseline_median: 23.8, mad: 1.1, robust_z: 0.3, samples: 620, stress: 0.02, contribution: -0.3 }],504 dns: [{ signal_id: 'dns_fail_rate', label: 'DNS SERVFAIL / timeout rate', scope_type: 'global', scope_id: null, current: 0.0034, baseline_median: 0.0028, mad: 0.0006, robust_z: 1.0, samples: 1810, stress: 0.14, contribution: 1.4 }, { signal_id: 'dns_latency_z', label: 'DNS lookup latency vs baseline', scope_type: 'global', scope_id: null, current: 21.2, baseline_median: 20.1, mad: 1.9, robust_z: 0.6, samples: 1810, stress: 0.06, contribution: 0.9 }, { signal_id: 'resolver_disagreement', label: 'Resolver disagreement', scope_type: 'global', scope_id: null, current: 0.01, baseline_median: 0.01, mad: 0.004, robust_z: 0.0, samples: 1810, stress: 0.0, contribution: 0.6 }],505 availability: [{ signal_id: 'target_down_corroborated', label: 'Targets failing from ≥2 probe regions', scope_type: 'global', scope_id: null, current: 4, baseline_median: 0, mad: 0.5, robust_z: 8.0, samples: TARGETS_TOTAL, stress: 0.46, contribution: 3.9 }, { signal_id: 'fail_rate_z', label: 'Failure rate vs baseline', scope_type: 'service', scope_id: 'aws', current: 0.021, baseline_median: 0.01, mad: 0.003, robust_z: 3.7, samples: 240, stress: 0.4, contribution: 1.7 }],506 http_tls: [{ signal_id: 'tls_fail_rate', label: 'TLS handshake failures', scope_type: 'global', scope_id: null, current: 0.008, baseline_median: 0.005, mad: 0.001, robust_z: 3.0, samples: 3400, stress: 0.35, contribution: 1.6 }, { signal_id: 'http_5xx_rate', label: 'HTTP 5xx rate', scope_type: 'global', scope_id: null, current: 0.0065, baseline_median: 0.005, mad: 0.001, robust_z: 1.5, samples: 3400, stress: 0.2, contribution: 1.2 }, { signal_id: 'reset_timeout_rate', label: 'Connection resets / timeouts', scope_type: 'global', scope_id: null, current: 0.004, baseline_median: 0.004, mad: 0.001, robust_z: 0.0, samples: 3400, stress: 0.0, contribution: 0.0 }],507 path: [{ signal_id: 'route_change_rate', label: 'Route fingerprint changes vs baseline churn', scope_type: 'region', scope_id: 'na-east', current: 0.62, baseline_median: 0.08, mad: 0.03, robust_z: 8.0, samples: 96, stress: 0.8, contribution: 3.4 }, { signal_id: 'hop_count_z', label: 'Hop count deviation', scope_type: 'global', scope_id: null, current: 11.4, baseline_median: 10.9, mad: 0.6, robust_z: 0.8, samples: 96, stress: 0.1, contribution: 0.4 }, { signal_id: 'path_latency_shift', label: 'Latency shift on changed paths', scope_type: 'asn', scope_id: '6453', current: 12.4, baseline_median: 0.8, mad: 1.1, robust_z: 8.0, samples: 41, stress: 0.7, contribution: 1.7 }],508 corroboration: [{ signal_id: 'vendor_incidents', label: 'Public incidents declared by major providers', scope_type: 'service', scope_id: 'aws', current: 1, baseline_median: 0, mad: 0.3, robust_z: 3.3, samples: 22, stress: 0.22, contribution: 1.1 }],509 })[component];510 return { ts: g.ts, pressure: g.pressure, components: g.components.map((c) => ({ id: c.id, score: c.score, weight: c.weight, contribution: c.contribution, signals: sig(c.id) })), excluded_probes: [],511 notes: ['Baseline: trailing 7 days, same hour of day ±1 h, most recent 10 minutes excluded.', 'Robust z clipped to [−3, 8]; component score = 100 × (1 − e^(−0.35 × stress)).', 'Weights sum to 1.0 (pressure.yaml v1).'] };512}513const METHODOLOGY = { weights: WEIGHTS, levels: LEVELS, engine: { cycle_seconds: 10, window_seconds: 120, bgp_window_seconds: 60, baseline_days: 7, baseline_exclude_seconds: 600, baseline_min_samples: 24, seasonality: 'hour_of_day', seasonality_min_days: 3, z_clip_low: -3.0, z_clip_high: 8.0, z_anomaly: 3.0, saturation_k: 0.35, min_probes_for_scoring: 2, probe_fresh_seconds: 180, probe_local_failure_ratio: 0.8, bgp_fresh_seconds: 120 },514 components: { latency: { signals: [{ id: 'ttfb_z', label: 'HTTP time-to-first-byte vs baseline', weight: 0.35 }, { id: 'tcp_z', label: 'TCP connect latency vs baseline', weight: 0.25 }, { id: 'rtt_z', label: 'ICMP round-trip time vs baseline', weight: 0.25 }, { id: 'loss', label: 'Packet loss', weight: 0.15 }] }, dns: { signals: [{ id: 'dns_fail_rate', label: 'DNS SERVFAIL / timeout rate', weight: 0.45 }, { id: 'dns_latency_z', label: 'DNS lookup latency vs baseline', weight: 0.3 }, { id: 'resolver_disagreement', label: 'Resolver disagreement', weight: 0.25 }] }, availability: { signals: [{ id: 'target_down_corroborated', label: 'Targets failing from ≥2 probe regions', weight: 0.7 }, { id: 'fail_rate_z', label: 'Failure rate vs baseline', weight: 0.3 }] }, http_tls: { signals: [{ id: 'http_5xx_rate', label: 'HTTP 5xx rate', weight: 0.35 }, { id: 'tls_fail_rate', label: 'TLS handshake failures', weight: 0.35 }, { id: 'reset_timeout_rate', label: 'Connection resets / timeouts', weight: 0.3 }] }, path: { signals: [{ id: 'route_change_rate', label: 'Route fingerprint changes vs baseline churn', weight: 0.6 }, { id: 'hop_count_z', label: 'Hop count deviation', weight: 0.2 }, { id: 'path_latency_shift', label: 'Latency shift on changed paths', weight: 0.2 }] }, routing: { signals: [{ id: 'bgp_withdrawals_z', label: 'BGP withdrawals/s vs baseline', weight: 0.4 }, { id: 'bgp_announcements_z', label: 'BGP announcements/s vs baseline', weight: 0.25 }, { id: 'bgp_origin_changes_z', label: 'Origin ASN changes vs baseline', weight: 0.2 }, { id: 'bgp_collector_disagreement', label: 'Collector disagreement', weight: 0.15 }] }, corroboration: { signals: [{ id: 'vendor_incidents', label: 'Public incidents declared by major providers', weight: 1.0 }] } },515 events: { detect_threshold: 45, confirm_cycles: 2, active_cycles: 6, recover_threshold: 30, resolve_after_seconds: 600, min_confidence: 0.45 }, fronts: { min_pairs: 3, z_threshold: 2.5, min_intensity: 35 },516 version: 1, updated_at: '2026-09-12T01:54:00Z' };517518// ---------------------------------------------------------------- detail objects519const probeList = () => PROBES.map((p) => ({ ...p, last_seen: DEGRADED && p.probe_id !== 'fr-gra-01' ? iso(START - 14 * 60_000) : iso(now() - (now() % 10_000) - 3000), status: DEGRADED && p.probe_id !== 'fr-gra-01' ? 'stale' : 'online' }));520const targetRow = (t) => ({ target_id: t.target_id, name: t.name, pressure: t.pressure, ok_ratio_1h: t.ok_ratio_1h, ttfb_ms_median: t.ttfb_ms_median_1h });521const serviceObj = ([slug, name, category, asn, source, indicator]) => {522 const p = SERVICE_PRESSURE[slug];523 const targets = TARGETS.filter((t) => t.service_id === slug);524 const affected = slug === 'aws' ? ['na-east', 'eu-west'] : slug === 'github' || slug === 'slack' ? ['na-east'] : [];525 return { slug, name, category, pressure: p, level: levelOf(p).id, observed_availability_24h: Number(clamp(1 - p / 4000 - (p > 30 ? 0.002 : 0), 0, 1).toFixed(4)), targets: targets.length, affected_regions: affected,526 vendor_status: source ? { indicator, incidents: indicator === 'none' ? 0 : 1, source, checked_at: minutesAgo(1) } : null, asn };527};528function serviceDetail(svc) {529 const s = serviceObj(svc);530 const targets = TARGETS.filter((t) => t.service_id === s.slug);531 const observedAff = s.affected_regions.map((id) => ({ id, name: REGION_DEFS.find((d) => d[0] === id)[1], observation: id === 'na-east' ? 'Elevated TTFB (+38 %) and 2.1× failure rate from 3 probes' : 'Elevated TLS latency from 2 probes' }));532 const vendorNone = s.vendor_status && s.vendor_status.indicator === 'none';533 return { ...s, affected_regions: observedAff,534 observed: { availability_24h: s.observed_availability_24h, availability_1h: Number(clamp(s.observed_availability_24h - (s.pressure > 30 ? 0.004 : 0), 0, 1).toFixed(4)), ttfb_ms_median_1h: targets[0]?.ttfb_ms_median_1h ?? 80, ttfb_ms_baseline: Math.round((targets[0]?.ttfb_ms_median_1h ?? 80) * (s.pressure > 30 ? 0.72 : 0.96)), tls_ms_median_1h: 30.1, failures_1h: s.pressure > 30 ? 14 : 2 },535 vendor_status: s.vendor_status ? { ...s.vendor_status, titles: s.vendor_status.incidents ? ['Increased error rates in US-EAST-1 (EC2 API)'] : [], url: `https://${s.vendor_status.source}` } : null,536 discrepancy: observedAff.length && vendorNone ? `Vendor reports no incident; we observe ${observedAff[0].observation.toLowerCase()}.` : null,537 matrix: probeList().map((p) => ({ probe_id: p.probe_id, probe_region: p.region, targets: targets.map((t) => { const stress = p.region === 'na-east' && s.pressure > 30 ? 2.4 : 0.6; const z = Number((r(-0.5, 1.2) * stress + (stress > 1 ? 1.4 : 0)).toFixed(1)); return { target_id: t.target_id, ok: z < 4.5, ttfb_ms: Number((t.ttfb_ms_median_1h * (1 + Math.max(0, z) * 0.12)).toFixed(1)), z, ts: p.last_seen }; }) })),538 targets: targets.map(targetRow), history_24h: history24('service', s.slug), incidents: allIncidents().filter((i) => i.affected_services.includes(s.slug)) };539}540function asnDetail(a) {541 const targets = TARGETS.filter((t) => t.asn === a.asn);542 const lvl = levelOf(a.pressure);543 const churn = a.asn === 6453 ? 4.9 : 1.1;544 const series = [];545 const end = now() - (now() % 3600_000);546 for (let i = 23; i >= 0; i--) series.push({ ts: iso(end - i * 3600_000), announcements: Math.round((a.prefixes_observed / 4) * (i === 0 && a.asn === 6453 ? churn : 1) * (0.8 + Math.sin(i) * 0.1)), withdrawals: Math.round((a.prefixes_observed / 90) * (i === 0 && a.asn === 6453 ? churn * 3 : 1)) });547 return { asn: a.asn, name: a.name, country: a.country, importance: a.importance, ts: engineTs(), pressure: a.pressure, level: lvl.id, level_label: lvl.label, delta_1h: a.asn === 6453 ? 22.4 : a.asn === 577 ? 9.1 : -1.0, trend: a.asn === 6453 || a.asn === 577 ? 'rising' : 'falling', confidence: 0.7,548 components: { routing: Number(clamp(a.pressure * 0.7 * churn).toFixed(1)), latency: Number(clamp(a.pressure * 1.2).toFixed(1)), availability: Number(clamp(a.pressure * 0.5).toFixed(1)), dns: Number(clamp(a.pressure * 0.2).toFixed(1)), http_tls: Number(clamp(a.pressure * 0.3).toFixed(1)), path: Number(clamp(a.pressure * 0.8).toFixed(1)) },549 bgp: { prefixes_observed_24h: a.prefixes_observed, announcements_1h: series[23].announcements, withdrawals_1h: series[23].withdrawals, churn_ratio: churn, origin_changes_1h: a.asn === 6453 ? 2 : 0, path_stability: a.asn === 6453 ? 0.61 : 0.97, series_24h: series },550 regions_observed: a.asn === 6453 ? ['na-east', 'eu-west', 'eu-east-med', 'asia-se'] : ['na-east', 'eu-west', 'eu-east-med'], targets: targets.map(targetRow), history_24h: history24('asn', String(a.asn)), incidents: allIncidents().filter((i) => i.affected_asns.includes(a.asn)) };551}552function regionDetail(id) {553 const rg = regionObj(id);554 const asns = ASNS.filter((a) => (id === 'na-east' ? ['CA', 'US'].includes(a.country) : id === 'eu-west' ? ['FR', 'NL', 'DE', 'SE'].includes(a.country) : true)).slice(0, 8);555 const svcs = SERVICES.map(serviceObj).filter((s) => TARGETS.some((t) => t.service_id === s.slug && t.region === id)).slice(0, 10);556 return { ...rg, history_24h: history24('region', id), baseline_7d: { median: Number((rg.pressure * 0.62).toFixed(1)), p90: Number((rg.pressure * 0.95).toFixed(1)) }, incidents: allIncidents().filter((i) => i.scope_id === id),557 top_asns: asns.map((a) => ({ asn: a.asn, name: a.name, pressure: a.pressure })), top_services: svcs.map((s) => ({ slug: s.slug, name: s.name, pressure: s.pressure, observed_availability_24h: s.observed_availability_24h })),558 probes: probeList().filter((p) => p.region === id), matrix: latency().matrix.filter((m) => m.from === id || m.to === id) };559}560function countryDetail(cc) {561 const c = countryObj(cc);562 const targets = TARGETS.filter((t) => t.country === cc);563 return { ...c, history_24h: history24('country', cc), baseline_7d: { median: Number((c.pressure * 0.7).toFixed(1)), p90: Number((c.pressure * 1.02).toFixed(1)) }, incidents: allIncidents().filter((i) => i.scope_id === cc || (i.scope_id === c.region && i.scope_type === 'region')),564 asns: ASNS.filter((a) => a.country === cc).map((a) => ({ asn: a.asn, name: a.name, pressure: a.pressure })), services: [...new Set(targets.map((t) => t.service_id))].map((slug) => serviceObj(SERVICES.find((s) => s[0] === slug))).map((s) => ({ slug: s.slug, name: s.name, pressure: s.pressure, observed_availability_24h: s.observed_availability_24h })),565 probes: probeList().filter((p) => p.country === cc), targets: targets.map((t) => ({ target_id: t.target_id, name: t.name, category: t.category, pressure: t.pressure, ok_ratio_1h: t.ok_ratio_1h, ttfb_ms_median: t.ttfb_ms_median_1h })) };566}567function targetDetail(t) {568 const pts = [];569 const end = now() - (now() % 60_000);570 for (let i = 1439; i >= 0; i -= 5) pts.push({ ts: iso(end - i * 60_000), ttfb_ms_p50: Number((t.ttfb_ms_median_1h * (1 + (i < 45 && t.pressure > 35 ? (45 - i) / 45 * 0.4 : 0) + Math.sin(i / 20) * 0.04)).toFixed(1)), ok_ratio: Number(clamp(i < 45 && t.pressure > 40 ? 0.93 + r(0, 0.05, 3) : 1, 0, 1).toFixed(3)) });571 return { ...t, latest_by_probe: probeList().map((p) => ({ probe_id: p.probe_id, kind: 'http', ts: p.last_seen, ok: true, error: null, dns_ms: r(4, 30), tcp_ms: r(8, 90), tls_ms: r(10, 120), ttfb_ms: Number((t.ttfb_ms_median_1h * (p.region === 'na-east' && t.pressure > 35 ? 1.4 : 1) + r(-8, 8)).toFixed(1)), http_status: 200, resolved_ip: `104.16.${Math.floor(rnd() * 255)}.${Math.floor(rnd() * 255)}`, packet_loss: p.region === 'na-east' ? 3.1 : 0.0, rtt_avg_ms: r(10, 200), z: p.region === 'na-east' && t.pressure > 35 ? r(3, 6) : r(-1, 1.5) })),572 series_24h: { step_seconds: 300, points: pts }, dns: { resolvers: [['local', 'NOERROR', 2, 4.1], ['8.8.8.8', 'NOERROR', 2, 12.3], ['1.1.1.1', 'NOERROR', 2, 9.8], ['9.9.9.9', 'NOERROR', 2, 14.6]].map(([resolver, rcode, answers, ms]) => ({ resolver, rcode, answers, ms })), disagreement: false } };573}574function search(q) {575 const s = q.trim().toLowerCase();576 if (!s) return [];577 const out = [];578 for (const c of countriesList()) if (c.name.toLowerCase().includes(s) || c.cc.toLowerCase() === s) out.push({ type: 'country', id: c.cc, label: c.name, href: `/country/${c.cc.toLowerCase()}`, pressure: c.pressure });579 for (const rg of regionsList()) if (rg.name.toLowerCase().includes(s) || rg.id.includes(s)) out.push({ type: 'region', id: rg.id, label: rg.name, href: `/internet/${rg.id}`, pressure: rg.pressure });580 for (const a of ASNS) if (a.name.toLowerCase().includes(s) || String(a.asn).includes(s.replace(/^as/, ''))) out.push({ type: 'asn', id: String(a.asn), label: `AS${a.asn} ${a.name}`, href: `/asn/${a.asn}`, pressure: a.pressure });581 for (const sv of SERVICES) if (sv[1].toLowerCase().includes(s) || sv[0].includes(s)) out.push({ type: 'service', id: sv[0], label: sv[1], href: `/service/${sv[0]}`, pressure: SERVICE_PRESSURE[sv[0]] });582 for (const t of TARGETS) if (t.hostname.includes(s)) out.push({ type: 'target', id: t.target_id, label: t.hostname, href: `/targets?q=${encodeURIComponent(t.hostname)}`, pressure: t.pressure });583 for (const i of allIncidents()) if (i.title.toLowerCase().includes(s)) out.push({ type: 'incident', id: i.slug, label: i.title, href: `/event/${i.slug}`, pressure: i.peak_pressure });584 return out.slice(0, 20);585}586587// ---------------------------------------------------------------- admin state588let adminConfig = JSON.parse(JSON.stringify({ version: 1, pressure_weights: WEIGHTS, levels: LEVELS, engine: METHODOLOGY.engine, components: METHODOLOGY.components, importance_weights: { 1: 0.4, 2: 0.7, 3: 1.0, 4: 1.5, 5: 2.2 }, events: METHODOLOGY.events, fronts: METHODOLOGY.fronts, scheduler: { tiers: { 1: 20, 2: 45, 3: 180 }, dns_every: 60, ping_every: 30, traceroute_every: 900, boost_factor: 0.5, boost_seconds: 900, batch_flush_seconds: 10, max_batch: 500, config_refresh_seconds: 300 } }));589const adminTargets = TARGETS.map((t) => ({ ...t, enabled: true }));590const adminProbes = PROBES.map((p) => ({ ...p, enabled: true }));591const adminAnnotations = [{ id: 'ann_1', ts: iso(START - 590 * 60_000), author: 'spb', scope_type: 'region', scope_id: 'eu-west', text: 'Quad9 confirmed European resolver incident.' }];592const incidentReview = {};593function adminOverview() {594 const b = bgpStats();595 return { probes: probeList().map((p, i) => ({ ...p, health: { uptime_24h: p.uptime_24h, clock_offset_ms: p.clock_offset_ms, missing_ratio_1h: [0.002, 0.004, 0.001, 0.0, 0.003, 0.011, 0.006, 0.002][i], error_rate_1h: [0.031, 0.028, 0.024, 0.004, 0.006, 0.019, 0.007, 0.003][i], buffered: [0, 0, 0, 0, 0, 12, 0, 0][i], spool_bytes: [0, 0, 0, 0, 0, 48120, 0, 0][i], version: p.version, last_health: p.last_seen } })),596 ingest: { batches_per_min: 62, measurements_per_min: 738, rejected_per_min: 0, last_batch: minutesAgo(0) },597 stores: { clickhouse: { ok: true, inserts_per_s: 14.2, tables: [['measurements', 41_221_930, 6_412_000_000, iso(START - 6.4 * 86400_000), minutesAgo(0)], ['traceroutes', 214_880, 912_000_000, iso(START - 6.4 * 86400_000), minutesAgo(2)], ['bgp_events', 189_400_120, 21_800_000_000, iso(START - 2 * 86400_000), minutesAgo(0)], ['bgp_stats', 9_216, 1_900_000, iso(START - 6.4 * 86400_000), minutesAgo(0)], ['pressure_history', 55_296, 12_400_000, iso(START - 6.4 * 86400_000), minutesAgo(0)], ['signal_features', 2_211_840, 480_000_000, iso(START - 6.4 * 86400_000), minutesAgo(0)], ['probe_health', 92_160, 8_100_000, iso(START - 6.4 * 86400_000), minutesAgo(0)]].map(([name, rows, bytes, oldest, newest]) => ({ name, rows, bytes, oldest, newest })) }, postgres: { ok: true, size_bytes: 188_000_000 }, redis: { ok: true, used_memory_bytes: 41_000_000, keys: 1284 } },598 bgp: { collectors: b.collectors, messages_per_s: b.updates_per_s, fresh: b.fresh, reconnects_24h: 2 },599 engine: { last_run: engineTs(), cycle_ms_p50: 412, cycle_ms_max: 1180, runs_1h: 360, errors_1h: 0, internal_status: internalStatus(), excluded_probes: [] },600 corroboration: [['cloudflare-status', 'Cloudflare status', true, 0], ['aws-health', 'AWS Health', true, 1], ['github-status', 'GitHub status', true, 0], ['google-cloud-status', 'Google Cloud status', true, 0], ['azure-status', 'Azure status', false, 0], ['ripe-ris', 'RIPE RIS Live', true, 0]].map(([id, name, ok, incidents]) => ({ id, name, ok, last_fetch: minutesAgo(ok ? 2 : 41), incidents })) };601}602function baselines(signal_id) {603 const pts = [];604 const end = now() - (now() % 60_000);605 const median = signal_id === 'ttfb_z' ? 110 : signal_id === 'bgp_withdrawals_z' ? 11 : 40;606 const mad = median * 0.08;607 for (let i = 1439; i >= 0; i -= 5) { const spike = i < 45 ? (45 - i) / 45 * median * 0.45 : 0; const value = Number((median + Math.sin(i / 30) * mad * 1.2 + spike + r(-mad * 0.6, mad * 0.6)).toFixed(1)); pts.push({ ts: iso(end - i * 60_000), value, median, mad: Number(mad.toFixed(2)), z: Number(((value - median) / mad).toFixed(2)) }); }608 return { signal_id, points: pts, samples: 8064, baseline_days: 7 };609}610function rawTable(table, limit) {611 const cols = { measurements: ['ts', 'probe_id', 'target_id', 'kind', 'ok', 'dns_ms', 'tcp_ms', 'tls_ms', 'ttfb_ms', 'http_status'], traceroutes: ['ts', 'probe_id', 'target_id', 'route_hash', 'hop_count', 'total_ms', 'reached'], bgp_events: ['ts', 'collector', 'peer_asn', 'prefix', 'origin_asn', 'event_type', 'as_path'], bgp_stats: ['ts', 'collector', 'announcements', 'withdrawals', 'peers'], pressure_history: ['ts', 'scope_type', 'scope_id', 'pressure', 'confidence'], signal_features: ['ts', 'signal_id', 'scope_type', 'scope_id', 'current', 'median', 'mad', 'robust_z'], probe_health: ['ts', 'probe_id', 'uptime', 'clock_offset_ms', 'buffered', 'version'] }[table] ?? ['ts', 'value'];612 const rows = [];613 for (let i = 0; i < Math.min(limit, 200); i++) {614 const ts = iso(now() - i * 7000);615 const p = PROBES[i % PROBES.length];616 const t = TARGETS[(i * 7) % TARGETS.length];617 rows.push({ measurements: [ts, p.probe_id, t.target_id, 'http', true, r(3, 30), r(8, 90), r(10, 120), r(40, 300), 200], traceroutes: [ts, p.probe_id, t.target_id, hash(ts + p.probe_id), 8 + (i % 4), r(20, 80), true], bgp_events: [ts, 'rrc00', 3356, `104.16.${i % 255}.0/24`, 13335, i % 9 === 0 ? 'W' : 'A', '3356 13335'], bgp_stats: [ts, 'rrc00', 118 + i % 13, 8 + i % 5, 210], pressure_history: [ts, 'global', null, pressureAt(now() - i * 10_000), 0.85], signal_features: [ts, 'ttfb_z', 'region', 'na-east', 161 - i * 0.3, 110, 9, Number(((161 - i * 0.3 - 110) / 9).toFixed(2))], probe_health: [ts, p.probe_id, 0.998, p.clock_offset_ms, 0, p.version] }[table] ?? [ts, i]);618 }619 return { columns: cols, rows };620}621622// ---------------------------------------------------------------- HTTP plumbing623const json = (res, status, body, extra = {}) => {624 const data = JSON.stringify(body);625 res.writeHead(status, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-store', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'X-IP-Admin-Token, Content-Type', 'Access-Control-Allow-Methods': 'GET,POST,PUT,PATCH,DELETE,OPTIONS', ...extra });626 res.end(data);627};628const notFound = (res) => json(res, 404, { error: 'not_found' });629const readBody = (req) => new Promise((resolve) => { let b = ''; req.on('data', (c) => (b += c)); req.on('end', () => { try { resolve(b ? JSON.parse(b) : {}); } catch { resolve({}); } }); });630631// SSE clients632const clients = new Set();633let eventId = 1;634function broadcast(event, data) {635 const payload = `id: ${eventId++}\nevent: ${event}\ndata: ${JSON.stringify(data)}\n\n`;636 for (const res of clients) res.write(payload);637}638setInterval(() => { for (const res of clients) res.write(': ping\n\n'); }, 15_000);639setInterval(() => {640 if (DEGRADED) { broadcast('internal_status', { ts: iso(now()), internal_status: 'degraded', reason: 'Only 1 of 8 probes fresh (min 2); score frozen' }); return; }641 cycle++;642 broadcast('global_pressure_update', globalPressure());643 broadcast('regional_pressure_update', { ts: engineTs(), regions: regionsList(), countries: countriesList().map((c) => ({ cc: c.cc, pressure: c.pressure, level: c.level, delta_1h: c.delta_1h })) });644 broadcast('front_update', { ts: engineTs(), fronts: fronts() });645 broadcast('probe_stats', { ts: engineTs(), probes_active: 8, probes_total: 8, measurements_per_s: 12.3, excluded: [] });646 if (cycle % 6 === 0) broadcast('incident_updated', incidentNaEast());647}, 10_000);648setInterval(() => { broadcast('ticker', ticker()); const b = bgpStats(); broadcast('bgp_stats', { ts: b.ts, updates_per_s: b.updates_per_s, announcements_per_s: b.announcements_per_s, withdrawals_per_s: b.withdrawals_per_s, ratio: b.ratio, fresh: b.fresh }); }, 5_000);649650const server = http.createServer(async (req, res) => {651 const url = new URL(req.url, `http://${req.headers.host}`);652 const path = url.pathname.replace(/\/+$/, '') || '/';653 const q = url.searchParams;654 if (req.method === 'OPTIONS') return json(res, 204, {});655656 // ---- SSE657 if (path === '/api/v1/live') {658 // `no-transform` stops intermediaries (incl. the Next dev rewrite proxy) from gzip-buffering the stream.659 res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-store, no-transform', Connection: 'keep-alive', 'X-Accel-Buffering': 'no', 'Access-Control-Allow-Origin': '*' });660 res.write('retry: 5000\n\n');661 res.write(`id: ${eventId++}\nevent: snapshot\ndata: ${JSON.stringify({ global: globalPressure(), ticker: ticker(), regions: regionsList(), fronts: fronts(), incidents: activeIncidents() })}\n\n`);662 if (DEGRADED) res.write(`id: ${eventId++}\nevent: internal_status\ndata: ${JSON.stringify({ ts: iso(now()), internal_status: 'degraded', reason: 'Only 1 of 8 probes fresh (min 2); score frozen' })}\n\n`);663 clients.add(res);664 req.on('close', () => clients.delete(res));665 return;666 }667668 // ---- admin669 if (path.startsWith('/api/admin')) {670 if (req.headers['x-ip-admin-token'] !== ADMIN_TOKEN) return json(res, 401, { error: 'unauthorized' });671 const body = ['POST', 'PUT', 'PATCH'].includes(req.method) ? await readBody(req) : {};672 if (path === '/api/admin/overview') return json(res, 200, adminOverview());673 if (path === '/api/admin/targets' && req.method === 'GET') return json(res, 200, { targets: adminTargets });674 if (path === '/api/admin/targets' && req.method === 'POST') { if (!body.target_id || !body.hostname) return json(res, 422, { error: 'validation', detail: 'target_id and hostname required' }); const t = { importance: 3, tier: 2, enabled: true, pressure: 0, ok_ratio_1h: 1, ttfb_ms_median_1h: 0, ...body }; adminTargets.unshift(t); return json(res, 201, t); }675 let m = path.match(/^\/api\/admin\/targets\/([^/]+)$/);676 if (m) { const i = adminTargets.findIndex((t) => t.target_id === decodeURIComponent(m[1])); if (i < 0) return notFound(res); if (req.method === 'PATCH') { Object.assign(adminTargets[i], body); return json(res, 200, adminTargets[i]); } if (req.method === 'DELETE') { adminTargets.splice(i, 1); return json(res, 200, { ok: true }); } return json(res, 200, adminTargets[i]); }677 if (path === '/api/admin/probes' && req.method === 'GET') return json(res, 200, { probes: adminProbes });678 if (path === '/api/admin/probes' && req.method === 'POST') { if (!body.probe_id || !body.region) return json(res, 422, { error: 'validation', detail: 'probe_id and region required' }); const p = { status: 'offline', last_seen: null, version: null, measurements_1h: 0, uptime_24h: 0, clock_offset_ms: 0, capabilities: [], enabled: true, ...body }; adminProbes.push(p); return json(res, 201, { ...p, key: [...Array(64)].map(() => Math.floor(rnd() * 16).toString(16)).join('') }); }679 m = path.match(/^\/api\/admin\/probes\/([^/]+)\/rotate-key$/);680 if (m && req.method === 'POST') { const p = adminProbes.find((x) => x.probe_id === m[1]); if (!p) return notFound(res); return json(res, 200, { ...p, key: [...Array(64)].map(() => Math.floor(rnd() * 16).toString(16)).join('') }); }681 m = path.match(/^\/api\/admin\/probes\/([^/]+)$/);682 if (m) { const p = adminProbes.find((x) => x.probe_id === m[1]); if (!p) return notFound(res); if (req.method === 'PATCH') Object.assign(p, body); return json(res, 200, p); }683 if (path === '/api/admin/config') { if (req.method === 'PUT') { const sum = Object.values(body.pressure_weights ?? {}).reduce((a, b) => a + Number(b), 0); if (Math.abs(sum - 1) > 0.001) return json(res, 422, { error: 'validation', detail: `weights sum to ${sum.toFixed(3)}, expected 1.000` }); adminConfig = { ...adminConfig, ...body, version: (adminConfig.version ?? 1) + 1 }; } return json(res, 200, adminConfig); }684 if (path === '/api/admin/baselines') return json(res, 200, baselines(q.get('signal_id') ?? 'ttfb_z'));685 if (path === '/api/admin/raw') return json(res, 200, rawTable(q.get('table') ?? 'measurements', Number(q.get('limit') ?? 200)));686 if (path === '/api/admin/incidents') { const st = q.get('status'); return json(res, 200, { incidents: allIncidents().filter((i) => !st || st === 'all' || (st === 'active' ? i.status !== 'resolved' : i.status === st)).map((i) => ({ ...i, review: incidentReview[i.event_id]?.review ?? 'unreviewed', note: incidentReview[i.event_id]?.note ?? null })) }); }687 m = path.match(/^\/api\/admin\/incidents\/([^/]+)$/);688 if (m && req.method === 'PATCH') { incidentReview[m[1]] = { review: body.review ?? 'unreviewed', note: body.note ?? null }; return json(res, 200, { event_id: m[1], ...incidentReview[m[1]] }); }689 if (path === '/api/admin/annotations') { if (req.method === 'POST') { const a = { id: `ann_${adminAnnotations.length + 1}`, author: 'admin', ...body }; adminAnnotations.unshift(a); return json(res, 201, a); } return json(res, 200, { annotations: adminAnnotations }); }690 if (path === '/api/admin/replay' && req.method === 'POST') { const from = new Date(body.from ?? now() - 86400_000).getTime(); const to = new Date(body.to ?? now()).getTime(); const step = Math.max(60, Math.round((to - from) / 240 / 60_000) * 60); const w = body.weights ?? WEIGHTS; const factor = (w.routing ?? 0.25) / 0.25 * 0.6 + (w.latency ?? 0.2) / 0.2 * 0.4; const points = []; for (let t = from; t <= to; t += step * 1000) { const o = pressureAt(t); points.push({ ts: iso(t), pressure_original: o, pressure_replayed: Number(clamp(o * factor).toFixed(1)) }); } return json(res, 200, { step_seconds: step, points }); }691 if (path === '/api/admin/boost' && req.method === 'POST') return json(res, 200, { ok: true, targets: body.targets ?? [], factor: body.factor ?? 0.5, seconds: body.seconds ?? 900, until: iso(now() + (body.seconds ?? 900) * 1000) });692 return notFound(res);693 }694695 // ---- public696 if (path === '/api/v1/status') return json(res, 200, { ok: true, ts: iso(now()), internal_status: internalStatus(), engine: { last_run: engineTs(), cycle_ms: 412, cycle_seconds: 10 }, ingest: { last_batch: minutesAgo(0), batches_5m: 312, measurements_5m: 41200 }, probes: { fresh: DEGRADED ? 1 : 8, total: 8, excluded: [] }, bgp: { fresh: !DEGRADED, last_message: minutesAgo(DEGRADED ? 14 : 0), collectors: 12 }, stores: { clickhouse: true, postgres: true, redis: true }, version: '0.1.0' });697 if (path === '/api/v1/pressure/global') return json(res, 200, globalPressure());698 if (path === '/api/v1/pressure/history') { const st = q.get('scope_type') ?? 'global'; const range = q.get('range') ?? '24h'; if (!STEP[range]) return json(res, 422, { error: 'validation', detail: 'bad range' }); return json(res, 200, history(st, q.get('scope_id'), range), RANGE_S[range] >= 86400 ? { 'Cache-Control': 'public, max-age=30' } : {}); }699 if (path === '/api/v1/pressure/regions') return json(res, 200, { ts: engineTs(), regions: regionsList() });700 let m = path.match(/^\/api\/v1\/pressure\/region\/([^/]+)$/);701 if (m) return REGION_PRESSURE[m[1]] === undefined ? notFound(res) : json(res, 200, regionDetail(m[1]));702 if (path === '/api/v1/pressure/countries') return json(res, 200, { ts: engineTs(), countries: countriesList() });703 m = path.match(/^\/api\/v1\/pressure\/country\/([^/]+)$/);704 if (m) { const cc = m[1].toUpperCase(); return COUNTRY_PRESSURE[cc] === undefined ? notFound(res) : json(res, 200, countryDetail(cc)); }705 if (path === '/api/v1/asns') return json(res, 200, { ts: engineTs(), asns: ASNS.map((a) => ({ asn: a.asn, name: a.name.replace(/,? (Inc\.|LLC|S\.a\.s\.|SAS|B\.V\.|AG|Ltee)$/i, ''), country: a.country, pressure: a.pressure, level: levelOf(a.pressure).id, routing: Number(clamp(a.pressure * 0.7 * (a.asn === 6453 ? 4.9 : 1.1)).toFixed(1)), latency: Number(clamp(a.pressure * 1.2).toFixed(1)), availability: Number(clamp(a.pressure * 0.5).toFixed(1)), targets: TARGETS.filter((t) => t.asn === a.asn).length, prefixes_observed: a.prefixes_observed, importance: a.importance })) });706 m = path.match(/^\/api\/v1\/pressure\/asn\/(\d+)$/);707 if (m) { const a = asnById[Number(m[1])]; return a ? json(res, 200, asnDetail(a)) : notFound(res); }708 if (path === '/api/v1/services') return json(res, 200, { services: SERVICES.map(serviceObj) });709 m = path.match(/^\/api\/v1\/service\/([^/]+)$/);710 if (m) { const s = SERVICES.find((x) => x[0] === m[1]); return s ? json(res, 200, serviceDetail(s)) : notFound(res); }711 if (path === '/api/v1/targets') return json(res, 200, { targets: TARGETS.map(({ asn, ...t }) => t) });712 m = path.match(/^\/api\/v1\/target\/([^/]+)$/);713 if (m) { const t = targetById[decodeURIComponent(m[1])]; return t ? json(res, 200, targetDetail(t)) : notFound(res); }714 if (path === '/api/v1/probes') return json(res, 200, { probes: probeList() });715 if (path === '/api/v1/incidents') { const st = q.get('status') ?? 'active'; const limit = Number(q.get('limit') ?? 50); const offset = Number(q.get('offset') ?? 0); const list = st === 'all' ? allIncidents() : st === 'resolved' ? RESOLVED : activeIncidents(); return json(res, 200, { total: list.length, incidents: list.slice(offset, offset + limit) }); }716 m = path.match(/^\/api\/v1\/incident\/([^/]+)$/);717 if (m) { const inc = allIncidents().find((i) => i.slug === m[1]); return inc ? json(res, 200, incidentDetail(inc)) : notFound(res); }718 if (path === '/api/v1/fronts') return json(res, 200, { ts: engineTs(), fronts: fronts() });719 if (path === '/api/v1/bgp/stats') return json(res, 200, bgpStats());720 if (path === '/api/v1/latency') return json(res, 200, latency());721 if (path === '/api/v1/ticker') return json(res, 200, ticker());722 if (path === '/api/v1/routes/pairs') return json(res, 200, { pairs: PAIRS.map(([probe_id, target_id, changed_24h, stable]) => ({ probe_id, target_id, changed_24h, current_route_hash: hash(`${probe_id}|${target_id}|${changed_24h ? 'cur' : 'base'}`), stable })) });723 if (path === '/api/v1/routes') { const p = q.get('probe'); const t = q.get('target'); if (!p || !t) return json(res, 422, { error: 'validation', detail: 'probe and target required' }); if (!PROBES.some((x) => x.probe_id === p) || !targetById[t]) return notFound(res); return json(res, 200, routes(p, t)); }724 if (path === '/api/v1/history/summary') { const y = q.get('year') ? Number(q.get('year')) : null; const mo = q.get('month') ? Number(q.get('month')) : null; return json(res, 200, historySummary(y, mo), { 'Cache-Control': 'public, max-age=30' }); }725 if (path === '/api/v1/explain') return json(res, 200, explain());726 if (path === '/api/v1/methodology') return json(res, 200, METHODOLOGY);727 if (path === '/api/v1/search') return json(res, 200, { results: search(q.get('q') ?? '') });728 if (path === '/health') return json(res, 200, { ok: true });729 return notFound(res);730});731732server.listen(PORT, '127.0.0.1', () => {733 console.log(`[mock] InternetPressure API fixtures on http://127.0.0.1:${PORT} (${TARGETS_TOTAL} targets, ${PROBES.length} probes, ${REGION_DEFS.length} regions${DEGRADED ? ', DEGRADED mode' : ''})`);734 console.log(`[mock] admin token: ${ADMIN_TOKEN}`);735});736