| # Architecture |
|
|
| > **Capability counts** (map layers, services, protos, locales, CI workflows, freshness sources) are derived from code and CI-verified by `npm run docs:check` (`scripts/docs-stats.mjs`, source of truth `docs/generated/stats.json`). Do not hand-edit those numbers β change the code, run `npm run docs:stats`. |
| > |
| > **Ownership rule**: When deployment topology, API surface, desktop runtime, or bootstrap keys change, this document must be updated in the same PR. |
|
|
| > **Design philosophy**: For the "why" behind architectural decisions, intelligence tradecraft, and algorithmic choices, see [Design Philosophy](docs/architecture.mdx). |
|
|
| World Monitor is a real-time global intelligence dashboard built as a TypeScript single-page application. It aggregates data from dozens of external sources covering geopolitics, military activity, financial markets, cyber threats, climate events, maritime tracking, and aviation into a unified operational picture rendered through an interactive map and a grid of specialized panels. |
|
|
| --- |
|
|
| ## 1. System Overview |
|
|
| ``` |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ |
| β Browser / Desktop β |
| β ββββββββββββ ββββββββββββ ββββββββββββββ ββββββββββββββββ β |
| β β DeckGLMapβ β GlobeMap β β Panels β β Workers β β |
| β β(deck.gl) β β(globe.gl)β β(Panel base)β β(ML, analysis)β β |
| β ββββββ¬ββββββ ββββββ¬ββββββ βββββββ¬βββββββ ββββββββββββββββ β |
| β ββββββββββββββββ΄βββββββββββββββ β |
| β β fetch /api/* β |
| βββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββββ |
| β |
| ββββββββββββββββΌβββββββββββββββ |
| β β β |
| ββββββββΌβββββββ βββββββΌββββββ βββββββΌβββββββ |
| β Vercel β β Railway β β Tauri β |
| β Edge Funcs β β AIS Relay β β Sidecar β |
| β + Middlewareβ β + Seeds β β (Node.js) β |
| ββββββββ¬βββββββ βββββββ¬ββββββ βββββββ¬βββββββ |
| β β β |
| ββββββββββββββββΌβββββββββββββββ |
| β |
| ββββββββΌβββββββ |
| β Upstash β |
| β Redis β |
| ββββββββ¬βββββββ |
| β |
| βββββββββββββΌββββββββββββ |
| β β β |
| βββββββΌββββ βββββββΌββββ ββββββΌβββββ |
| β Finnhub β β Yahoo β β ACLED β |
| β OpenSky β β GDELT β β UCDP β |
| β CoinGeckβ β FRED β β FIRMS β |
| β ... β β ... β β ... β |
| βββββββββββ βββββββββββ βββββββββββ |
| 65+ upstream providers and APIs |
| ``` |
|
|
| **Source files**: `package.json`, `vercel.json` |
|
|
| --- |
|
|
| ## 2. Deployment Topology |
|
|
| | Service | Platform | Role | |
| |---------|----------|------| |
| | SPA + Edge Functions | Vercel | Static files, API endpoints, middleware (bot filtering, social OG) | |
| | CORS Preflight Worker | Cloudflare | Edge CORS for `api.worldmonitor.app` β short-circuits OPTIONS, stamps CORS headers on responses | |
| | AIS Relay | Railway | WebSocket proxy (AIS stream), seed loops (market, aviation, GPSJAM, risk scores, UCDP, positive events), RSS proxy, OREF polling | |
| | Consumer Prices | Railway | Containerized price scrapers (Playwright, per-country baskets) + Redis publisher for the consumer-prices dataset | |
| | Redis | Upstash | Cache layer with stampede protection, seed-meta freshness tracking, rate limiting | |
| | Convex | Convex Cloud | Billing/entitlements (Dodo), user state and API keys, broadcast/email, contact + waitlist forms, historical intelligence memory (vector search) | |
| | Documentation | Mintlify | Public docs, proxied through Vercel at `/docs` | |
| | Desktop App | Tauri 2.x | macOS (ARM64, x64), Windows (x64), Linux (x64, ARM64) with bundled Node.js sidecar | |
| | Container Image | GHCR | Multi-arch Docker image (nginx serving built SPA, proxies API to upstream) | |
|
|
| **Source files**: `vercel.json`, `docker/Dockerfile`, `scripts/ais-relay.cjs`, `consumer-prices-core/Dockerfile`, `workers/api-cors-preflight/wrangler.toml`, `convex/schema.ts`, `src-tauri/tauri.conf.json` |
|
|
| **Cloudflare zone config (dashboard-managed, NOT in this repo):** the apex `worldmonitor.app` β `www` 301 is a Cloudflare Dynamic Redirect rule ("apex to www (exclude agent-discoverable paths)") whose exemption list is load-bearing: `/.well-known/*`, `/robots.txt`, `/security.txt`, `/mcp`, `/mcp/*`, and `/oauth/*` are served on the apex, never redirected. Dropping the `/mcp*` exemptions breaks every apex-URL MCP client; dropping `/oauth/*` re-breaks OAuth dynamic client registration β a redirected POST becomes a GET and dies with 405 (issue #4938). When editing the rule, mind expression precedence: `and` binds tighter than `or`, so a new exemption must be added as its own `or` term **inside** the `not (β¦)` group (appending `and not β¦` after the last term is a silent no-op). `mcp-live-smoke.yml` probes the MCP/OAuth members of this list (`/mcp`, `/.well-known/oauth-authorization-server`, and the OAuth endpoints it declares) every 6 hours and fails on the redirect fingerprint; the `robots.txt` / `security.txt` exemptions are crawler-facing and have no automated probe. |
|
|
| --- |
|
|
| ## 3. Frontend Architecture |
|
|
| ### Entry and Initialization |
|
|
| `src/main.ts` initializes Sentry error tracking, Vercel analytics, dynamic meta tags, runtime fetch patches (desktop sidecar redirection), theme application, and creates the `App` instance. |
|
|
| `App.init()` runs in 8 phases: |
|
|
| 1. **Storage + i18n**: IndexedDB, language detection, locale loading |
| 2. **ML Worker**: ONNX model prep (embeddings, sentiment, summarization) |
| 3. **Sidecar**: Wait for desktop sidecar readiness (desktop only) |
| 4. **Bootstrap**: Two-tier concurrent hydration from `/api/bootstrap` (fast 3s + slow 5s timeouts) |
| 5. **Layout**: PanelLayoutManager renders map and panels |
| 6. **UI**: SignalModal, IntelligenceGapBadge, BreakingNewsBanner, correlation engine |
| 7. **Data**: Parallel `loadAllData()` + viewport-conditional `primeVisiblePanelData()` |
| 8. **Refresh**: Variant-specific polling intervals via `startSmartPollLoop()` |
|
|
| ### Component Model |
|
|
| All panels extend the `Panel` base class (107 classes across `src/components`). Panels render via `setContent(html)` (debounced 150ms) and use event delegation on a stable `this.content` element. Panels support resizable row/col spans persisted to localStorage. |
|
|
| ### Dual Map System |
|
|
| - **DeckGLMap**: WebGL rendering via deck.gl + maplibre-gl. Supports ScatterplotLayer, GeoJsonLayer, PathLayer, IconLayer, PolygonLayer, ArcLayer, HeatmapLayer, H3HexagonLayer. PMTiles protocol for self-hosted basemap tiles. Supercluster for marker clustering. |
| - **GlobeMap**: 3D interactive globe via globe.gl. Single merged `htmlElementsData` array with `_kind` discriminator. Earth texture, atmosphere shader, auto-rotate after idle. |
|
|
| Layer definitions live in `src/config/map-layer-definitions.ts`, each specifying renderer support (flat/globe), premium status, variant filtering, and i18n keys. |
|
|
| ### State Management |
|
|
| No external state library. `AppContext` is a central mutable object holding: map references, panel instances, panel/layer settings, all cached data (news, markets, predictions, clusters, intelligence caches), in-flight request tracking, and UI component references. URL state syncs bidirectionally via `src/utils/urlState.ts` (debounced 250ms). |
|
|
| ### Web Workers |
|
|
| - **analysis.worker.ts**: News clustering (Jaccard similarity), cross-domain correlation detection |
| - **ml.worker.ts**: ONNX inference via `@xenova/transformers` (MiniLM-L6 embeddings, sentiment, summarization, NER), in-worker vector store for headline memory |
| - **vector-db.ts**: IndexedDB-backed vector store for semantic search |
|
|
| ### Variant System |
|
|
| Detected by hostname (`tech.worldmonitor.app` β tech, `finance.worldmonitor.app` β finance, etc.) or localStorage on desktop. Controls: default panels, map layers, refresh intervals, theme, UI text. Variant change resets all settings to defaults. |
|
|
| **Source files**: `src/main.ts`, `src/App.ts`, `src/app/`, `src/components/Panel.ts`, `src/components/DeckGLMap.ts`, `src/components/GlobeMap.ts`, `src/config/variant.ts`, `src/workers/` |
|
|
| --- |
|
|
| ## 4. API Layer |
|
|
| ### Edge Functions |
|
|
| The `api/` directory holds two kinds of endpoints, both deployed as Vercel Edge Functions: |
|
|
| - **Domain intelligence gateways** β generated from proto contracts and backed by handlers under `server/worldmonitor/**`. The per-domain thin entry points (`api/<domain>/v<N>/[rpc].ts`) are produced via `createDomainGateway` (`server/gateway.ts`) and esbuild-bundled, so the *deployed* artifact is self-contained even though the source composes server-side modules. |
| - **Operational endpoints** β hand-written for concerns that don't fit the contract model: auth/session, checkout and customer portal, MCP, bootstrap/health, notifications, cache invalidation, and user workflows (e.g. `api/create-checkout.ts`, `api/customer-portal.ts`, `api/mcp.ts`, `api/user-prefs.ts`). |
|
|
| Edge functions are bundled per file: each deployed function may not pull in unrelated modules at runtime, a constraint enforced by `tests/edge-functions.test.mjs` and the pre-push esbuild bundle check. Hand-written endpoints that genuinely cannot be proto-defined are listed in `api/api-route-exceptions.json` and enforced by `npm run lint:api-contract`. |
|
|
| ### Shared Helpers |
|
|
| | File | Purpose | |
| |------|---------| |
| | `_cors.js` | Origin allowlist (worldmonitor.app, Vercel previews, tauri://localhost, localhost) | |
| | `_rate-limit.js` | Upstash sliding window rate limiting, IP extraction | |
| | `_api-key.js` | Origin-aware API key validation (desktop requires key, trusted browser exempt) | |
| | `_relay.js` | Factory for proxying requests to Railway relay service | |
|
|
| ### Gateway Factory |
|
|
| `server/gateway.ts` provides `createDomainGateway(routes)` for per-domain Edge Function bundles. Pipeline: |
|
|
| 1. Origin check (403 if disallowed) |
| 2. CORS headers |
| 3. OPTIONS preflight |
| 4. API key validation |
| 5. Rate limiting (endpoint-specific, then global fallback) |
| 6. Route matching (static Map lookup, then dynamic `{param}` scan) |
| 7. POST-to-GET compatibility (for stale clients) |
| 8. Handler execution with error boundary |
| 9. ETag generation (FNV-1a hash) + 304 Not Modified |
| 10. Cache header application |
|
|
| ### Cache Tiers |
|
|
| | Tier | s-maxage | Use case | |
| |------|----------|----------| |
| | fast | 300s | Live event streams, flight status | |
| | medium | 600s | Market quotes, stock analysis | |
| | slow | 1800s | ACLED events, cyber threats | |
| | static | 7200s | Humanitarian summaries, ETF flows | |
| | daily | 86400s | Critical minerals, static reference data | |
| | no-store | 0 | Vessel snapshots, aircraft tracking | |
|
|
| ### Domain Handlers |
|
|
| `server/worldmonitor/<domain>/v1/handler.ts` exports handler objects with per-RPC functions. Each RPC function uses `cachedFetchJson()` from `server/_shared/redis.ts` for cache-miss coalescing: concurrent requests for the same key share a single upstream fetch and Redis write. |
|
|
| **Source files**: `api/`, `server/gateway.ts`, `server/router.ts`, `server/_shared/redis.ts`, `server/worldmonitor/` |
|
|
| --- |
|
|
| ## 5. Proto/RPC Contract System |
|
|
| The project uses the **sebuf** framework built on Protocol Buffers: |
|
|
| ``` |
| proto/ definitions |
| β buf generate |
| src/generated/client/ (TypeScript RPC client stubs) |
| src/generated/server/ (TypeScript server message types) |
| docs/api/ (OpenAPI v3 specs) |
| ``` |
|
|
| Service definitions use `(sebuf.http.config)` annotations to map RPCs to HTTP verbs and paths. GET fields require `(sebuf.http.query)` annotation. `repeated string` fields need `parseStringArray()` in the handler. `int64` maps to `string` in TypeScript. |
|
|
| CI enforces generated code freshness via `.github/workflows/proto-check.yml`: runs `make generate` and fails if output differs from committed files. |
|
|
| **Source files**: `proto/`, `Makefile`, `src/generated/`, `.github/workflows/proto-check.yml` |
|
|
| --- |
|
|
| ## 6. Data Pipeline |
|
|
| ### Bootstrap Hydration |
|
|
| `/api/bootstrap` reads cached keys from Redis in a single batch call. The SPA fetches two tiers concurrently (fast + slow) with separate abort controllers and timeouts. Hydrated data is consumed on-demand by panels via `getHydratedData(key)`. |
|
|
| ### Seed Scripts |
|
|
| `scripts/seed-*.mjs` fetch upstream data, transform it, and write to Redis via `atomicPublish()` from `scripts/_seed-utils.mjs`. Atomic publish acquires a Redis lock (SET NX), validates data, writes the cache key, writes `seed-meta:<key>` with `{ fetchedAt, recordCount }`, and releases the lock. |
|
|
| ### AIS Relay Seed Loops |
|
|
| The Railway relay service (`scripts/ais-relay.cjs`) runs continuous seed loops: |
|
|
| - Market data (stocks, commodities, crypto, stablecoins, sectors, ETF flows, gulf quotes) |
| - Aviation (international delays) |
| - Positive events |
| - GPSJAM (GPS interference) |
| - Risk scores (CII) |
| - UCDP events |
|
|
| These are the primary seeders. Standalone `seed-*.mjs` scripts on Railway cron are secondary/backup. |
|
|
| ### Refresh Scheduling |
|
|
| `startSmartPollLoop()` supports: exponential backoff (max 4x), viewport-conditional refresh (only if panel is near viewport), tab-pause (suspend when hidden), and staggered flush on tab visibility (150ms delays). |
|
|
| ### Health Monitoring |
|
|
| `api/health.js` checks every bootstrap and standalone key. For each key it reads `seed-meta:<key>` and compares `fetchedAt` against `maxStaleMin`. Cascade groups handle fallback chains (e.g., theater-posture: live, stale, backup). Returns per-key status: OK, STALE, WARN, EMPTY. |
|
|
| **Source files**: `api/bootstrap.js`, `api/health.js`, `scripts/_seed-utils.mjs`, `scripts/seed-*.mjs`, `scripts/ais-relay.cjs`, `src/services/bootstrap.ts`, `src/app/refresh-scheduler.ts` |
|
|
| --- |
|
|
| ## 7. Desktop Architecture |
|
|
| ### Tauri Shell |
|
|
| Tauri 2.x (Rust) manages the app lifecycle, system tray, and IPC commands: |
|
|
| - **Secret management**: Read/write platform keyring (macOS Keychain, Windows Credential Manager, Linux keyring) |
| - **Sidecar control**: Spawn Node.js process, probe port, inject environment variables |
| - **Window management**: Three trusted windows (main, settings, live-channels) with Edit menu for macOS clipboard shortcuts |
|
|
| ### Node.js Sidecar |
|
|
| `src-tauri/sidecar/local-api-server.mjs` runs on a dynamic port. It dynamically loads Edge Function handler modules from `api/`, injects secrets from the keyring via environment variables, and monkey-patches `globalThis.fetch` to force IPv4 (Node.js tries IPv6 first, but many government APIs have broken IPv6). |
|
|
| ### Fetch Patching |
|
|
| `installRuntimeFetchPatch()` in `src/services/runtime.ts` replaces `window.fetch` on the desktop renderer. All `/api/*` requests route to the sidecar with `Authorization: Bearer <token>` (5-min TTL from Tauri IPC). If the sidecar fails, requests fall back to the cloud API. |
|
|
| **Source files**: `src-tauri/src/main.rs`, `src-tauri/sidecar/local-api-server.mjs`, `src/services/runtime.ts`, `src/services/tauri-bridge.ts` |
|
|
| --- |
|
|
| ## 8. Security Model |
|
|
| ### Trust Boundaries |
|
|
| ``` |
| Browser β Vercel Edge β Upstream APIs |
| Desktop β Sidecar β Cloud API / Upstream APIs |
| ``` |
|
|
| ### Content Security Policy |
|
|
| Three CSP sources that must stay in sync: |
|
|
| 1. `index.html` `<meta>` tag (development, Tauri fallback) |
| 2. `vercel.json` HTTP header (production, overrides meta) |
| 3. `src-tauri/tauri.conf.json` (desktop) |
|
|
| ### Authentication |
|
|
| API keys are required for non-browser origins. Trusted browser origins (production domains, Vercel preview deployments, localhost) are exempt. Premium RPC paths always require a key. |
|
|
| ### Bot Protection |
|
|
| `middleware.ts` filters automated traffic: blocks known crawler user-agents on API and asset paths, allows social preview bots (Twitter, Facebook, LinkedIn, Telegram, Discord) on story and OG endpoints. |
|
|
| ### Rate Limiting |
|
|
| Per-IP sliding window via Upstash with per-endpoint overrides for high-traffic paths. |
|
|
| ### Desktop Secret Storage |
|
|
| Secrets are stored in the platform keyring (never plaintext), injected into the sidecar via Tauri IPC, and scoped to an allowlist of environment variable keys. |
|
|
| **Source files**: `middleware.ts`, `vercel.json`, `index.html`, `src-tauri/tauri.conf.json`, `api/_api-key.js`, `server/_shared/rate-limit.ts` |
|
|
| --- |
|
|
| ## 9. Caching Architecture |
|
|
| ### Four-Layer Hierarchy |
|
|
| ``` |
| Bootstrap seed (Railway writes to Redis on schedule) |
| β miss |
| In-memory cache (per Vercel instance, short TTL) |
| β miss |
| Redis (Upstash, cross-instance, cachedFetchJson coalesces concurrent misses) |
| β miss |
| Upstream API fetch (result cached back to Redis + seed-meta written) |
| ``` |
|
|
| ### Cache Key Rules |
|
|
| Every RPC handler with shared cache MUST include request-varying parameters in the cache key. Failure to do so causes cross-request data leakage. |
|
|
| ### ETag / Conditional Requests |
|
|
| `server/gateway.ts` computes an FNV-1a hash of each response body and returns it as an `ETag`. Clients send `If-None-Match` and receive `304 Not Modified` when content is unchanged. |
|
|
| ### CDN Integration |
|
|
| `CDN-Cache-Control` headers give Cloudflare edge (when enabled) longer TTLs than `Cache-Control`, since CF can revalidate via ETag without full payload transfer. |
|
|
| ### Seed Metadata |
|
|
| Every cache write also writes `seed-meta:<key>` with `{ fetchedAt, recordCount }`. The health endpoint reads these to determine data freshness and raise staleness alerts. |
|
|
| **Source files**: `server/_shared/redis.ts`, `server/gateway.ts`, `api/health.js` |
|
|
| --- |
|
|
| ## 10. Testing |
|
|
| ### Unit and Integration |
|
|
| `node:test` runner. Test files in `tests/*.test.{mjs,mts}` cover: server handlers, cache keying, circuit breakers, edge function constraints, data validation, market quote dedup, health checks, panel config guardrails, and variant layer filtering. |
|
|
| ### Sidecar and API Tests |
|
|
| `api/*.test.mjs` and `src-tauri/sidecar/*.test.mjs` test CORS handling, YouTube embed proxying, and local API server behavior. |
|
|
| ### End-to-End |
|
|
| Playwright specs in `e2e/*.spec.ts` test theme toggling, circuit breaker persistence, keyword spike flows, mobile map interactions, runtime fetch patching, and visual regression via golden screenshot comparison per variant. |
|
|
| ### Edge Function Guardrails |
|
|
| `tests/edge-functions.test.mjs` validates that all non-helper `api/*.js` files are self-contained: no `node:` built-in imports, no cross-directory `../server/` or `../src/` imports. The pre-push hook also runs an esbuild bundle check on each endpoint. |
|
|
| ### Pre-Push Hook |
|
|
| Runs before every `git push`: |
|
|
| 1. TypeScript check (`tsc --noEmit` for src and API) |
| 2. CJS syntax validation |
| 3. Edge function esbuild bundle check |
| 4. Edge function import guardrail test |
| 5. Markdown lint |
| 6. MDX lint (Mintlify compatibility) |
| 7. Version sync check |
|
|
| **Source files**: `tests/`, `e2e/`, `playwright.config.ts`, `.husky/pre-push` |
|
|
| --- |
|
|
| ## 11. CI/CD |
|
|
| | Workflow | Trigger | Checks | |
| |----------|---------|--------| |
| | `typecheck.yml` | PR, push to main | `tsc --noEmit` for src and API tsconfigs | |
| | `lint-code.yml` | PR, push to main | Biome lint + sebuf API-contract enforcement | |
| | `lint.yml` | PR (markdown changes) | markdownlint-cli2 | |
| | `test.yml` | PR, push to main | Unit/integration suite, docs-stats guardrail, plus conditional digest-image and resilience-validation smoke gates | |
| | `proto-check.yml` | PR (proto changes) | Generated code matches committed output | |
| | `pro-bundle-freshness.yml` | PR (pro bundle changes) | Committed pro data bundle artifacts are fresh | |
| | `feed-validation.yml` | PR (feed changes), daily cron | RSS feed reachability and validation | |
| | `mcp-live-smoke.yml` | 6-hourly cron, push to main (smoke paths), manual | Anonymous strict-client walk of the production MCP surface on apex + www (capability walk, auth wall, OAuth endpoint routing β #4937/#4938 regression net) | |
| | `live-api-cache-auth.yml` | 6-hourly cron, push to main (sweep paths), manual | Production cache/auth posture sweep: fake auth stays no-store and is never a cached 200, anonymous public surfaces stay cacheable, MCP/OAuth surfaces stay protocol-valid (#4497 regression net; suite was inert until #5379 wired the gate on, and the step fails if it executes 0 assertions) | |
| | `china-decision-parity-live.yml` | 6-hourly cron, push to main (audit paths), manual (optional staging URL) | Live half of the China decision-signal parity audit: probes the deployed composition RPC and the public `chinaDecisionSignals` bootstrap projection for the six-domain contract and a canonical snapshot under one hour old (#5643 β the probe existed but nothing invoked it, and `--require-live` keeps a lost `--url` from passing vacuously) | |
| | `security-audit.yml` | PR, push to main, daily cron, manual | Production dependency audits for every tracked `package-lock.json` workspace, failing on unbaselined high/critical advisories | |
| | `seed-freshness-monitor.yml` | 15-minute cron, manual | Enforces production ingestion acceptance after a green scheduled main gate; fails on every actionable compact-health problem except explicitly on-demand sources without grading production before Railway deploys or runs | |
| | `analytics-collector-monitor.yml` | 15-minute cron, manual | Probes the self-hosted Umami collector directly (heartbeat, tracker script, ingest route) and fails when events are being dropped β Railway reported a green deployment through the 4-day #5565 blackout, so deployment status is not trusted here | |
| | `contributor-trust.yml` | PR | Gates untrusted first-time-contributor runs | |
| | `deploy-gate.yml` | After Test/Typecheck/Security Audit complete | Aggregates required smoke-gate statuses onto the head SHA for branch protection | |
| | `indexnow-submit.yml` | Successful Production deployment, manual | Submits deployment-relevant canonical URLs to IndexNow only after their host-specific ownership keys are directly reachable | |
| | `convex-deploy.yml` | Push to main, manual | Deploys Convex backend functions | |
| | `deploy-worker.yml` | Push to main (worker paths), manual | Deploys the `api-cors-preflight` Cloudflare Worker | |
| | `build-desktop.yml` | Release tag, push, manual | Multi-platform Tauri build, code signing (macOS), AppImage library stripping (Linux), smoke test | |
| | `docker-publish.yml` | Release, manual | Multi-arch image (amd64, arm64) pushed to GHCR | |
| | `publish-cli.yml` | `cli-v*` tag, manual | Tests and publishes the `worldmonitor` npm CLI (`cli/`) via OIDC trusted publishing (no token) with provenance | |
| | `publish-python.yml` | `py-v*` tag, manual | Tests and publishes the `worldmonitor-sdk` PyPI package (`sdk/python/`) via OIDC trusted publishing (no token) with attestations | |
| | `publish-ruby.yml` | `gem-v*` tag, manual | Tests and publishes the `worldmonitor` gem (`sdk/ruby/`) via RubyGems OIDC trusted publishing (no token) | |
| | `publish-go.yml` | `sdk/go/v*` tag, manual | Vets/tests the Go SDK module (`sdk/go/`) at the tag and warms proxy.golang.org so the version is go-gettable and indexed on pkg.go.dev | |
| | `test-linux-app.yml` | Manual | Linux AppImage build + headless smoke test with screenshot verification | |
|
|
| **Source files**: `.github/workflows/`, `.husky/pre-push`. The workflow list is CI-checked against `.github/workflows/*.yml` by `npm run docs:check` β a new workflow file must be added to this table. |
|
|
| --- |
|
|
| ## 12. Directory Reference |
|
|
| ``` |
| . |
| βββ api/ Vercel Edge Functions (self-contained JS) |
| β βββ _*.js Shared helpers (CORS, rate-limit, API key, relay, Sentry, session) |
| β βββ <domain>/ Domain endpoints (aviation/, climate/, conflict/, ...) |
| βββ blog-site/ Static blog (built into public/blog/) |
| βββ cli/ Official `worldmonitor` npm CLI (zero-dep ESM, MCP-first; published via cli-v* tag) |
| βββ consumer-prices-core/ Consumer-price collection service (Playwright scrapers, per-country baskets; Railway/Docker) |
| βββ convex/ Convex backend (billing/entitlements, user state, broadcast, forms, intel history) |
| βββ data/ Static data (telegram channels, OREF threat translations, gamma irradiators) |
| βββ deploy/ Deployment configs (nginx) |
| βββ docker/ Dockerfile + nginx config for Railway |
| βββ docs/ Mintlify documentation site |
| βββ e2e/ Playwright E2E specs |
| βββ pro-test/ Standalone Pro QA app (separate package) |
| βββ proto/ Protobuf service definitions (sebuf framework) |
| βββ public/ Static assets served as-is (favicons, textures, .well-known agent-skills/MCP, llms.txt) |
| βββ scripts/ Seed scripts, build helpers, relay service |
| βββ server/ Server-side code (bundled into Edge Functions) |
| β βββ _shared/ Redis, rate-limit, LLM, caching utilities |
| β βββ gateway.ts Domain gateway factory |
| β βββ router.ts Route matching |
| β βββ worldmonitor/ Domain handlers (mirrors proto structure) |
| βββ shared/ Cross-platform JSON configs (markets, RSS domains) |
| βββ src/ Browser SPA (TypeScript) |
| β βββ app/ App orchestration managers |
| β βββ bootstrap/ Startup/recovery (chunk reload, deferred Sentry, SW update) |
| β βββ components/ Panel subclasses + map components |
| β βββ config/ Variant, panel, layer, market configurations |
| β βββ data/ Static JSON datasets (conservation, renewable, happiness) |
| β βββ e2e/ Map test harnesses (consumed by Playwright specs) |
| β βββ embed/ Embeddable widget loader |
| β βββ generated/ Proto-generated client/server stubs (DO NOT EDIT) |
| β βββ locales/ i18n translation files |
| β βββ services/ Business logic organized by domain |
| β βββ shared/ Cross-cutting helpers (premium paths, registries, staleness) |
| β βββ shims/ Runtime shims (child-process for sidecar) |
| β βββ styles/ Global CSS (layers, themes, panel styles) |
| β βββ types/ TypeScript type definitions |
| β βββ utils/ Shared utilities (circuit-breaker, theme, URL state) |
| β βββ workers/ Web Workers (analysis, ML, vector DB) |
| βββ src-tauri/ Tauri desktop shell (Rust) |
| β βββ sidecar/ Node.js sidecar API server |
| βββ tests/ Unit/integration tests (node:test) |
| βββ workers/ Cloudflare Workers (edge CORS preflight for api.worldmonitor.app) |
| ``` |
|
|