Commit Graph

168 Commits

Author SHA1 Message Date
Elie Habib
116fc80fc7 Merge remote-tracking branch 'origin/main' into feature/finance-variant
# Conflicts:
#	index.html
#	src/components/DeckGLMap.ts
2026-02-17 09:37:47 +04:00
Elie Habib
ed9cc922e2 Fix finance variant runtime resiliency and API pressure 2026-02-17 09:34:15 +04:00
Elie Habib
ef2b67ad22 fix(finance): address PR review blocking issues
- Add missing RSS proxy domains (seekingalpha, coindesk, cointelegraph)
- Fix operator precedence in finance marker zoom checks (explicit parens)
- Add Number.isFinite() NaN guards on all finance marker projections
- Include finance variant in aggregated test:e2e script
2026-02-17 08:38:25 +04:00
Elie Habib
631a5e2112 chore(ai): switch OpenRouter model to auto-routed free tier 2026-02-17 00:15:11 +04:00
Elie Habib
b59235fc45 CORS fixes for Tauri desktop app 2026-02-16 23:14:08 +04:00
Elie Habib
cccfdac0f9 feat(update): add desktop update check with architecture-aware download links 2026-02-16 23:13:10 +04:00
Elias El Khoury
32fd309e5d fix: remove overly broad CORS origin regex
The pattern /worldmonitor.*\.vercel\.app/ matched any Vercel deployment
with a "worldmonitor" prefix, allowing unauthorized origins to bypass
CORS and consume server-side API keys. The owner-scoped pattern on the
previous line already covers all legitimate preview deployments.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 10:58:53 +02:00
Elie Habib
cf62e169e9 chore: add PR #71 think tank domains to RSS proxy allowlist
warontherocks.com, www.aei.org, responsiblestatecraft.org,
www.fpri.org, jamestown.org
2026-02-15 23:42:06 +04:00
Elie Habib
f3fddcb0e8 fix: settings UX — save verified keys, preserve inputs across renders, bump v2.3.2
- Save keys that pass verification even when others fail (was all-or-nothing)
- Capture un-blurred input values before render to prevent loss on checkbox toggle
- Fix missing isDisallowedOrigin import in PIZZINT endpoints
2026-02-15 23:33:19 +04:00
Elie Habib
f64af4c571 fix: harden CORS patterns & URL validation
- Allow hyphens in Vercel preview URL patterns (worldmonitor-xxx-yyy)
- Harden open_url command with proper URL parsing via reqwest::Url
- Update YouTube embed test assertions for quote style change
2026-02-15 21:34:00 +04:00
Elie Habib
a9224254a5 fix: security hardening — CORS, auth bypass, origin validation & bump v2.2.7
- Tighten CORS regex to block worldmonitorEVIL.vercel.app spoofing
- Move sidecar /api/local-env-update behind token auth + add key allowlist
- Add postMessage origin/source validation in LiveNewsPanel
- Replace postMessage wildcard '*' targetOrigin with specific origin
- Add isDisallowedOrigin() check to 25 API endpoints missing it
- Migrate gdelt-geo & EIA from custom CORS to shared _cors.js
- Add CORS to firms-fires, stock-index, youtube/live endpoints
- Tighten youtube/embed.js ALLOWED_ORIGINS regex
- Remove 'unsafe-inline' from CSP script-src
- Add iframe sandbox attribute to YouTube embed
- Validate meta-tags URL query params with regex allowlist
2026-02-15 20:33:20 +04:00
Elie Habib
ac935d505e fix: migrate all Vercel edge functions to CORS allowlist & bump v2.2.5
Replace Access-Control-Allow-Origin: * with shared getCorsHeaders()
across 20 API edge functions to restrict access to worldmonitor.app,
tech.worldmonitor.app, and authorized Vercel preview URLs.

Version bump to 2.2.5 across package.json, tauri.conf.json, Cargo.toml.
2026-02-15 19:13:54 +04:00
Elie Habib
af6f321493 feat: dramatically increase cyber threat map density
Increase geo cap 100→250, concurrency 8→16, per-IP timeout 8→3s.
Add country centroid fallback with jitter for IPs with country codes.
2026-02-15 17:40:01 +04:00
Elie Habib
4d816c22f8 fix: cap geo enrichment at 12s overall timeout & prevent duplicate download banners
Addresses PR #68 review comments:
- P1: hydrateThreatCoordinates now races workers against a 12s overall
  timeout so slow GeoIP providers can't block the entire request
- P2: DownloadBanner adds module-level guard preventing duplicate panels
2026-02-15 17:25:38 +04:00
Elie Habib
f2b650fc81 fix: replace ipwho.is/ipapi.co with ipinfo.io/freeipapi.com for geo enrichment
ipwho.is returns 403 from Node.js/Edge ("CORS not supported on Free plan")
and ipapi.co rate-limits aggressively (429). Both providers only work from
browser-side requests.

Switch to ipinfo.io (HTTPS, 50K/mo free, works from Edge runtime) as primary
with freeipapi.com as fallback.

Validated end-to-end: 20 C2 IPs geo-enriched in <1s with real coordinates.
2026-02-15 17:17:03 +04:00
Elie Habib
6e0dbbd15b feat: add C2IntelFeeds, OTX, and AbuseIPDB as cyber threat sources
Expands from 2 to 5 threat intel sources:
- C2IntelFeeds (free, no auth): ~500 active C2 server IPs (CobaltStrike, Metasploit)
- AlienVault OTX (optional API key): community-sourced IOCs with tags
- AbuseIPDB (optional API key): high-confidence abuse reports with geo
- Feodo: now includes recently-offline entries (still threat-relevant)

All sources fetched in parallel. Graceful degradation when API keys missing.
2026-02-15 17:06:14 +04:00
Elie Habib
5facae7105 feat: add cyber threat map layer with Feodo Tracker + URLhaus integration
Plot live botnet C2 servers, malware distribution nodes, and malicious IPs
on the globe using free abuse.ch APIs (Feodo Tracker + URLhaus).

- Vercel edge API with triple-layer caching (Redis → memory → stale fallback)
- IP geolocation via ipwho.is + ipapi.co (HTTPS-compatible with Edge runtime)
- Severity-based color coding (critical=red, high=orange, medium=amber, low=yellow)
- Feature-gated behind VITE_ENABLE_CYBER_LAYER=true env var
- Frontend circuit breaker, data sanitization, 10min auto-refresh
- Tauri desktop support: 3 new secret keys (URLHAUS, OTX, AbuseIPDB)
- Full test suite (6 unit tests), e2e harness updates, popup + tooltip rendering
2026-02-15 16:52:24 +04:00
Elie Habib
458be05a59 feat: add full-page Country Brief Page replacing modal overlay
Replace the small CountryIntelModal with a comprehensive full-page
intelligence product per country. Implements all 5 phases of the plan:

Phase 1 - Full-page shell + bug fixes:
- CountryBriefPage.ts: score ring, component bars, signal chips,
  non-tier fallback, loading states
- Fix hardcoded earthquakes: 0 with bbox + place name filtering
- Export getCountryData, TIER1_COUNTRIES from country-instability
- Expand CountryBriefSignals with displacement, climate, conflict

Phase 2 - D3 multi-lane timeline:
- CountryTimeline.ts: 4 lanes, 7-day filter, severity-sized circles
- XSS-safe tooltip rendering via escapeHtml

Phase 3 - Infrastructure + Evidence:
- Export getNearbyInfrastructure from related-assets
- Local BriefAssetType union, port proximity lookup
- Evidence cards with threat levels and numbered references

Phase 4 - AI brief citations + Export:
- LLM prompt cites headlines as [N], bounded regex parsing
- Export dropdown: Image PNG, JSON, CSV, Print/PDF

Phase 5 - Deep-linking + Polish:
- country field in URL state, pre-capture before sync
- Force URL rewrite on open/close, mobile + print styles

Bug fixes: URL sync race, async response guards,
briefRequestToken cancellation, listener accumulation,
tier-1 detection via membership not data existence
2026-02-15 11:06:09 +04:00
Elie Habib
d2568576a3 Add download redirect API for platform-specific installers
Edge function that redirects /api/download?platform=macos-arm64 to
the matching asset from the latest GitHub release. Falls back to
the releases page when no match is found.
2026-02-15 10:28:52 +04:00
Elie Habib
fd631ca86c perf: harden regression guardrails in CI, cache, and map clustering 2026-02-15 08:45:49 +04:00
Elie Habib
9b216843be Fix YouTube playback in Tauri desktop with Player API and postMessage controls
Switch bridge page from raw iframe to YouTube IFrame Player API with
postMessage protocol for play/pause/mute commands. Use youtube-nocookie.com
host, add click-to-play overlay for WKWebView autoplay restrictions, and
route desktop embeds through cloud URL to avoid sidecar auth issues.
2026-02-14 20:22:37 +04:00
Elie Habib
c353cf2070 Reduce egress costs, add PWA support, fix Polymarket and Railway relay
Egress optimization:
- Add s-maxage + stale-while-revalidate to all API endpoints for Vercel CDN caching
- Add vercel.json with immutable caching for hashed assets
- Add gzip compression to sidecar responses >1KB
- Add gzip to Railway RSS responses (4 paths previously uncompressed)
- Increase polling intervals: markets/crypto 60s→120s, ETF/macro/stablecoins 60s→180s
- Remove hardcoded Railway URL from theater-posture.js (now env-var only)

PWA / Service Worker:
- Add vite-plugin-pwa with autoUpdate strategy
- Cache map tiles (CacheFirst), fonts (StaleWhileRevalidate), static assets
- NetworkOnly for all /api/* routes (real-time data must be fresh)
- Manual SW registration (web only, skip Tauri)
- Add offline fallback page
- Replace manual manifest with plugin-generated manifest

Polymarket fix:
- Route dev proxy through production Vercel (bypasses JA3 blocking)
- Add 4th fallback tier: production URL as absolute fallback

Desktop/Sidecar:
- Dual-backend cache (_upstash-cache.js): Redis cloud + in-memory+file desktop
- Settings window OK/Cancel redesign
- Runtime config and secret injection improvements
2026-02-14 19:53:04 +04:00
Admin
e0e1b40e1a feat: add think tank, arms control, and food security RSS feeds
- Add RUSI, Wilson Center, GMF, Stimson, CNAS, Lowy Institute feeds
- Add Arms Control Association, Bulletin of Atomic Scientists feeds
- Add FAO GIEWS food security alerts, EU ISS feeds
- Add www.iss.europa.eu to RSS proxy allowlist
- Add SOURCE_TIERS and SOURCE_TYPES entries for new feeds
2026-02-13 15:06:33 -08:00
Elie Habib
75a85ebafc Fix desktop app reliability: YouTube embeds, panel failures, circuit breakers
- Fix YouTube Error 153 by serving embed bridge from cloud URL (origin match)
- Fix channel switching when playerContainer detached from DOM
- Fix Fires panel infinite spinner when API returns 0 or fails
- Make TECH variant button open web URL instead of being disabled
- Fix circuit breaker caching empty results as success in 6 services
  (polymarket, wingbits, military-flights, outages, conflicts, protests)
- Improve sidecar: cloud-preferred routing, failed import caching, log dedup
- Add FINNHUB_API_KEY and NASA_FIRMS_API_KEY to Tauri secret keys
- Add early 503 for missing ACLED token in risk-scores
2026-02-14 00:25:02 +04:00
Elie Habib
ad4e52caee Fix Tauri desktop runtime reliability and settings UX 2026-02-13 23:05:51 +04:00
Elie Habib
871af119a3 Batch AI classification and Railway-direct AIS routing
- Add /api/classify-batch endpoint: classifies up to 20 headlines per Groq call
  (reduces 182 individual API calls to ~10 batched calls, 90% rate limit savings)
- Update threat-classifier.ts: collect headlines in batch queue, flush every 500ms
  or when batch reaches 20 items
- Route AIS snapshot through Railway directly when VITE_WS_RELAY_URL is set,
  falling back to Vercel — eliminates 503 when WS_RELAY_URL not configured on Vercel
2026-02-13 20:38:20 +04:00
Elie Habib
0503f20943 Move UCDP proxy to Railway with persistent in-memory cache
- Add /ucdp-events handler to ais-relay.cjs with 6h TTL cache,
  background refresh, version discovery, and 30s per-page timeout
- Route client through Railway when VITE_WS_RELAY_URL is set
- Add 8s AbortController timeout to Vercel fallback fetchGedPage()
2026-02-13 18:29:30 +04:00
Elie Habib
19754716c6 feat: add intelligence layers and harden data ingestion 2026-02-13 08:14:53 +04:00
Elie Habib
c80136ffdb Add sparkline charts to Markets, Crypto, and Commodities panels
- Extract close price arrays from Yahoo Finance chart API for indices/commodities
- Switch CoinGecko crypto fetch to /coins/markets endpoint with 7d sparkline data
- Render inline SVG sparklines color-coded green/red by price direction
- Fix Vite dev proxy for CoinGecko (was hitting root instead of /api/v3/simple/price)
- Add endpoint=markets support to CoinGecko edge function
2026-02-12 00:20:44 +04:00
Elie Habib
14c67ff592 Optimize proxy usage with AIS snapshots, Upstash caching, and telemetry 2026-02-11 19:06:00 +04:00
Elie Habib
ee3a3f1c6b Add Market Radar, BTC ETF Tracker, and Stablecoins panels
Three new crypto/market intelligence panels with self-fetching data:

- Market Radar (macro-signals): 7 signals from Yahoo Finance, mempool.space,
  alternative.me — liquidity, flow structure, macro regime, BTC trend with
  30d VWAP, hash rate, mining cost, fear & greed. SVG sparklines and donut gauge.
- BTC ETF Tracker (etf-flows): 10 spot Bitcoin ETFs via Yahoo Finance 5-day
  chart with estimated net flows, volume, and price change per ETF.
- Stablecoins (stablecoin-markets): CoinGecko proxy for peg health monitoring
  (ON PEG / SLIGHT DEPEG / DEPEGGED) and supply/volume breakdown.

All endpoints include CORS origin guard, input validation, in-memory caching
with stale fallback. Panels registered in both full and tech variants.
2026-02-11 14:35:28 +04:00
Elie Habib
f7119b9ed6 Harden CORS, XSS, and input validation across all API endpoints and components
- Add CORS origin allowlist (api/_cors.js) replacing Access-Control-Allow-Origin: *
- Add isDisallowedOrigin guard to all API endpoints (acled, cloudflare-outages, finnhub, fred-data, hackernews, wingbits)
- Gut debug-env endpoint to return 404
- Tighten sanitizeUrl() with escapeAttr output and strict relative URL validation
- Add sanitizeUrl() adoption in CountryIntelModal, InsightsPanel, PredictionPanel, RegulationPanel, TechEventsPanel
- Comprehensive escapeHtml() hardening in MapPopup (cables, flights, vessels, clusters)
- Bound HackerNews concurrent fetches (MAX_CONCURRENCY=10), validate story type and limit params
- Add wingbits cache eviction (MAX_LOCAL_CACHE_ENTRIES=2000, sweep on TTL + LRU)
- Fix arxiv http→https, og-story parseInt safety with Number.isFinite + clamping
2026-02-11 14:35:07 +04:00
Elie Habib
45dc787224 Fix UCDP proxy: API returns snake_case fields, not PascalCase
UCDP API fields are conflict_id, location, side_a, intensity_level etc.
(snake_case) — proxy was reading ConflictId, Location, IntensityLevel
(PascalCase), causing all values to be empty/0.

Also paginate through all results instead of just first page.
2026-01-31 08:06:18 +04:00
Elie Habib
f7fd4ad24d Fix Chatham House 403 and FAO parse errors
- Chatham House RSS returns 403 from cloud IPs, use Google News fallback
- FAO FPMA feed returns HTML (Angular app), not RSS — replaced with fao.org/rss
- Updated rss-proxy allowlist domain
2026-01-31 08:00:13 +04:00
Elie Habib
8e6b627a66 Fix HAPI 500: correct endpoint URL, auth format, response parsing
- Endpoint was conflict-event (singular), fixed to conflict-events (plural)
- app_identifier must be base64("name:email"), passed as query param
- Response fields are (events, fatalities, event_type) per row, not
  pre-aggregated columns — fixed aggregation logic
- Remove Arab News and Times of Israel feeds (403 from cloud IPs)
2026-01-31 07:30:48 +04:00
Elie Habib
c6f1da95c5 Integrate ACLED conflicts, UCDP classification, and HDX HAPI for real conflict detection
Replace hardcoded conflict floor scores with real data from three sources:
- ACLED battles/explosions/violence against civilians (30-day events)
- UCDP conflict classification (war vs minor vs none, data-driven floors)
- HDX HAPI aggregated monthly conflict counts (fallback/validation)

New CII component 'conflict' weighted 30% of event score. Updated formula:
unrest(25%) + conflict(30%) + security(20%) + information(25%)
2026-01-30 23:26:53 +04:00
Elie Habib
f3b9cd8fa4 Fix FIRMS API key: accept NASA_FIRMS_API_KEY env var with fallback 2026-01-30 20:05:48 +04:00
Elie Habib
41c52af5ea Fix SVG arc paths: add missing M (moveto) command 2026-01-30 10:54:41 +04:00
Elie Habib
beac24c1f1 Redesign OG image as rich intelligence card
- Gradient background with left accent sidebar in level color
- Large 120px CII score with /100 + labeled score bar with tick marks
- Semicircle arc gauge on right with score + level badge
- Data indicator legend (threat, military, markets, convergence, signals)
- No-score fallback shows 4 feature cards with descriptions
- Bottom bar with W logo circle, brand text, and CTA button
- Subtle grid background, status pill, date stamp
2026-01-30 10:51:41 +04:00
Elie Habib
91dbfefd06 Improve story card clarity + fix OG image missing score data
- Story renderer: larger fonts, better contrast (#777 vs #555 headers,
  #e0e0e0 vs #ddd text), visible separators (#222 vs #1a1a2e), removed
  grid background noise, bigger score (72px), bigger headlines (26px)
- OG image: pass score & level params to og-story endpoint, improve
  contrast, larger score text (96px), better fallback when no score
- Meta tags: include s= and l= query params in og:image URL
2026-01-30 10:34:01 +04:00
Elie Habib
d981c3b180 feat: add OG image and story page edge functions for Twitter card previews
- /api/og-story: generates SVG OG image with country name, CII score, level
- /api/story: serves meta tags to social crawlers, redirects real users to SPA
- Deep links now point to /api/story for proper crawler support
- Pass CII score/level through URL params for dynamic OG images
2026-01-30 06:22:18 +00:00
Elie Habib
e34b1ca0a3 feat: satellite fires layer, temporal baseline, cleanup dead code, update README
- Add NASA FIRMS satellite fire detection map layer and panel
- Add temporal baseline anomaly detection (Welford's algorithm, Redis-backed)
- Wire signal aggregator with fires, temporal anomalies
- Remove 10 dead service files and unused markdown docs
- Deduplicate RSS feeds, clean up story templates
- Fix data freshness, status panel, and verification checklist
- Create og-image.png for social sharing meta tags
- Update README with signal aggregation, source tiering, edge architecture
- Bump version to 2.1.4
2026-01-30 06:07:40 +00:00
Elie Habib
8f4cba06e5 feat(worldmonitor): 10 initiatives - launch prep and enhancements
COMPLETED INITIATIVES:

1. **Critical RSS Feeds** - Added 20+ feeds (RUSI, Chatham House, CFR, FAO, etc.)
2. **CII Trends** - 7-day/30-day rolling baselines with trend detection
3. **Trending Stories** - Analytics panel with localStorage persistence
4. **Launch Copy** - Finalized Twitter, LinkedIn, Reddit, Product Hunt materials
5. **Product Hunt** - Submission ready with tagline, bullets, screenshots
6. **Reddit Posts** - Ready for r/cybersecurity, r/INTELLIGENCE, r/geopolitics
7. **OG Meta Tags** - Dynamic meta tags for story sharing + Twitter Cards
8. **Story Templates** - 6 templates (analysis, crisis, brief, markets, compare, trend)
9. **Deep Link Router** - /story?c=UA routing to open country stories
10. **Self-Review Logging** - DEVELOPMENT_LOG.md per @jumperz pattern

FILES ADDED:
- src/services/meta-tags.ts - Dynamic OG/Twitter meta tags
- src/services/story-templates.ts - Template configurations
- src/services/cii-trends.ts - CII trend tracking
- src/services/trending-stories.ts - Story analytics
- 10_INITIATIVES.md - Initiative tracker
- ENHANCEMENT_PLAN.md - Comprehensive plan
- DEVELOPMENT_LOG.md - Self-review log

FILES MODIFIED:
- src/config/feeds.ts - Added 20+ RSS feeds
- api/rss-proxy.js - Added domains to allowlist
- src/main.ts - Initialize meta tags
- src/App.ts - Deep link handling
- index.html - OG meta tags
- LAUNCH_MATERIALS.md - Final launch copy

READY FOR LAUNCH!
2026-01-29 20:58:17 +00:00
Elie Habib
c5b683212f Switch story rendering to client-side Canvas (WASM not allowed in Vercel Edge) 2026-01-29 23:49:48 +04:00
Elie Habib
5adefb1d76 Add World Stories: shareable vertical country intelligence snapshots via @vercel/og 2026-01-29 23:42:03 +04:00
Elie Habib
79368dc4e0 Add AI threat classification, map progressive disclosure, and bug fixes
- Hybrid keyword + Groq LLM classification with Redis cache (24h TTL)
- Progressive disclosure: bases/nuclear/datacenters hidden at low zoom
- Label deconfliction: BREAKING badges suppress overlaps by priority
- Zoom-adaptive opacity and marker sizing for reduced visual clutter
- Fix unbounded summary growth in alert merging (cap at 3 items)
- Fix Strategic Risk Panel showing "Insufficient Data" on startup
- Remove dead renderLimitedData code
- Expand README with algorithms, architecture, and new features
- Bump version to 2.1.2
2026-01-29 19:29:40 +04:00
Elie Habib
a0bc560daf Lower theater posture thresholds for open-source tracking reality, add localStorage caching
Thresholds were calibrated for classified-level data visibility (50+ aircraft for
Iran ELEVATED). Open-source trackers (OpenSky/Wingbits) see ~10-20% of actual
military flights. Lowered all theaters ~5-6x to match real detection rates.

Added localStorage persistence to cached-theater-posture so the Strategic Posture
panel shows last-known data instantly on page reload instead of starting empty.
2026-01-29 16:40:56 +04:00
Elie Habib
d40dc246ae Improve Polymarket: tag-based event queries, clickable links
Switch from volume-only market fetching to tag-based event queries
for better relevance. Variant-aware tags (geopolitical vs tech).
Deduplicates across tag queries, falls back to top-volume markets
only when needed. Add clickable links to Polymarket event pages.
2026-01-29 15:19:31 +04:00
Elie Habib
8b58af0452 Remove unreliable Kuwait symbol (only 1 data point on Yahoo) 2026-01-27 18:14:14 +04:00
Elie Habib
d804dc7c85 Fix Middle East stock indices: add UAE DFM, fix Kuwait, use 1mo range
- Add DFMGI.AE for UAE (DFM General Index)
- Use range=1mo instead of 5d to handle Sun-Thu trading weeks
- Take last ~5 trading days from monthly data for weekly % change
- Remove broken Qatar symbol (^QSI returns no data)
2026-01-27 17:23:47 +04:00