70 Commits

Author SHA1 Message Date
Elie Habib
278c69b5a3 perf: reduce Vercel data transfer costs with CDN optimization (#1057)
- Increase polling intervals (markets 8→12min, feeds 15→20min, crypto 8→12min)
- Increase background tab hiddenMultiplier from 10→30 (polls 3x less when hidden)
- Double CDN s-maxage TTLs across all cache tiers in gateway
- Add CDN-Cache-Control header for Cloudflare-specific longer edge caching
- Add ETag generation + 304 Not Modified support in gateway (zero-byte revalidation)
- Add CDN-Cache-Control to bootstrap endpoint
- Add explicit SPA rewrite rule in vercel.json for CF proxy compatibility
- Add Cache-Control headers for /map-styles/, /data/, /textures/ static paths
2026-03-05 14:37:29 +04:00
Elie Habib
6c4901f5da fix(aviation): move AviationStack fetching to Railway relay, reduce to 40 airports (#858)
AviationStack API calls cost ~$100/day because each cache miss triggered
114 individual API calls from Vercel Edge (where isolates don't share
in-flight dedup). This moves all AviationStack fetching to the Railway
relay (like market data, OREF, UCDP) and reduces to 40 top international
hubs (down from 114).

- Add AVIATIONSTACK_AIRPORTS constant (40 curated IATA codes)
- Add startAviationSeedLoop() to ais-relay.cjs (2h interval, 4h TTL)
- Make Vercel handler cache-read-only (getCachedJson + simulation fallback)
- Delete Vercel cron (warm-aviation-cache.ts) and remove from vercel.json
2026-03-03 03:56:38 +04:00
Elie Habib
37f07a6af2 fix(prod): CORS fallback, rate-limit bump, RSS proxy allowlist (#814)
- Add wildcard CORS headers in vercel.json for /api/* routes so Vercel
  infra 500s (which bypass edge function code) still include CORS headers
- Bump rate limit from 300 to 600 req/60s in both rate-limit files to
  accommodate dashboard init burst (~30-40 parallel requests)
- Add smartraveller.gov.au (bare + www) to Railway relay RSS allowlist
- Add redirect hostname validation in fetchWithRedirects to prevent SSRF
  via open redirects on allowed domains
2026-03-03 00:25:09 +04:00
Elie Habib
04c5205537 fix(csp): restore unsafe-inline in vercel.json for Vercel bot-challenge pages (#788)
Vercel Firewall injects an obfuscated bot-protection challenge script
into served pages. Our hash-based script-src in vercel.json blocked
this injected script, causing CSP violations and SyntaxError.

The fix uses a dual-policy approach:
- vercel.json header: 'unsafe-inline' (allows Vercel challenge scripts)
- index.html <meta> tag: strict hash-based (enforced on our pages)

When both CSP policies exist, browsers enforce both — our <meta> tag's
strict hashes still protect our actual pages.
2026-03-02 20:28:38 +04:00
Elie Habib
83cc35f1d6 fix(api): remove [domain] catch-all that intercepted all RPC routes (#753 regression) (#785)
Vercel routes dynamic [domain] segments BEFORE specific directory names,
so api/[domain]/v1/[rpc].ts was catching every request meant for
api/intelligence/v1/[rpc].ts, api/economic/v1/[rpc].ts, etc. and
returning 404. Delete the catch-all so requests reach the real handlers.

Also: add missing CSP script hash, add list-iran-events cache tier,
and update route-cache-tier test to read from server/gateway.ts.
2026-03-02 19:58:45 +04:00
Elie Habib
31793ede03 harden: replace CSP unsafe-inline with script hashes and add trust signals (#781)
Remove 'unsafe-inline' from script-src in both index.html and vercel.json,
replacing it with SHA-256 hashes of the two static inline theme-detection
scripts. Add security.txt, sitemap.xml, and Sitemap directive in robots.txt
to improve scanner reputation. Fix stale variant-metadata test that was
reading vite.config.ts instead of the extracted variant-meta.ts module.
2026-03-02 19:07:37 +04:00
Elie Habib
e10c088229 harden: expand Permissions-Policy and tighten CSP connect-src (#779)
Expand Permissions-Policy from 3 to 19 directives (16 fully disabled,
3 delegated to YouTube origins for embed compatibility). Remove
unencrypted ws: and dev-only http://localhost:5173 from production CSP
connect-src. Add 5 guardrail tests to prevent regressions.
2026-03-02 18:36:01 +04:00
Elie Habib
8b02ec599f feat(aviation): add Vercel cron to pre-warm AviationStack cache (#776)
16,710 AviationStack requests/day instead of expected ~1,368. Root
cause: when 2h Redis cache expires, multiple Vercel Edge instances
each independently fire 114 API calls (inflight coalescing is
process-local). Fix: cron job writes to Redis every 2h with 4h TTL,
so user requests always hit cache.

- New api/cron/warm-aviation-cache.ts (edge runtime, CRON_SECRET auth)
- Three independent sources: FAA, AviationStack (intl), NOTAM
- Unhealthy AviationStack responses skip cache write to preserve data
- vercel.json: crons array at "0 */2 * * *"
- Expected reduction: 16,710 → ~1,368 requests/day (92%)
2026-03-02 18:10:46 +04:00
Elie Habib
36e36d8b57 Cost/traffic hardening, runtime fallback controls, and PostHog removal (#638)
- Remove PostHog analytics runtime and configuration
- Add API rate limiting (api/_rate-limit.js)
- Harden traffic controls across edge functions
- Add runtime fallback controls and data-loader improvements
- Add military base data scripts (fetch-mirta-bases, fetch-osm-bases)
- Gitignore large raw data files
- Settings playground prototypes
2026-03-01 11:53:20 +04:00
Elie Habib
d191477481 fix(analytics): use greedy regex in PostHog ingest rewrites (#481)
Vercel's :path* wildcard doesn't match trailing slashes that
PostHog SDK appends (e.g. /ingest/s/?compression=...), causing 404s.
Switch to :path(.*) which matches all path segments including
trailing slashes. Ref: PostHog/posthog#17596
2026-02-27 23:12:44 +04:00
Elie Habib
c54907f272 fix: add security headers to Vercel deployment (#439)
Add X-Content-Type-Options, X-Frame-Options, Strict-Transport-Security,
Content-Security-Policy, Referrer-Policy, and Permissions-Policy headers
to all routes via vercel.json catch-all pattern.
2026-02-26 22:49:18 +04:00
Sebastien Melki
5d7e77f8b0 fix: shorten vercel.json ignoreCommand to fit 256-char limit
Invert the path logic from an allowlist of watched directories to an
exclusion list (*.md, .planning, docs, e2e, scripts, .github). This
brings the command from 318 to 242 characters while keeping the same
build-trigger behavior for all source code changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 13:25:57 +02:00
Elie Habib
b23cac04b9 Fix Vercel build failure when previous deploy SHA is missing (#225) 2026-02-22 09:52:21 +00:00
Elie Habib
584159f35c fix(analytics): proxy PostHog through own domain to bypass ad blockers
- Add /ingest/* rewrites in vercel.json → us.i.posthog.com
- Web uses /ingest proxy, desktop uses direct PostHog host
- Enable capture_pageview so every visitor registers
2026-02-21 23:53:20 +00:00
Elie Habib
9273facad1 docs: expand README with proto-first API, cable health, OG images, and production hardening
Add new sections for proto-first API contracts (17 service domains,
code generation pipeline, edge gateway), undersea cable health monitoring
(NGA warnings + AIS cable ship tracking), dynamic OG image generation,
chunk reload guard, and storage quota management. Update tech stack,
architecture principles, security model, and roadmap. Add server/ and
proto/ to Vercel ignoreCommand watched paths.
2026-02-20 23:58:53 +00:00
Elie Habib
d07f14fef4 fix: prevent Vercel build skip when previous SHA is empty
Guard ignoreCommand against unset VERCEL_GIT_PREVIOUS_SHA (first deploy,
force deploy) which caused git diff to fail → build canceled. Also add
data/ to watched paths.
2026-02-20 23:45:33 +00:00
Elie Habib
b714e7b13e fix: harden API routes, batch FRED requests, and sanitize tooltip HTML
- fred-data: batch mode (comma-separated series_id) reduces 7 edge
  function invocations to 1; cap at 15 series; propagate upstream
  502s instead of masking as empty 200; add X-Data-Status header
- ucdp-events: parallelize page fetches; track failed pages and use
  short cache TTL for partial results instead of caching at full 6h
- ucdp: add OPTIONS/method guard matching ucdp-events pattern
- middleware: exact-match social bot paths instead of startsWith
- vercel.json: use VERCEL_GIT_PREVIOUS_SHA for multi-commit diffs;
  add middleware.ts, settings.html, vercel.json to watch list
- Panel.ts: use safeHtml() allowlist sanitizer for tooltip content
- dom-utils: add safeHtml() with tag/attribute allowlist and
  javascript: URI blocking
2026-02-20 14:51:54 +04:00
Elie Habib
919e7c996e perf: reduce Vercel costs — extend API cache TTLs and skip non-code builds
- vercel.json: add ignoreCommand to skip builds when only docs/tests/CI change
- service-status: extend edge cache 60s→300s (46 service checks, slow-moving)
- cyber-threats: extend edge cache 5min→1hr (threat intel updates hourly)
- theater-posture: extend edge cache 60s→300s, stale fallback 30s→120s
- markets/crypto polling: 2min→4min (reduce edge requests by ~50%)
2026-02-20 13:25:35 +04:00
Elie Habib
a78a072079 fix(deploy): prevent stale chunk 404s after Vercel redeployment
- vercel.json: add no-cache headers for / and /index.html so CDN never serves stale HTML
- main.ts: add vite:preloadError listener to auto-reload once on chunk 404s
- vite.config.ts: remove HTML from SW precache, add NetworkFirst for navigation requests
2026-02-17 11:30:58 +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