mirror of
https://github.com/koala73/worldmonitor.git
synced 2026-04-25 17:14:57 +02:00
* docs(mintlify): add Route Explorer + Scenario Engine workflow pages Checkpoint for review on the IA refresh (per plan docs/plans/2026-04-19-001-feat-docs-user-facing-ia-refresh-plan.md). - docs/docs.json: link Country Resilience Index methodology under Intelligence & Analysis so the flagship 222-country feature is reachable from the main nav (previously orphaned). Add a new Workflows group containing route-explorer and scenario-engine. - docs/route-explorer.mdx: standalone workflow page. Who it is for, Cmd+K entry, four tabs (Current / Alternatives / Land / Impact), inputs, keyboard bindings, map-state integration, PRO gating with free-tier blur + public-route highlight, data sources. - docs/scenario-engine.mdx: standalone workflow page. Template categories (conflict / weather / sanctions / tariff_shock / infrastructure / pandemic), how a scenario activates on the map, PRO gating, pointers to the async job API. Deferred to follow-up commits in the same PR: - documentation.mdx landing rewrite - features.mdx refresh - maritime-intelligence.mdx link-out to Route Explorer - Panels nav group (waits for PR 2 content) All content grounded in live source files cited inline. * docs(mintlify): fix Route Explorer + Scenario Engine review findings Reviewer caught 4 cases where I described behavior I hadn't read carefully. All fixes cross-checked against source. - route-explorer (free-tier): the workflow does NOT blur a numeric payload behind a public demo route. On free tier, fetchLane() short-circuits to renderFreeGate() which blurs the left rail, replaces the tab area with an Upgrade-to-PRO card, and applies a generic public-route highlight on the map. No lane data is rendered in any tab. See src/components/RouteExplorer/ RouteExplorer.ts:212 + :342. - route-explorer (keyboard): Tab / Shift+Tab moves focus between the panel and the map. Direct field jumps are F (From), T (To), P (Product/HS2), not Tab-cycling. Also added the full KeyboardHelp binding list (S swap, ↑/↓ list nav, Enter commit, Cmd+, copy URL, Esc close, ? help, 1-4 tabs). See src/components/RouteExplorer/ KeyboardHelp.ts:9 and RouteExplorer.ts:623. - scenario-engine: the SCENARIO_TEMPLATES array only ships templates of 4 types today (conflict, weather, sanctions, tariff_shock). The ScenarioType union includes infrastructure and pandemic but no templates of those types ship. Dropped them from the shipped table and noted the type union leaves room for future additions. - scenario-engine + api-scenarios: the worker writes status: 'done' (not 'completed') on success, 'failed' on error; pending is synthesised by the status endpoint when no worker record exists. Fixed both the new workflow page and the merged api-scenarios.mdx completed-response example + polling language. See scripts/scenario-worker.mjs:421 and src/components/SupplyChainPanel.ts:870. * docs(mintlify): fix third-round review findings (real IDs + 4-state lifecycle) - api-scenarios (template example): replaced invented hormuz-closure-30d / ["hormuz"] with the actually-shipped hormuz-tanker-blockade / ["hormuz_strait"] from scenario- templates.ts:80. Listed the other 5 shipped template IDs so scripted users aren't dependent on a single example. - api-scenarios (status lifecycle): worker writes FOUR states, not three. Added the intermediate "processing" state with startedAt, written by the worker at job pickup (scenario- worker.mjs:411). Lifecycle now: pending → processing → done|failed. Both pending and processing are non-terminal. - scenario-engine (scripted use blurb): mirror the 4-state language and link into the lifecycle table. - scenario-engine (UI dismiss): replaced "Click Deactivate" with the actual × dismiss control on the scenario banner (aria-label: "Dismiss scenario") per src/components/SupplyChainPanel.ts:790. Also described the banner contents (name, chokepoints, countries, tagline). - api-shipping-v2: while fixing chokepoint IDs, also corrected "hormuz" → "hormuz_strait" and "bab-el-mandeb" → "bab_el_mandeb" across all four occurrences in the shipping v2 page (from PR #3209). Real IDs come from server/_shared/chokepoint- registry.ts (snake_case, not kebab-case, not bare "hormuz"). * docs(mintlify): fix fourth-round findings (banner DOM, webhook TTL refresh) - scenario-engine: accurate description of the rendered scenario banner. Always-present elements are the ⚠ icon, scenario name, top-5 impacted countries with impact %, and dismiss ×. Params chip (e.g. '14d · +110% cost') and 'Simulating …' tagline are conditional on the worker result carrying template parameters (durationDays, disruptionPct, costShockMultiplier). The banner never lists affected chokepoints by name — the map and the chokepoint cards surface those. Per renderScenarioBanner at src/components/SupplyChainPanel.ts:750. - api-shipping-v2 (webhook TTL): register extends both the record and the owner-index set's 30-day TTL via atomic pipeline (SET + SADD + EXPIRE). rotate-secret and reactivate only extend the record's TTL — neither touches the owner-index set, so the owner index can expire independently if a caller only rotates/reactivates within a 30-day window. Re-register to keep both alive. Per api/v2/shipping/webhooks.ts:230 (register pipeline) and :325 (rotate setCachedJson on record only). * docs(mintlify): fix PRO auth contract (trusted origin ≠ PRO) - api-scenarios: 'X-WorldMonitor-Key (or trusted browser origin) + PRO' was wrong — isCallerPremium() explicitly skips trusted-origin short-circuits (keyCheck.required === false) and only counts (a) an env-valid or user-owned wm_-prefixed API key with apiAccess entitlement, or (b) a Clerk bearer with role=pro or Dodo tier ≥ 1. Browser calls work because premiumFetch() injects one of those credentials per request, not because Origin alone authenticates. Per server/_shared/premium-check.ts:34 and src/services/premium-fetch.ts:66. - usage-auth: strengthened the 'Entitlement / tier gating' section to state outright that authentication and PRO entitlement are orthogonal, and that trusted Origin is NOT accepted as PRO even though it is accepted for public endpoints. Listed the two real credential forms that pass the gate. * docs(mintlify): fix stale line cite (MapContainer.activateScenario at :1010) Greptile review P2: prose cited MapContainer.ts:1004 but activateScenario is declared at :1010. Line 1004 landed inside the JSDoc block. * docs(mintlify): finish PR 1 — landing rewrite, features refresh, maritime link-out Completes the PR 1 items from docs/plans/2026-04-19-001-feat-docs-user- facing-ia-refresh-plan.md that were deferred after the checkpoint on Route Explorer + Scenario Engine + CRI nav. No new pages — only edits to existing pages to point at and cohere with the new workflow pages. - documentation.mdx: landing rewrite. Dropped brittle counts (344 news sources, 49 layers, 24 CII countries, 31+ sources, 24 typed services) in favor of durable product framing. Surfaced the shipped differentiators that were invisible on the landing previously: Country Resilience Index (222 countries, linked to its methodology page), AI daily brief, Route Explorer, Scenario Engine, MCP server. Kept CII and CRI as two distinct country-risk surfaces — do not conflate. - features.mdx: replaced the 'all 55 panels' Cmd+K claim and the stale inventory list with family-grouped descriptions that include the panels this audit surfaced as missing (disease- outbreaks, radiation-watch, thermal-escalation, consumer-prices, latest-brief, forecast, country-resilience). Added a Workflows section linking to Route Explorer and Scenario Engine, and a Country-level risk section linking CII + CRI. Untouched sections (map, marker clustering, data layers, export, monitors, activity tracking) left as-is. - maritime-intelligence.mdx: collapsed the embedded Route Explorer subsection to a one-paragraph pointer at /route-explorer so the standalone page is the canonical home. Panels nav group remains intentionally unadded; it waits on PR 2 content to avoid rendering an empty group in Mintlify.
99 lines
4.4 KiB
Plaintext
99 lines
4.4 KiB
Plaintext
---
|
|
title: "Maritime Intelligence"
|
|
description: "Real-time vessel tracking with chokepoint monitoring, traffic density analysis, dark ship detection, and WebSocket-based AIS data streaming."
|
|
---
|
|
The Ships layer provides real-time vessel tracking and maritime domain awareness through AIS (Automatic Identification System) data, monitoring critical chokepoints, detecting anomalous vessel behavior, and streaming position updates over WebSocket connections.
|
|
|
|
## Route Explorer
|
|
|
|
Route Explorer is the keyboard-first workflow for planning a shipment between any two countries and seeing chokepoint exposure, bypass corridors, land alternatives, and per-country impact — all on top of this maritime layer. See the dedicated [Route Explorer](/route-explorer) page for the full workflow, tab contents, keyboard bindings, and tier gating.
|
|
|
|
## Chokepoint Monitoring
|
|
|
|
The system monitors 13 strategic waterways where disruptions could impact global trade, powered by three data sources: IMF PortWatch (weekly vessel transit counts), AISStream (real-time 24h crossing counter), and CorridorRisk (risk intelligence).
|
|
|
|
| Chokepoint | Strategic Importance |
|
|
|------------|---------------------|
|
|
| **Strait of Hormuz** | 20% of global oil transits; Iran control |
|
|
| **Suez Canal** | Europe-Asia shipping; single point of failure |
|
|
| **Strait of Malacca** | Primary Asia-Pacific oil route |
|
|
| **Bab el-Mandeb** | Red Sea access; Yemen/Houthi activity |
|
|
| **Panama Canal** | Americas east-west transit |
|
|
| **Taiwan Strait** | Semiconductor supply chain; PLA activity |
|
|
| **Cape of Good Hope** | Suez bypass route for VLCCs |
|
|
| **Strait of Gibraltar** | Atlantic-Mediterranean gateway; NATO chokepoint |
|
|
| **Bosporus Strait** | Black Sea access; includes Dardanelles corridor; Montreux Convention |
|
|
| **Korea Strait** | Japan-Korea trade; busiest East Asia corridor |
|
|
| **Dover Strait** | World's busiest shipping lane |
|
|
| **Kerch Strait** | Russia-controlled; Ukraine grain via Azov restricted |
|
|
| **Lombok Strait** | Malacca bypass for large tankers |
|
|
|
|
Each chokepoint card shows real-time transit counts (tanker vs cargo), week-over-week change, and an expandable 180-day time-series chart rendered with TradingView lightweight-charts.
|
|
|
|
## Density Analysis
|
|
|
|
Vessel positions are aggregated into a 2-degree grid to calculate traffic density. Each cell tracks:
|
|
|
|
- Current vessel count
|
|
- Historical baseline (30-minute rolling window)
|
|
- Change percentage from baseline
|
|
|
|
Density changes of +/-30% trigger alerts, indicating potential congestion, diversions, or blockades.
|
|
|
|
## Dark Ship Detection
|
|
|
|
The system monitors for AIS gaps, vessels that stop transmitting their position. An AIS gap exceeding 60 minutes in monitored regions may indicate:
|
|
|
|
- Sanctions evasion (ship-to-ship transfers)
|
|
- Illegal fishing
|
|
- Military activity
|
|
- Equipment failure
|
|
|
|
Vessels reappearing after gaps are flagged for the duration of the session.
|
|
|
|
## WebSocket Architecture
|
|
|
|
AIS data flows through a WebSocket relay for real-time updates without polling:
|
|
|
|
```
|
|
AISStream -> WebSocket Relay -> Browser
|
|
(ws://relay)
|
|
```
|
|
|
|
The connection automatically reconnects on disconnection with a 30-second backoff. When the Ships layer is disabled, the WebSocket disconnects to conserve resources.
|
|
|
|
## Railway Relay Architecture
|
|
|
|
Some APIs block requests from cloud providers (Vercel, AWS, Cloudflare Workers). A Railway relay server provides authenticated access:
|
|
|
|
```
|
|
Browser -> Railway Relay -> External APIs
|
|
(Node.js) (AIS, OpenSky, RSS)
|
|
```
|
|
|
|
**Relay Functions**:
|
|
|
|
| Endpoint | Purpose | Authentication |
|
|
|----------|---------|----------------|
|
|
| `/` (WebSocket) | AIS vessel stream | AISStream API key |
|
|
| `/opensky` | Military aircraft | OAuth2 Bearer token |
|
|
| `/rss` | Blocked RSS feeds | None (user-agent spoofing) |
|
|
| `/health` | Status check | None |
|
|
|
|
**Environment Variables** (Railway):
|
|
|
|
- `AISSTREAM_API_KEY` - AIS data access
|
|
- `OPENSKY_CLIENT_ID` - OAuth2 client ID
|
|
- `OPENSKY_CLIENT_SECRET` - OAuth2 client secret
|
|
|
|
**Why Railway?**
|
|
|
|
- Residential IP ranges (not blocked like cloud providers)
|
|
- WebSocket support for persistent connections
|
|
- Global edge deployment for low latency
|
|
- Free tier sufficient for moderate traffic
|
|
|
|
The relay is stateless; it simply authenticates and proxies requests. All caching and processing happens client-side or in Vercel Edge Functions.
|
|
|
|
See also [Finance Data - Chokepoints](/finance-data) for disruption scoring methodology.
|