Files
world/CHANGELOG.md
zeekayandHanzo Dev d4aa5c21dc Rename relay deployment mentions off a named rival platform
The WebSocket/RSS relay is deployment-target-agnostic in code and docs;
drop the platform brand from identifiers, comments, and prose describing
it. The industry status-board entry and the Gulf FDI "railways" transport
sector (unrelated meaning) are untouched.

Co-authored-by: Hanzo Dev <[email protected]>
Claude-Session: https://claude.ai/code/session_011i2AG9nwpiKUCVxAdDzYuU
2026-09-24 15:03:23 -07:00

20 KiB
Raw Permalink Blame History

Changelog

All notable changes to World Monitor are documented here.

[2.4.43]

Added

  • Finance-terminal alt-asset feeds are live (?variant=finance). The "Art & Collectibles — Auctions" and "Luxury Real Estate" panels now render REAL data instead of "live feed pending":
    • GET /v1/world/auctions — Christie's public auction results (realized sale totals: title, inferred category, price + currency, sale date, location, image, link). Sotheby's gates realized prices behind a login (its sale-results API returns 401 Not signed in), so the honest public major house is the source.
    • GET /v1/world/luxury-realestate — LuxuryEstate.com luxury listings (title, location, price + currency, type, image, link). JamesEdition sits behind a Cloudflare JS challenge that blocks datacenter egress, so it cannot be fetched from the pod.
    • Both are scraped server-side (internal/world/handlers_altassets.go) at most once an hour and served from cache to every caller (respectful). On a source failure the last-good copy is served; with no cache yet, an honest empty {items:[]} (the panel shows "live feed pending") — never fabricated data. The payload attributes its source per feed.

[2.4.19]

Fixed

  • Moving/resizing a panel no longer shifts the others (the "when I shift the 3D map it shifts all other components" report). The dashboard now DEFAULTS to the free layout: every panel owns its own {x,y,w,h}, so a drag or resize leaves every sibling exactly where it was — no more grid reflow. The switch is invisible: the current grid arrangement is frozen as the starting geometry (grid-config.applyDefaultLayout), and Grid stays one dropdown-click away for anyone who wants snap-to-grid back.
  • Panels resize granularly — pixel-exact width AND height from any edge or corner, instead of jumping between coarse column/row spans.
  • Panels can be made much narrower/smaller ("constrained on min width"): the free-mode floors drop to 96×40px (map 140px), and the grid widget-size slider now reaches a 120px column track (was 140).

Changed

  • A panel shown from the Panels menu / "+ Add widget" while in free mode seeds a tidy default slot below the placed panels (never a full-width block under its absolute siblings). Hidden panels no longer persist 0×0 geometry.

[2.4.13]

Fixed

  • Globe overlays now sit ON the sphere with correct occlusion (the "map spazzes" report). On the native deck.gl GlobeView, data layers (shared with the 2D map) carried no depth parameters, so the far hemisphere showed through and count badges floated above the limb. GlobeNative now seats every data layer against the depth-writing ocean sphere (test, don't write — no inter-marker z-fight), and the far-side billboard cull (occludeFarSide) faces the globe's OWN live camera instead of the parked (frozen) mapbox center — extended to TextLayer so a back-side "36" count badge disappears instead of hovering over the planet.
  • Terrain striping on the globe: the draped ESRI imagery tiles each wrote depth, so coplanar neighbours z-fought at the tile seams (horizontal stripes / partial render). Tiles now depth-TEST only; the ocean sphere owns the depth buffer.
  • Live request-geo dots kept polling on the 3D globe: the /v1/world/cloud/* poll was gated on renderPaused, which the native GlobeView sets on activation — so the realtime dots froze the moment you entered the default 3D view. It now gates on tab visibility, so the dots stay live (and fade) on the globe.

Changed

  • Request-origin → serving-region arcs on by default in the Cloud view: the /cloud/traffic arcs derive from the same real native request-geo points as the dots (origin country → nearest Hanzo region) and degrade to empty — never demo.

[2.4.6]

Added

  • Enso Flywheel panel (AI variant): the router self-improvement loop made visible. New /v1/world/enso-training folds the routing-decision ledger tail + reward tail (export-routing-ledger / export-routing-rewards, super-admin) into ledger growth, engine-vs-heuristic mix, a routing-confidence histogram, and task/model distributions, alongside the latest enso-bench eval scores (an embedded results/summary.json snapshot, overridable live via ENSO_BENCH_URL). The response is event-typed so future retrain/deploy milestones slot into the same timeline. Eval scores render even signed-out; state (live/partial/demo) says which live sources resolved.

[2.4.5]

Added

  • AI Compute panel (AI variant): live Hanzo inference-plane telemetry over SSE — tokens/s, requests/s, 24h spend, top models by real spend, and the serving fleet (GPUs, machines online, models served). New /v1/world/ai-pulse pushes typed usage/fleet/status frames (EventSource) and answers a plain GET with one JSON snapshot as the poll fallback. Honest "connecting"/"unavailable" states — never a zero dressed up as live; the service bearer stays server-side.

[2.4.4]

Changed

  • Cloud Pulse is real when a service token is wired: /v1/world/cloud-pulse now folds MEASURED platform-wide 24h request/token volume from the ClickHouse-backed usage ledger (get-cloud-usages ?org=all, super-admin) on top of the live model/node/GPU/region counts — dropping both demo:true and volumeModeled:true. Top models come from real ledger spend. Without a token, or with a non-admin token, it stays honestly demo/modeled — platform numbers are never faked silently. The service bearer stays server-side (never sent to the browser).

[2.4.2]

Added

  • Streaming analyst: answers flow in live over SSE — reasoning shows as dim thinking text, tool calls appear as chips the moment they run, the reply types itself in; the final render and command dispatch are unchanged (done event = the old JSON contract)
  • Model menu: the composer pill opens a grouped popover (Auto / Zen / GPT / Llama / Claude / Agents) with per-family marks and an active check

Fixed

  • Model identity: the Zen ring appears only on zen* models — gpt-oss/llama/claude get their own marks on the pill, menu rows, avatars, and the thinking row
  • Dev server: npm run dev proxies /v1 to production by default (VITE_DEV_API_PROXY overrides)

[2.4.1]

Added

  • Western Pacific cyclones: cross-agency tropical-cyclone attribution (GDACS + HKO warnings via new /v1/world/hko-warnings proxy) with per-agency wind observations, canonical dedup, and map popup detail rows
  • China macro snapshot: /v1/world/china-macro — CPI/CLI (OECD), policy rate, USD/CNY (FRED), HKMA context, NBS release calendar + PBoC LPR dates, surfaced with staleness-honest indicator tiles
  • Model roster: Best (auto) leads the analyst model picker — the gateway routing alias that always resolves

Changed

  • AI default model: zen5 → best; a pinned family id goes dark when the inference plane's claim catalog shifts, the routing alias never does
  • Server cache is now stale-while-revalidate: cachedJSON/passthrough serve stale instantly and refresh in the background (single-flight); GDELT/theater-posture no longer stall requests ~10s on TTL expiry
  • GDELT cache warmers: hot keys (analyst grounding, protests layer) refreshed every ~4min so no user ever eats a cold miss
  • Sparkline payloads: close arrays rounded to 7 significant digits (float32-widening noise stripped, ~40% smaller; scalars untouched)

Fixed

  • News first paint: panels no longer gate their first DOM write on a 65MB ML sentiment model download — headlines paint immediately, sentiment refines in place
  • Analyst grounding snapshot: context fetches bounded at 2.5s so a cold endpoint can't hold the chat send hostage
  • AI errors are honest: upstream error codes (insufficient_balance, spend_cap_exceeded, …) surface in the chat instead of a bare status 402

[2.4.0] - 2026-02-19

Added

  • Live Webcams Panel: 2x2 grid of live YouTube webcam feeds from global hotspots with region filters (Middle East, Europe, Asia-Pacific, Americas), grid/single view toggle, idle detection, and full i18n support (#111)
  • Linux download: added .AppImage option to download banner

Changed

  • Mobile detection: use viewport width only for mobile detection; touch-capable notebooks (e.g. ROG Flow X13) now get desktop layout (#113)
  • Webcam feeds: curated Tel Aviv, Mecca, LA, Miami; replaced dead Tokyo feed; diverse ALL grid with Jerusalem, Tehran, Kyiv, Washington

Fixed

  • Le Monde RSS: English feed URL updated (/en/rss/full.xml → /en/rss/une.xml) to fix 404
  • Workbox precache: added html to globPatterns so navigateFallback works for offline PWA
  • Panel ordering: one-time migration ensures Live Webcams follows Live News for existing users
  • Mobile popups: improved sheet/touch/controls layout (#109)
  • Intelligence alerts: disabled on mobile to reduce noise (#110)
  • RSS proxy: added 8 missing domains to allowlist
  • HTML tags: repaired malformed tags in panel template literals
  • ML worker: wrapped unloadModel() in try/catch to prevent unhandled timeout rejections
  • YouTube player: optional chaining on playVideo?.() / pauseVideo?.() for initialization race
  • Panel drag: guarded .closest() on non-Element event targets
  • Beta mode: resolved race condition and timeout failures
  • Sentry noise: added filters for Firefox too much recursion, maplibre _layers/id/type null crashes

[2.3.9] - 2026-02-18

Added

  • Full internationalization (14 locales): English, French, German, Spanish, Italian, Polish, Portuguese, Dutch, Swedish, Russian, Arabic, Chinese Simplified, Japanese — each with 1100+ translated keys
  • RTL support: Arabic locale with dir="rtl", dedicated RTL CSS overrides, regional language code normalization (e.g. ar-SA correctly triggers RTL)
  • Language switcher: in-app locale picker with flag icons, persists to localStorage
  • i18n infrastructure: i18next with browser language detection and English fallback
  • Community discussion widget: floating pill linking to GitHub Discussions with delayed appearance and permanent dismiss
  • Linux AppImage: added ubuntu-22.04 to CI build matrix with webkit2gtk/appindicator dependencies
  • NHK World and Nikkei Asia: added RSS feeds for Japan news coverage
  • Intelligence Findings badge toggle: option to disable the findings badge in the UI

Changed

  • Zero hardcoded English: all UI text routed through t() — panels, modals, tooltips, popups, map legends, alert templates, signal descriptions
  • Trending proper-noun detection: improved mid-sentence capitalization heuristic with all-caps fallback when ML classifier is unavailable
  • Stopword suppression: added missing English stopwords to trending keyword filter

Fixed

  • Dead UTC clock: removed #timeDisplay element that permanently displayed --:--:-- UTC
  • Community widget duplicates: added DOM idempotency guard preventing duplicate widgets on repeated news refresh cycles
  • Settings help text: suppressed raw i18n key paths rendering when translation is missing
  • Intelligence Findings badge: fixed toggle state and listener lifecycle
  • Context menu styles: restored intel-findings context menu styles
  • CSS theme variables: defined missing --panel-bg and --panel-border variables

[2.3.8] - 2026-02-17

Added

  • Finance variant: Added a dedicated market-first variant (world.hanzo.ai) with finance/trading-focused feeds, panels, and map defaults
  • Finance desktop profile: Added finance-specific desktop config and build profile for Tauri packaging

Changed

  • Variant feed loading: loadNews now enumerates categories dynamically and stages category fetches with bounded concurrency across variants
  • Feed resilience: Replaced direct MarketWatch RSS usage in finance/full/tech paths with Google News-backed fallback queries
  • Classification pressure controls: Tightened AI classification budgets for tech/full and tuned per-feed caps to reduce startup burst pressure
  • Timeline behavior: Wired timeline filtering consistently across map and news panels
  • AI summarization defaults: Switched OpenRouter summarization to auto-routed free-tier model selection

Fixed

  • Finance panel parity: Kept data-rich panels while adding news panels for finance instead of removing core data surfaces
  • Desktop finance map parity: Finance variant now runs first-class Deck.GL map/layer behavior on desktop runtime
  • Polymarket fallback: Added one-time direct connectivity probe and memoized fallback to prevent repeated ERR_CONNECTION_RESET storms
  • FRED fallback behavior: Missing FRED_API_KEY now returns graceful empty payloads instead of repeated hard 500s
  • Preview CSP tooling: Allowed https://vercel.live script in CSP so Vercel preview feedback injection is not blocked
  • Trending quality: Suppressed noisy generic finance terms in keyword spike detection
  • Mobile UX: Hidden desktop download prompt on mobile devices

[2.3.7] - 2026-02-16

Added

  • Full light mode theme: Complete light/dark theme system with CSS custom properties, ThemeManager module, FOUC prevention, and getCSSColor() utility for theme-aware inline styles
  • Theme-aware maps and charts: Deck.GL basemap, overlay layers, and CountryTimeline charts respond to theme changes in real time
  • Dark/light mode header toggle: Sun/moon icon in the header bar for quick theme switching, replacing the duplicate UTC clock
  • Desktop update checker: Architecture-aware download links for macOS (ARM/Intel) and Windows
  • Node.js bundled in Tauri installer: Sidecar no longer requires system Node.js
  • Markdown linting: Added markdownlint config and CI workflow

Changed

  • Panels modal: Reverted from "Settings" back to "Panels" — removed redundant Appearance section now that header has theme toggle
  • Default panels: Enabled UCDP Conflict Events, UNHCR Displacement, Climate Anomalies, and Population Exposure panels by default

Fixed

  • CORS for Tauri desktop: Fixed CORS issues for desktop app requests
  • Markets panel: Keep Yahoo-backed data visible when Finnhub API key is skipped
  • Windows UNC paths: Preserve extended-length path prefix when sanitizing sidecar script path
  • Light mode readability: Darkened neon semantic colors and overlay backgrounds for light mode contrast

[2.3.6] - 2026-02-16

Fixed

  • Windows console window: Hide the node.exe console window that appeared alongside the desktop app on Windows

[2.3.5] - 2026-02-16

Changed

  • Panel error messages: Differentiated error messages per panel so users see context-specific guidance instead of generic failures
  • Desktop config auto-hide: Desktop configuration panel automatically hides on web deployments where it is not relevant

[2.3.4] - 2026-02-16

Fixed

  • Windows sidecar crash: Strip \\?\ UNC extended-length prefix from paths before passing to Node.js — Tauri resource_dir() on Windows returns UNC-prefixed paths that cause EISDIR: lstat 'C:' in Node.js module resolution
  • Windows sidecar CWD: Set explicit current_dir on the Node.js Command to prevent bare drive-letter working directory issues from NSIS shortcut launcher
  • Sidecar package scope: Add package.json with "type": "module" to sidecar directory, preventing Node.js from walking up the entire directory tree during ESM scope resolution

[2.3.3] - 2026-02-16

Fixed

  • Keychain persistence: Enable apple-native (macOS) and windows-native (Windows) features for the keyring crate — v3 ships with no default platform backends, so API keys were stored in-memory only and lost on restart
  • Settings key verification: Soft-pass network errors during API key verification so transient sidecar failures don't block saving
  • Resilient keychain reads: Use Promise.allSettled in loadDesktopSecrets so a single key failure doesn't discard all loaded secrets
  • Settings window capabilities: Add "settings" to Tauri capabilities window list for core plugin permissions
  • Input preservation: Capture unsaved input values before DOM re-render in settings panel

[2.3.0] - 2026-02-15

Security

  • CORS hardening: Tighten Vercel preview deployment regex to block origin spoofing (worldmonitorEVIL.vercel.app)
  • Sidecar auth bypass: Move /api/local-env-update behind LOCAL_API_TOKEN auth check
  • Env key allowlist: Restrict sidecar env mutations to 18 known secret keys (matching SUPPORTED_SECRET_KEYS)
  • postMessage validation: Add origin and source checks on incoming messages in LiveNewsPanel
  • postMessage targetOrigin: Replace wildcard '*' with specific embed origin
  • CORS enforcement: Add isDisallowedOrigin() check to 25+ API endpoints that were missing it
  • Custom CORS migration: Migrate gdelt-geo and eia from custom CORS to shared _cors.js module
  • New CORS coverage: Add CORS headers + origin check to firms-fires, stock-index, youtube/live
  • YouTube embed origins: Tighten ALLOWED_ORIGINS regex in youtube/embed.js
  • CSP hardening: Remove 'unsafe-inline' from script-src in both index.html and tauri.conf.json
  • iframe sandbox: Add sandbox="allow-scripts allow-same-origin allow-presentation" to YouTube embed iframe
  • Meta tag validation: Validate URL query params with regex allowlist in parseStoryParams()

Fixed

  • Service worker stale assets: Add skipWaiting, clientsClaim, and cleanupOutdatedCaches to workbox config — fixes NS_ERROR_CORRUPTED_CONTENT / MIME type errors when users have a cached SW serving old HTML after redeployment

[2.2.6] - 2026-02-14

Fixed

  • Filter trending noise and fix sidecar auth
  • Restore tech variant panels
  • Remove Market Radar and Economic Data panels from tech variant

Docs

  • Add developer X/Twitter link to Support section
  • Add cyber threat API keys to .env.example

[2.2.5] - 2026-02-13

Security

  • Migrate all Vercel edge functions to CORS allowlist
  • Restrict relay CORS to allowed origins only

Fixed

  • Hide desktop config panel on web
  • Route World Bank & Polymarket via relay

[2.2.3] - 2026-02-12

Added

  • Cyber threat intelligence map layer (Feodo Tracker, URLhaus, C2IntelFeeds, OTX, AbuseIPDB)
  • Trending keyword spike detection with end-to-end flow
  • Download desktop app slide-in banner for web visitors
  • Country briefs in Cmd+K search

Changed

  • Redesign 4 panels with table layouts and scoped styles
  • Redesign population exposure panel and reorder UCDP columns
  • Dramatically increase cyber threat map density

Fixed

  • Resolve z-index conflict between pinned map and panels grid
  • Cap geo enrichment at 12s timeout, prevent duplicate download banners
  • Replace ipwho.is/ipapi.co with ipinfo.io/freeipapi.com for geo enrichment
  • Harden trending spike processing and optimize hot paths
  • Improve cyber threat tooltip/popup UX and dot visibility

[2.2.2] - 2026-02-10

Added

  • Full-page Country Brief Page replacing modal overlay
  • Download redirect API for platform-specific installers

Fixed

  • Normalize country name from GeoJSON to canonical TIER1 name
  • Tighten headline relevance, add Top News section, compact markets
  • Hide desktop config panel on web, fix irrelevant prediction markets
  • Tone down climate anomalies heatmap to stop obscuring other layers
  • macOS: hide window on close instead of quitting

Performance

  • Reduce idle CPU from pulse animation loop
  • Harden regression guardrails in CI, cache, and map clustering

[2.2.1] - 2026-02-08

Fixed

  • Consolidate variant naming and fix PWA tile caching
  • Windows settings window: async command, no menu bar, no white flash
  • Constrain layers menu height in DeckGLMap
  • Allow Cloudflare Insights script in CSP
  • macOS build failures when Apple signing secrets are missing

[2.2.0] - 2026-02-07

Initial v2.2 release with multi-variant support (World + Tech), desktop app (Tauri), and comprehensive geopolitical intelligence features.