9 Commits

Author SHA1 Message Date
Elie Habib
6148d4ca75 fix(csp): allow Dodo payment frames + Google Pay permission (#2789)
- frame-src: added *.hs.dodopayments.com, *.custom.hs.dodopayments.com,
  pay.google.com (Dodo payment iframe and Google Pay)
- Permissions-Policy: payment now allowed for checkout.dodopayments.com
  and pay.google.com (was denied entirely)
2026-04-07 20:26:50 +04:00
Elie Habib
429b1d99dd Revert "feat: seed orchestrator with auto-seeding, persistence, and managemen…" (#2060)
This reverts commit bb79386d24.
2026-03-22 19:59:42 +04:00
Jon Torrez
bb79386d24 feat: seed orchestrator with auto-seeding, persistence, and management CLI (#1940)
* feat(docker): enable Redis RDB persistence, add seed-orchestrator to supervisord, copy scripts into image

* feat(orchestrator): add prefixed logger utility

* feat(orchestrator): add seed-meta read/write helpers

* feat(orchestrator): add child process runner with timeout support

* feat(orchestrator): add central seed catalog with 42 seeders

* feat(orchestrator): implement seed orchestrator with tiered scheduling

Adds scripts/seed-orchestrator.mjs with:
- classifySeeders: classify seeders into active/skipped by env vars
- buildStartupSummary: human-readable startup report
- Tiered cold start (hot/warm/cold/frozen with per-tier concurrency)
- Freshness check via seed-meta keys before running stale seeders
- Steady-state scheduling with setTimeout-based recurring timers
- Overlap protection, retry-after-60s, consecutive failure demotion
- Global concurrency cap of 5 with queue-based overflow
- Graceful shutdown on SIGTERM/SIGINT (15s drain timeout)
- Meta writing for null-metaKey seeders to seed-meta:orchestrator:{name}

* fix(seeds): use local API for warm-ping seeders in Docker mode

* fix(orchestrator): allow ACLED email+password as alternative to access token

* feat(wmsm): add seed manager CLI scaffold with help, catalog, and checks

* feat(wmsm): implement status command with freshness display

* feat(wmsm): implement schedule command with next-run estimates

* feat(wmsm): implement refresh command with single and --all modes

* feat(wmsm): implement flush and logs commands

* fix(wmsm): auto-detect docker vs podman runtime

* feat(orchestrator): extract pure scheduling functions and add test harness

* feat(orchestrator): add SEED_TURBO=real|dry mode with compressed intervals

* feat(orchestrator): add SEED_TURBO env passthrough and fix retry log message
2026-03-22 19:51:03 +04:00
Jon Torrez
f4183f99c7 feat: self-hosted Docker stack (#1521)
* feat: self-hosted Docker stack with nginx, Redis REST proxy, and seeders

Multi-stage Docker build: esbuild TS handler compilation, vite frontend
build, nginx + Node.js API under supervisord. Upstash-compatible Redis
REST proxy with command allowlist for security. AIS relay WebSocket
sidecar. Seeder wrapper script with auto-sourced env vars from
docker-compose.override.yml. Self-hosting guide with architecture
diagram, API key setup, and troubleshooting.

Security: Redis proxy command allowlist (blocks FLUSHALL/CONFIG/EVAL),
nginx security headers (X-Content-Type-Options, X-Frame-Options,
Referrer-Policy), non-root container user.

* feat(docker): add Docker secrets support for API keys

Entrypoint reads /run/secrets/* files and exports as env vars at
startup. Secrets take priority over environment block values and
stay out of docker inspect / process metadata.

Both methods (env vars and secrets) work simultaneously.

* fix(docker): point supervisord at templated nginx config

The entrypoint runs envsubst on nginx.conf.template and writes
the result to /tmp/nginx.conf (with LOCAL_API_PORT substituted
and listening on port 8080 for non-root). But supervisord was
still launching nginx with /etc/nginx/nginx.conf — the default
Alpine config that listens on port 80, which fails with
"Permission denied" under the non-root appuser.

* fix(docker): remove KEYS from Redis allowlist, fix nginx header inheritance, add LLM vars to seeders

- Remove KEYS from redis-rest-proxy allowlist (O(N) blocking, Redis DoS risk)
- Move security headers into each nginx location block to prevent add_header
  inheritance suppression
- Add LLM_API_URL / LLM_API_KEY / LLM_MODEL to run-seeders.sh grep filter
  so LLM API keys set in docker-compose.override.yml are forwarded to seed scripts

* fix(docker): add path-based POST to Redis proxy, expand allowlist, add missing seeder secrets

- Add POST /{command}/{args...} handler to redis-rest-proxy so Upstash-style
  path POSTs work (setCachedJson uses POST /set/<key>/<value>/EX/<ttl>)
- Expand allowlist: HLEN, LTRIM (seed-military-bases, seed-forecasts),
  ZREVRANGE (premium-stock-store), ZRANDMEMBER (seed-military-bases)
- Add ACLED_EMAIL, ACLED_PASSWORD, OPENROUTER_API_KEY, OLLAMA_API_URL,
  OLLAMA_MODEL to run-seeders.sh so override keys reach host-run seeders

---------

Co-authored-by: Elie Habib <elie.habib@gmail.com>
2026-03-19 12:07:20 +04:00
msantosn-mt
c281103eb5 Upgrade Node.js version in Dockerfile (#1678)
* Upgrade Node.js version in Dockerfile

* Updated Node.js version in Dockerfile from 20-alpine to 25-alpine.
* Copy of the sources has to happen before the build.

* fix(docker): use node:22-alpine to match .nvmrc LTS version

---------

Co-authored-by: Elie Habib <elie.habib@gmail.com>
2026-03-19 10:07:40 +04:00
Jon Torrez
987ed03f5d feat(webcams): add webcam map layer with Windy API integration (#1540) (#1540)
- Webcam markers on flat, globe, and DeckGL maps with category-based icons
- Server-side spatial queries via Redis GEOSEARCH with quantized bbox caching
- Pinned webcams panel with localStorage persistence
- Seed script for Windy API with regional bounding boxes and adaptive splitting
- Input validation (webcamId regex + encodeURIComponent) and NaN projection guards
- Bandwidth optimizations: zoom threshold, bbox overlap check, 1s cooldown
- Client-side image cache with 200-entry FIFO eviction
- Globe altitude-based viewport estimation for webcam loading
- CSP updates for webcam iframe sources
- Seed-meta key for health.js freshness tracking
2026-03-14 09:34:54 +04:00
Nicolas Dos Santos
6b2550ff49 fix(csp): allow cross-subdomain framing for Pro page variant switcher (#1332)
* fix(csp): allow cross-subdomain framing and add finance to frame-src

frame-ancestors 'self' blocked tech/finance variants from rendering
inside the Pro landing page iframe. Widen to *.worldmonitor.app.
Also adds missing finance.worldmonitor.app to frame-src.

Closes #1322

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(csp): remove conflicting X-Frame-Options and tighten frame-ancestors

X-Frame-Options: SAMEORIGIN contradicts the new frame-ancestors directive
that allows cross-subdomain framing. Modern browsers prioritize
frame-ancestors over X-Frame-Options, but sending both is contradictory
and gets flagged by security scanners. Remove X-Frame-Options entirely.

Also replace wildcard *.worldmonitor.app with explicit subdomain list
to limit the framing scope to known variants only.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Elie Habib <elie.habib@gmail.com>
2026-03-09 14:26:02 +04:00
Elie Habib
0d5f6a2386 fix(railway): move .dockerignore to docker/ to unblock Nixpacks builds (#1336)
.dockerignore at repo root excludes scripts/, docs/, and e2e/ from the
build context. Nixpacks (and/or Railway's build system) respects this
file, causing all seed cron services to crash with "Cannot find module
'/app/scripts/...'" at runtime.

Moving .dockerignore into docker/ (alongside the Dockerfile) means:
- Railway Nixpacks builds get the full repo (scripts/ included)
- GHA Docker builds use context: . with file: docker/Dockerfile,
  and Docker only reads .dockerignore from the build context root,
  so docker/ placement is harmless for GHA
2026-03-09 13:24:15 +04:00
Elie Habib
0787528584 fix(docker): move Dockerfile to docker/ to prevent Railway auto-detection (#1334)
Railway auto-detects Dockerfiles at repo root and uses them for ALL
services, even those set to NIXPACKS. This caused all seed services
(ais-relay, seed-gpsjam, etc.) to build nginx-only containers with
no node binary, breaking every Railway service.

Move Dockerfile and related files to docker/ subdirectory. Railway
only checks the repo root for Dockerfiles, so this prevents
accidental detection. GHA workflow updated with explicit file: path.
2026-03-09 12:43:57 +04:00