Files
worldmonitor/docs/Docs_To_Review/DATA_MODEL.md
Elie Habib 07d0803014 Add WTO trade policy intelligence service with tariffs, flows, and barriers (#364)
* feat: add WTO trade policy service with 4 RPC endpoints and TradePolicyPanel

Adds a new `trade` RPC domain backed by the WTO API (apiportal.wto.org) for
trade policy intelligence: quantitative restrictions, tariff timeseries,
bilateral trade flows, and SPS/TBT barrier notifications.

New files: 6 protos, generated server/client, 4 server handlers + shared WTO
fetch utility, client service with circuit breakers, TradePolicyPanel (4 tabs),
and full API key infrastructure (Rust keychain, sidecar, runtime config).

Panel registered for FULL and FINANCE variants with data loader integration,
command palette entry, status panel tracking, data freshness monitoring, and
i18n across all 17 locale files.

https://claude.ai/code/session_01HZXyoQp6xK3TX8obDzv6Ye

* chore: update package-lock.json

https://claude.ai/code/session_01HZXyoQp6xK3TX8obDzv6Ye

* fix: move tab click listener to constructor to prevent leak

The delegated click handler was added inside render(), which runs
on every data update (4× per load cycle). Since the listener targets
this.content (a persistent container), each call stacked a duplicate
handler. Moving it to the constructor binds it exactly once.

https://claude.ai/code/session_01HZXyoQp6xK3TX8obDzv6Ye

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-25 10:50:12 +00:00

44 KiB
Raw Blame History

Data Model Reference

Comprehensive data model documentation for World Monitor — an AI-powered real-time global intelligence dashboard. This reference covers all TypeScript interfaces, data structures, and their relationships across the system.

Source of truth: src/types/index.ts (1,297 lines, 60+ interfaces)


Table of Contents

  1. Core News & Events
  2. Geopolitical & Military
  3. Cyber & Security
  4. Humanitarian & Climate
  5. Infrastructure
  6. Natural Events
  7. Markets & Finance
  8. Tech Variant Types
  9. Panel & Map Configuration
  10. Application State
  11. Focal Points
  12. Social Unrest
  13. Entity Model
  14. News Item Lifecycle
  15. Signal Model
  16. Map Data Models
  17. Panel State Model
  18. Variant Configuration
  19. Risk Scoring Models
  20. Cache & Storage Schemas

1. Core News & Events

The news pipeline ingests RSS feeds, parses individual items, clusters them into events, and scores each event for severity and velocity.

Feed

RSS feed configuration. Each feed defines a source to poll, with optional metadata for filtering and propaganda risk assessment.

interface Feed {
  name: string;
  url: string | Record<string, string>;
  type?: string;
  region?: string;
  propagandaRisk?: PropagandaRisk;       // 'low' | 'medium' | 'high'
  stateAffiliated?: string;              // e.g. "Russia", "China", "Iran"
  lang?: string;                         // ISO 2-letter language code
}

NewsItem

A single parsed news article from an RSS feed. The minimal unit of intelligence in the pipeline.

interface NewsItem {
  source: string;
  title: string;
  link: string;
  pubDate: Date;
  isAlert: boolean;
  monitorColor?: string;
  tier?: number;
  threat?: ThreatClassification;
  lat?: number;
  lon?: number;
  locationName?: string;
  lang?: string;
}

ClusteredEvent

Multiple NewsItems merged into a single event via Jaccard or hybrid semantic clustering. This is the primary unit displayed in news panels.

interface ClusteredEvent {
  id: string;
  primaryTitle: string;
  primarySource: string;
  primaryLink: string;
  sourceCount: number;
  topSources: Array<{ name: string; tier: number; url: string }>;
  allItems: NewsItem[];
  firstSeen: Date;
  lastUpdated: Date;
  isAlert: boolean;
  monitorColor?: string;
  velocity?: VelocityMetrics;
  threat?: ThreatClassification;
  lat?: number;
  lon?: number;
  lang?: string;
}

VelocityMetrics

Measures how quickly a story is spreading across sources. Used to detect breaking news and surging stories.

type VelocityLevel = 'normal' | 'elevated' | 'spike';
type SentimentType = 'negative' | 'neutral' | 'positive';

interface VelocityMetrics {
  sourcesPerHour: number;
  level: VelocityLevel;
  trend: 'rising' | 'stable' | 'falling';
  sentiment: SentimentType;
  sentimentScore: number;
}

RelatedAsset

Links a news event to a nearby physical asset (pipeline, cable, datacenter, military base, nuclear facility).

type AssetType = 'pipeline' | 'cable' | 'datacenter' | 'base' | 'nuclear';

interface RelatedAsset {
  id: string;
  name: string;
  type: AssetType;
  distanceKm: number;
}

interface RelatedAssetContext {
  origin: { label: string; lat: number; lon: number };
  types: AssetType[];
  assets: RelatedAsset[];
}

2. Geopolitical & Military

Hotspot

A monitored geopolitical hotspot from the geo configuration. Includes static metadata and dynamic escalation tracking.

type EscalationTrend = 'escalating' | 'stable' | 'de-escalating';

interface Hotspot {
  id: string;
  name: string;
  lat: number;
  lon: number;
  keywords: string[];
  subtext?: string;
  location?: string;             // e.g. "Sahel Region, West Africa"
  agencies?: string[];
  level?: 'low' | 'elevated' | 'high';
  description?: string;
  status?: string;
  escalationScore?: 1 | 2 | 3 | 4 | 5;
  escalationTrend?: EscalationTrend;
  escalationIndicators?: string[];
  history?: HistoricalContext;
  whyItMatters?: string;
}

interface HistoricalContext {
  lastMajorEvent?: string;
  lastMajorEventDate?: string;
  precedentCount?: number;
  precedentDescription?: string;
  cyclicalRisk?: string;
}

DynamicEscalationScore

Real-time escalation assessment combining static baselines with live signal data. Maintained in src/services/hotspot-escalation.ts.

interface DynamicEscalationScore {
  hotspotId: string;
  staticBaseline: number;
  dynamicScore: number;
  combinedScore: number;
  trend: EscalationTrend;
  components: {
    newsActivity: number;       // weight: 0.35
    ciiContribution: number;    // weight: 0.25
    geoConvergence: number;     // weight: 0.25
    militaryActivity: number;   // weight: 0.15
  };
  history: Array<{ timestamp: number; score: number }>;
  lastUpdated: Date;
}

ConflictZone

Active conflict zone with polygon boundaries and contextual metadata.

interface ConflictZone {
  id: string;
  name: string;
  coords: [number, number][];
  center: [number, number];
  intensity?: 'high' | 'medium' | 'low';
  parties?: string[];
  casualties?: string;
  displaced?: string;
  keywords?: string[];
  startDate?: string;
  location?: string;
  description?: string;
  keyDevelopments?: string[];
}

UCDP Geo Events

Georeferenced events from the Uppsala Conflict Data Program.

type UcdpEventType = 'state-based' | 'non-state' | 'one-sided';

interface UcdpGeoEvent {
  id: string;
  date_start: string;
  date_end: string;
  latitude: number;
  longitude: number;
  country: string;
  side_a: string;
  side_b: string;
  deaths_best: number;
  deaths_low: number;
  deaths_high: number;
  type_of_violence: UcdpEventType;
  source_original: string;
}

Military Bases

Foreign military installations and bases worldwide.

type MilitaryBaseType =
  | 'us-nato' | 'china' | 'russia' | 'uk' | 'france'
  | 'india' | 'italy' | 'uae' | 'turkey' | 'japan' | 'other';

interface MilitaryBase {
  id: string;
  name: string;
  lat: number;
  lon: number;
  type: MilitaryBaseType;
  description?: string;
  country?: string;            // Host country
  arm?: string;                // Armed forces branch
  status?: 'active' | 'planned' | 'controversial' | 'closed';
  source?: string;
}

Military Flights

Tracked military aircraft from ADS-B/OpenSky with classification metadata.

type MilitaryAircraftType =
  | 'fighter' | 'bomber' | 'transport' | 'tanker' | 'awacs'
  | 'reconnaissance' | 'helicopter' | 'drone' | 'patrol'
  | 'special_ops' | 'vip' | 'unknown';

type MilitaryOperator =
  | 'usaf' | 'usn' | 'usmc' | 'usa' | 'raf' | 'rn'
  | 'faf' | 'gaf' | 'plaaf' | 'plan' | 'vks' | 'iaf'
  | 'nato' | 'other';

interface MilitaryFlight {
  id: string;
  callsign: string;
  hexCode: string;
  registration?: string;
  aircraftType: MilitaryAircraftType;
  aircraftModel?: string;
  operator: MilitaryOperator;
  operatorCountry: string;
  lat: number;
  lon: number;
  altitude: number;
  heading: number;
  speed: number;
  verticalRate?: number;
  onGround: boolean;
  squawk?: string;
  origin?: string;
  destination?: string;
  lastSeen: Date;
  firstSeen?: Date;
  track?: [number, number][];
  confidence: 'high' | 'medium' | 'low';
  isInteresting?: boolean;
  note?: string;
  enriched?: {
    manufacturer?: string;
    owner?: string;
    operatorName?: string;
    typeCode?: string;
    builtYear?: string;
    confirmedMilitary?: boolean;
    militaryBranch?: string;
  };
}

interface MilitaryFlightCluster {
  id: string;
  name: string;
  lat: number;
  lon: number;
  flightCount: number;
  flights: MilitaryFlight[];
  dominantOperator?: MilitaryOperator;
  activityType?: 'exercise' | 'patrol' | 'transport' | 'unknown';
}

Military Vessels

Naval vessel tracking from AIS data with type classification.

type MilitaryVesselType =
  | 'carrier' | 'destroyer' | 'frigate' | 'submarine'
  | 'amphibious' | 'patrol' | 'auxiliary' | 'research'
  | 'icebreaker' | 'special' | 'unknown';

interface MilitaryVessel {
  id: string;
  mmsi: string;
  name: string;
  vesselType: MilitaryVesselType;
  aisShipType?: string;
  hullNumber?: string;
  operator: MilitaryOperator | 'other';
  operatorCountry: string;
  lat: number;
  lon: number;
  heading: number;
  speed: number;
  course?: number;
  destination?: string;
  lastAisUpdate: Date;
  aisGapMinutes?: number;
  isDark?: boolean;
  nearChokepoint?: string;
  nearBase?: string;
  track?: [number, number][];
  confidence: 'high' | 'medium' | 'low';
  isInteresting?: boolean;
  note?: string;
}

interface MilitaryVesselCluster {
  id: string;
  name: string;
  lat: number;
  lon: number;
  vesselCount: number;
  vessels: MilitaryVessel[];
  region?: string;
  activityType?: 'exercise' | 'deployment' | 'transit' | 'unknown';
}

Military Activity Summary

Aggregated view of all tracked military assets.

interface MilitaryActivitySummary {
  flights: MilitaryFlight[];
  vessels: MilitaryVessel[];
  flightClusters: MilitaryFlightCluster[];
  vesselClusters: MilitaryVesselCluster[];
  activeOperations: number;
  lastUpdate: Date;
}

Strategic Waterways & AIS

interface StrategicWaterway {
  id: string;
  name: string;
  lat: number;
  lon: number;
  description?: string;
}

type AisDisruptionType = 'gap_spike' | 'chokepoint_congestion';

interface AisDisruptionEvent {
  id: string;
  name: string;
  type: AisDisruptionType;
  lat: number;
  lon: number;
  severity: 'low' | 'elevated' | 'high';
  changePct: number;
  windowHours: number;
  darkShips?: number;
  vesselCount?: number;
  region?: string;
  description: string;
}

interface AisDensityZone {
  id: string;
  name: string;
  lat: number;
  lon: number;
  intensity: number;
  deltaPct: number;
  shipsPerDay?: number;
  note?: string;
}

GDELT Tension & PizzINT

interface GdeltTensionPair {
  id: string;
  countries: [string, string];
  label: string;
  score: number;
  trend: 'rising' | 'stable' | 'falling';
  changePercent: number;
  region: string;
}

// Pentagon Pizza Index (novelty OSINT indicator)
type PizzIntDefconLevel = 1 | 2 | 3 | 4 | 5;
type PizzIntDataFreshness = 'fresh' | 'stale';

interface PizzIntStatus {
  defconLevel: PizzIntDefconLevel;
  defconLabel: string;
  aggregateActivity: number;
  activeSpikes: number;
  locationsMonitored: number;
  locationsOpen: number;
  lastUpdate: Date;
  dataFreshness: PizzIntDataFreshness;
  locations: PizzIntLocation[];
}

3. Cyber & Security

CyberThreat

Cyber threat indicators sourced from threat intelligence feeds (Feodo, URLhaus, C2Intel, OTX, AbuseIPDB).

type CyberThreatType = 'c2_server' | 'malware_host' | 'phishing' | 'malicious_url';
type CyberThreatSource = 'feodo' | 'urlhaus' | 'c2intel' | 'otx' | 'abuseipdb';
type CyberThreatSeverity = 'low' | 'medium' | 'high' | 'critical';
type CyberThreatIndicatorType = 'ip' | 'domain' | 'url';

interface CyberThreat {
  id: string;
  type: CyberThreatType;
  source: CyberThreatSource;
  indicator: string;
  indicatorType: CyberThreatIndicatorType;
  lat: number;
  lon: number;
  country?: string;
  severity: CyberThreatSeverity;
  malwareFamily?: string;
  tags: string[];
  firstSeen?: string;
  lastSeen?: string;
}

APT Groups

Known Advanced Persistent Threat group profiles, mapped to their attributed state sponsors.

interface APTGroup {
  id: string;
  name: string;
  aka: string;
  sponsor: string;
  lat: number;
  lon: number;
}

4. Humanitarian & Climate

UNHCR Displacement

Three-tier model: global summary → country-level displacement → individual flow corridors.

interface DisplacementFlow {
  originCode: string;
  originName: string;
  asylumCode: string;
  asylumName: string;
  refugees: number;
  originLat?: number;
  originLon?: number;
  asylumLat?: number;
  asylumLon?: number;
}

interface CountryDisplacement {
  code: string;
  name: string;
  // Origin-country displacement outflow
  refugees: number;
  asylumSeekers: number;
  idps: number;
  stateless: number;
  totalDisplaced: number;
  // Host-country intake
  hostRefugees: number;
  hostAsylumSeekers: number;
  hostTotal: number;
  lat?: number;
  lon?: number;
}

interface UnhcrSummary {
  year: number;
  globalTotals: {
    refugees: number;
    asylumSeekers: number;
    idps: number;
    stateless: number;
    total: number;
  };
  countries: CountryDisplacement[];
  topFlows: DisplacementFlow[];
}

Climate Anomalies

Derived from Open-Meteo / ERA5 reanalysis data.

type AnomalySeverity = 'normal' | 'moderate' | 'extreme';

interface ClimateAnomaly {
  zone: string;
  lat: number;
  lon: number;
  tempDelta: number;
  precipDelta: number;
  severity: AnomalySeverity;
  type: 'warm' | 'cold' | 'wet' | 'dry' | 'mixed';
  period: string;
}

Population Exposure

WorldPop-derived population density for impact assessment.

interface CountryPopulation {
  code: string;
  name: string;
  population: number;
  densityPerKm2: number;
}

interface PopulationExposure {
  eventId: string;
  eventName: string;
  eventType: string;
  lat: number;
  lon: number;
  exposedPopulation: number;
  exposureRadiusKm: number;
}

5. Infrastructure

Undersea Cables

Submarine cable routes with landing points and country-level capacity data.

interface CableLandingPoint {
  country: string;       // ISO code
  countryName: string;
  city?: string;
  lat: number;
  lon: number;
}

interface CountryCapacity {
  country: string;       // ISO code
  capacityShare: number; // 01
  isRedundant: boolean;
}

interface UnderseaCable {
  id: string;
  name: string;
  points: [number, number][];
  major?: boolean;
  landingPoints?: CableLandingPoint[];
  countriesServed?: CountryCapacity[];
  capacityTbps?: number;
  rfsYear?: number;
  owners?: string[];
}

interface CableAdvisory {
  id: string;
  cableId: string;
  title: string;
  severity: 'fault' | 'degraded';
  description: string;
  reported: Date;
  lat: number;
  lon: number;
  impact: string;
  repairEta?: string;
}

interface RepairShip {
  id: string;
  name: string;
  cableId: string;
  status: 'enroute' | 'on-station';
  lat: number;
  lon: number;
  eta: string;
  operator?: string;
  note?: string;
}

Pipelines

Oil and gas pipelines with terminal endpoints and capacity data.

type PipelineType = 'oil' | 'gas' | 'products';
type PipelineStatus = 'operating' | 'construction';

interface PipelineTerminal {
  country: string;
  name?: string;
  portId?: string;
  lat?: number;
  lon?: number;
}

interface Pipeline {
  id: string;
  name: string;
  type: PipelineType;
  status: PipelineStatus;
  points: [number, number][];
  capacity?: string;
  length?: string;
  operator?: string;
  countries?: string[];
  origin?: PipelineTerminal;
  destination?: PipelineTerminal;
  transitCountries?: string[];
  capacityMbpd?: number;
  capacityBcmY?: number;
  alternatives?: string[];
}

Internet Outages

Real-time internet connectivity disruptions.

interface InternetOutage {
  id: string;
  title: string;
  link: string;
  description: string;
  pubDate: Date;
  country: string;
  region?: string;
  lat: number;
  lon: number;
  severity: 'partial' | 'major' | 'total';
  categories: string[];
  cause?: string;
  outageType?: string;
  endDate?: Date;
}

Infrastructure Cascade Analysis

Graph-based dependency model for simulating cascading failures across infrastructure networks.

type InfrastructureNodeType = 'cable' | 'pipeline' | 'port' | 'chokepoint' | 'country' | 'route';

interface InfrastructureNode {
  id: string;
  type: InfrastructureNodeType;
  name: string;
  coordinates?: [number, number];
  metadata?: Record<string, unknown>;
}

type DependencyType =
  | 'serves' | 'terminates_at' | 'transits_through' | 'lands_at'
  | 'depends_on' | 'shares_risk' | 'alternative_to'
  | 'trade_route' | 'controls_access' | 'trade_dependency';

interface DependencyEdge {
  from: string;
  to: string;
  type: DependencyType;
  strength: number;        // 01 criticality
  redundancy?: number;     // 01 replaceability
  metadata?: {
    capacityShare?: number;
    alternativeRoutes?: number;
    estimatedImpact?: string;
    portType?: string;
    relationship?: string;
  };
}

type CascadeImpactLevel = 'critical' | 'high' | 'medium' | 'low';

interface CascadeAffectedNode {
  node: InfrastructureNode;
  impactLevel: CascadeImpactLevel;
  pathLength: number;
  dependencyChain: string[];
  redundancyAvailable: boolean;
  estimatedRecovery?: string;
}

interface CascadeResult {
  source: InfrastructureNode;
  affectedNodes: CascadeAffectedNode[];
  countriesAffected: CascadeCountryImpact[];
  economicImpact?: {
    dailyTradeLoss?: number;
    affectedThroughput?: number;
  };
  redundancies?: Array<{
    id: string;
    name: string;
    capacityShare: number;
  }>;
}

Nuclear Facilities

type NuclearFacilityType =
  | 'plant' | 'enrichment' | 'reprocessing' | 'weapons'
  | 'ssbn' | 'test-site' | 'icbm' | 'research';

interface NuclearFacility {
  id: string;
  name: string;
  lat: number;
  lon: number;
  type: NuclearFacilityType;
  status: 'active' | 'contested' | 'inactive' | 'decommissioned' | 'construction';
  operator?: string;
}

interface GammaIrradiator {
  id: string;
  city: string;
  country: string;
  lat: number;
  lon: number;
  organization?: string;
}

6. Natural Events

Earthquakes

USGS earthquake data.

interface Earthquake {
  id: string;
  place: string;
  magnitude: number;
  lat: number;
  lon: number;
  depth: number;
  time: Date;
  url: string;
}

NASA EONET Natural Events

type NaturalEventCategory =
  | 'severeStorms' | 'wildfires' | 'volcanoes' | 'earthquakes'
  | 'floods' | 'landslides' | 'drought' | 'dustHaze'
  | 'snow' | 'tempExtremes' | 'seaLakeIce' | 'waterColor' | 'manmade';

interface NaturalEvent {
  id: string;
  title: string;
  description?: string;
  category: NaturalEventCategory;
  categoryTitle: string;
  lat: number;
  lon: number;
  date: Date;
  magnitude?: number;
  magnitudeUnit?: string;
  sourceUrl?: string;
  sourceName?: string;
  closed: boolean;
}

7. Markets & Finance

MarketData

Equities, indices, and commodities pricing.

interface MarketData {
  symbol: string;
  name: string;
  display: string;
  price: number | null;
  change: number | null;
  sparkline?: number[];
}

interface CryptoData {
  name: string;
  symbol: string;
  price: number;
  change: number;
  sparkline?: number[];
}

interface Sector {
  symbol: string;
  name: string;
}

interface Commodity {
  symbol: string;
  name: string;
  display: string;
}

Prediction Markets

Polymarket-sourced prediction contract data.

interface PredictionMarket {
  title: string;
  yesPrice: number;
  volume?: number;
  url?: string;
}

Gulf FDI Investments

Tracks Saudi and UAE foreign direct investment in global infrastructure.

type GulfInvestorCountry = 'SA' | 'UAE';

type GulfInvestmentSector =
  | 'ports' | 'pipelines' | 'energy' | 'datacenters' | 'airports'
  | 'railways' | 'telecoms' | 'water' | 'logistics' | 'mining'
  | 'real-estate' | 'manufacturing';

type GulfInvestmentStatus =
  | 'operational' | 'under-construction' | 'announced'
  | 'rumoured' | 'cancelled' | 'divested';

type GulfInvestingEntity =
  | 'DP World' | 'AD Ports' | 'Mubadala' | 'ADIA' | 'ADNOC'
  | 'Masdar' | 'PIF' | 'Saudi Aramco' | 'ACWA Power' | 'STC'
  | 'Mawani' | 'NEOM' | 'Emirates Global Aluminium' | 'Other';

interface GulfInvestment {
  id: string;
  investingEntity: GulfInvestingEntity;
  investingCountry: GulfInvestorCountry;
  targetCountry: string;
  targetCountryIso: string;
  sector: GulfInvestmentSector;
  assetType: string;
  assetName: string;
  lat: number;
  lon: number;
  investmentUSD?: number;
  stakePercent?: number;
  status: GulfInvestmentStatus;
  yearAnnounced?: number;
  yearOperational?: number;
  description: string;
  sourceUrl?: string;
  tags?: string[];
}

Economic Centers

type EconomicCenterType = 'exchange' | 'central-bank' | 'financial-hub';

interface EconomicCenter {
  id: string;
  name: string;
  type: EconomicCenterType;
  lat: number;
  lon: number;
  country: string;
  marketHours?: { open: string; close: string; timezone: string };
  description?: string;
}

8. Tech Variant Types

Specialized types for the Tech variant dashboard.

AI Data Centers

interface AIDataCenter {
  id: string;
  name: string;
  owner: string;
  country: string;
  lat: number;
  lon: number;
  status: 'existing' | 'planned' | 'decommissioned';
  chipType: string;
  chipCount: number;
  powerMW?: number;
  h100Equivalent?: number;
  sector?: string;
  note?: string;
}

AI Regulation

type RegulationType = 'comprehensive' | 'sectoral' | 'voluntary' | 'proposed';
type ComplianceStatus = 'active' | 'proposed' | 'draft' | 'superseded';
type RegulationStance = 'strict' | 'moderate' | 'permissive' | 'undefined';

interface AIRegulation {
  id: string;
  name: string;
  shortName: string;
  country: string;
  region?: string;
  type: RegulationType;
  status: ComplianceStatus;
  announcedDate: string;
  effectiveDate?: string;
  complianceDeadline?: string;
  scope: string[];
  keyProvisions: string[];
  penalties?: string;
  link?: string;
  description?: string;
}

interface RegulatoryAction {
  id: string;
  date: string;
  country: string;
  title: string;
  type: 'law-passed' | 'executive-order' | 'guideline' | 'enforcement' | 'consultation';
  regulationId?: string;
  description: string;
  impact: 'high' | 'medium' | 'low';
  source?: string;
}

Tech Companies & AI Research Labs

interface TechCompany {
  id: string;
  name: string;
  lat: number;
  lon: number;
  country: string;
  city?: string;
  sector?: string;
  officeType?: 'headquarters' | 'regional' | 'engineering' | 'research' | 'campus' | 'major office';
  employees?: number;
  foundedYear?: number;
  keyProducts?: string[];
  valuation?: number;
  stockSymbol?: string;
  description?: string;
}

interface AIResearchLab {
  id: string;
  name: string;
  lat: number;
  lon: number;
  country: string;
  city?: string;
  type: 'corporate' | 'academic' | 'government' | 'nonprofit' | 'industry' | 'research institute';
  parent?: string;
  focusAreas?: string[];
  description?: string;
  foundedYear?: number;
  notableWork?: string[];
  publications?: number;
  faculty?: number;
}

interface StartupEcosystem {
  id: string;
  name: string;
  lat: number;
  lon: number;
  country: string;
  city: string;
  ecosystemTier?: 'tier1' | 'tier2' | 'tier3' | 'emerging';
  totalFunding2024?: number;
  activeStartups?: number;
  unicorns?: number;
  topSectors?: string[];
  majorVCs?: string[];
  notableStartups?: string[];
  avgSeedRound?: number;
  avgSeriesA?: number;
  description?: string;
}

9. Panel & Map Configuration

PanelConfig

Per-panel toggle and priority for the variant system.

interface PanelConfig {
  name: string;
  enabled: boolean;
  priority?: number;
}

MapLayers

35+ boolean layer toggles that control which data overlays appear on the map.

interface MapLayers {
  // Geopolitical
  conflicts: boolean;
  bases: boolean;
  hotspots: boolean;
  military: boolean;
  sanctions: boolean;

  // Infrastructure
  cables: boolean;
  pipelines: boolean;
  nuclear: boolean;
  irradiators: boolean;
  datacenters: boolean;
  waterways: boolean;
  spaceports: boolean;
  minerals: boolean;

  // Security
  cyberThreats: boolean;
  outages: boolean;

  // Environmental
  weather: boolean;
  fires: boolean;
  natural: boolean;
  climate: boolean;

  // Tracking
  ais: boolean;
  flights: boolean;
  protests: boolean;

  // Economic
  economic: boolean;
  gulfInvestments: boolean;
  stockExchanges: boolean;
  financialCenters: boolean;
  centralBanks: boolean;
  commodityHubs: boolean;

  // Data sources
  ucdpEvents: boolean;
  displacement: boolean;

  // Tech variant
  startupHubs: boolean;
  cloudRegions: boolean;
  accelerators: boolean;
  techHQs: boolean;
  techEvents: boolean;
}

Monitor

User-defined keyword monitors that highlight matching news items.

interface Monitor {
  id: string;
  keywords: string[];
  color: string;
  name?: string;
  lat?: number;
  lon?: number;
}

10. Application State

Top-level application state holding all active data and UI configuration.

interface AppState {
  currentView: 'global' | 'us';
  mapZoom: number;
  mapPan: { x: number; y: number };
  mapLayers: MapLayers;
  panels: Record<string, PanelConfig>;
  monitors: Monitor[];
  allNews: NewsItem[];
  isLoading: boolean;
}

11. Focal Points

Intelligence synthesis layer that detects entities (countries, companies) with converging news and signal activity.

type FocalPointUrgency = 'watch' | 'elevated' | 'critical';

interface HeadlineWithUrl {
  title: string;
  url: string;
}

interface EntityMention {
  entityId: string;
  entityType: 'country' | 'company' | 'index' | 'commodity' | 'crypto' | 'sector';
  displayName: string;
  mentionCount: number;
  avgConfidence: number;
  clusterIds: string[];
  topHeadlines: HeadlineWithUrl[];
}

interface FocalPoint {
  id: string;
  entityId: string;
  entityType: 'country' | 'company' | 'index' | 'commodity' | 'crypto' | 'sector';
  displayName: string;

  // News dimension
  newsMentions: number;
  newsVelocity: number;
  topHeadlines: HeadlineWithUrl[];

  // Signal dimension
  signalTypes: string[];
  signalCount: number;
  highSeverityCount: number;
  signalDescriptions: string[];

  // Scoring
  focalScore: number;
  urgency: FocalPointUrgency;

  // AI context
  narrative: string;
  correlationEvidence: string[];
}

interface FocalPointSummary {
  timestamp: Date;
  focalPoints: FocalPoint[];
  aiContext: string;
  topCountries: FocalPoint[];
  topCompanies: FocalPoint[];
}

12. Social Unrest

SocialUnrestEvent

Individual protest, riot, or civil unrest event sourced from ACLED, GDELT, or RSS feeds.

type ProtestSeverity = 'low' | 'medium' | 'high';
type ProtestSource = 'acled' | 'gdelt' | 'rss';
type ProtestEventType = 'protest' | 'riot' | 'strike' | 'demonstration' | 'civil_unrest';

interface SocialUnrestEvent {
  id: string;
  title: string;
  summary?: string;
  eventType: ProtestEventType;
  city?: string;
  country: string;
  region?: string;
  lat: number;
  lon: number;
  time: Date;
  severity: ProtestSeverity;
  fatalities?: number;
  sources: string[];
  sourceType: ProtestSource;
  tags?: string[];
  actors?: string[];
  relatedHotspots?: string[];
  confidence: 'high' | 'medium' | 'low';
  validated: boolean;
  imageUrl?: string;
  sentiment?: 'angry' | 'peaceful' | 'mixed';
}

ProtestCluster

Geographically grouped protest events.

interface ProtestCluster {
  id: string;
  country: string;
  region?: string;
  eventCount: number;
  events: SocialUnrestEvent[];
  severity: ProtestSeverity;
  startDate: Date;
  endDate: Date;
  primaryCause?: string;
}

Map Cluster Types

Compact cluster representations used for map rendering (protest, tech HQ, datacenter, tech event).

interface MapProtestCluster {
  id: string;
  lat: number;
  lon: number;
  count: number;
  items: SocialUnrestEvent[];
  country: string;
  maxSeverity: 'low' | 'medium' | 'high';
  hasRiot: boolean;
  totalFatalities: number;
  riotCount?: number;
  highSeverityCount?: number;
  verifiedCount?: number;
  sampled?: boolean;
}

interface MapDatacenterCluster {
  id: string;
  lat: number;
  lon: number;
  count: number;
  items: AIDataCenter[];
  region: string;
  country: string;
  totalChips: number;
  totalPowerMW: number;
  majorityExisting: boolean;
  sampled?: boolean;
}

13. Entity Model

Source: src/config/entities.ts (636 lines)

The entity system provides a registry of 600+ real-world entities (companies, indices, commodities, countries, crypto assets) used for news-to-asset linking.

Core Types

type EntityType = 'company' | 'index' | 'commodity' | 'crypto' | 'sector' | 'country';

interface EntityEntry {
  id: string;              // Ticker symbol or code (e.g., "AAPL", "^GSPC", "BTC")
  type: EntityType;
  name: string;            // Display name (e.g., "Apple Inc.")
  aliases: string[];       // All recognized names/abbreviations
  keywords: string[];      // Contextual keywords for matching
  sector?: string;         // Sector classification (e.g., "Technology")
  related?: string[];      // Entity IDs of related entities
}

EntityIndex

Multi-index lookup structure built from ENTITY_REGISTRY. Defined in src/services/entity-index.ts.

interface EntityIndex {
  byId: Map<string, EntityEntry>;        // Direct lookup by entity ID
  byAlias: Map<string, string>;          // alias → entity ID (lowercased)
  byKeyword: Map<string, Set<string>>;   // keyword → set of entity IDs
  bySector: Map<string, Set<string>>;    // sector → set of entity IDs
  byType: Map<string, Set<string>>;      // entity type → set of entity IDs
}

Lookup functions:

Function Signature Description
buildEntityIndex() (entities: EntityEntry[]) → EntityIndex Build all index maps
getEntityIndex() () → EntityIndex Singleton accessor (lazy build)
lookupEntityByAlias() (alias: string) → EntityEntry | undefined Find entity by any alias
lookupEntitiesByKeyword() (keyword: string) → EntityEntry[] Find all entities matching keyword
lookupEntitiesBySector() (sector: string) → EntityEntry[] Find all entities in a sector
findRelatedEntities() (entityId: string) → EntityEntry[] Get related entities
findEntitiesInText() (text: string) → EntityMatch[] NLP-style entity extraction from text

EntityMatch

Result of text-based entity extraction.

interface EntityMatch {
  entityId: string;
  matchedText: string;
  matchType: 'alias' | 'keyword' | 'name';
  confidence: number;
  position: number;
}

14. News Item Lifecycle

flowchart LR
    A[RSS Feed] --> B[Parsed NewsItem]
    B --> C{Clustering}
    C -->|Jaccard only| D[clusterNews]
    C -->|Jaccard + semantic| E[clusterNewsHybrid]
    D --> F[ClusteredEvent]
    E --> F
    F --> G[Threat Classification]
    G --> H[Entity Extraction]
    H --> I[Severity & Velocity Scoring]
    I --> J[Panel Display]

Stages:

  1. Ingest — RSS feeds polled at REFRESH_INTERVALS.feeds (5 min). Raw XML parsed into NewsItem objects.
  2. Cluster — Duplicate/related stories merged via two strategies:
    • clusterNews() — Jaccard similarity on tokenized titles. Fast, no ML dependency.
    • clusterNewsHybrid() — Jaccard + ML-based semantic similarity via Web Worker embedding model (cosine similarity). Produces higher-quality merges.
  3. Classify — Threat classifier assigns ThreatClassification with category and severity level.
  4. Entity extractionfindEntitiesInText() matches aliases/keywords from ENTITY_REGISTRY against titles.
  5. ScoreVelocityMetrics computed (sources/hour, acceleration). Sentiment scored.
  6. Display — Final ClusteredEvent rendered in news panels with velocity badges, threat indicators, and entity links.

15. Signal Model

Source: src/services/signal-aggregator.ts (495 lines)

The signal aggregator collects all map-layer signals and correlates them by country/region to feed the AI Insights engine.

Signal Types

type SignalType =
  | 'internet_outage'
  | 'military_flight'
  | 'military_vessel'
  | 'protest'
  | 'ais_disruption'
  | 'satellite_fire'        // NASA FIRMS thermal anomalies
  | 'temporal_anomaly';     // Baseline deviation alerts

Signal Pipeline

flowchart TD
    S1[Internet Outages] --> GS[GeoSignal]
    S2[Military Flights] --> GS
    S3[Military Vessels] --> GS
    S4[Protests] --> GS
    S5[AIS Disruptions] --> GS
    S6[Satellite Fires] --> GS
    S7[Temporal Anomalies] --> GS
    GS --> CSC[CountrySignalCluster]
    CSC --> RC[RegionalConvergence]
    RC --> SS[SignalSummary]
    SS --> AI[AI Insights Context]

Core Signal Types

interface GeoSignal {
  type: SignalType;
  country: string;
  countryName: string;
  lat: number;
  lon: number;
  severity: 'low' | 'medium' | 'high';
  title: string;
  timestamp: Date;
}

interface CountrySignalCluster {
  country: string;
  countryName: string;
  signals: GeoSignal[];
  signalTypes: Set<SignalType>;
  totalCount: number;
  highSeverityCount: number;
  convergenceScore: number;
}

interface RegionalConvergence {
  region: string;
  countries: string[];
  signalTypes: SignalType[];
  totalSignals: number;
  description: string;
}

interface SignalSummary {
  timestamp: Date;
  totalSignals: number;
  byType: Record<SignalType, number>;
  convergenceZones: RegionalConvergence[];
  topCountries: CountrySignalCluster[];
  aiContext: string;          // Pre-formatted text for LLM prompts
}

Region Definitions

Six monitored regions with their constituent country codes:

Region Countries
Middle East IR, IL, SA, AE, IQ, SY, YE, JO, LB, KW, QA, OM, BH
East Asia CN, TW, JP, KR, KP, HK, MN
South Asia IN, PK, BD, AF, NP, LK, MM
Eastern Europe UA, RU, BY, PL, RO, MD, HU, CZ, SK, BG
North Africa EG, LY, DZ, TN, MA, SD, SS
Sahel ML, NE, BF, TD, NG, CM, CF

16. Map Data Models

The map renders 35+ toggleable layers. Each layer is controlled by a boolean in MapLayers.

Layer Keys

Defined in src/utils/urlState.ts, the LAYER_KEYS array lists all URL-serializable layer identifiers:

const LAYER_KEYS: (keyof MapLayers)[] = [
  'conflicts', 'bases', 'cables', 'pipelines', 'hotspots', 'ais',
  'nuclear', 'irradiators', 'sanctions', 'weather', 'economic',
  'waterways', 'outages', 'cyberThreats', 'datacenters', 'protests',
  'flights', 'military', 'natural', 'spaceports', 'minerals', 'fires',
  'ucdpEvents', 'displacement', 'climate',
  'startupHubs', 'cloudRegions', 'accelerators', 'techHQs', 'techEvents',
];

Layer → Data Type Mapping

Layer Data Interface Source
conflicts ConflictZone Static config + UCDP
bases MilitaryBase Static config
cables UnderseaCable Static config
pipelines Pipeline Static config
hotspots Hotspot Static config + dynamic escalation
ais AisDisruptionEvent, AisDensityZone API
nuclear NuclearFacility Static config
flights MilitaryFlight OpenSky / Wingbits
military MilitaryVessel AIS data
protests MapProtestCluster ACLED / GDELT
fires FIRMS data NASA FIRMS API
cyberThreats CyberThreat Multi-source threat feeds
outages InternetOutage Cloudflare / IODA
datacenters MapDatacenterCluster Static config
ucdpEvents UcdpGeoEvent UCDP API
displacement CountryDisplacement UNHCR API
climate ClimateAnomaly Open-Meteo / ERA5
natural NaturalEvent NASA EONET
economic EconomicCenter Static config
gulfInvestments GulfInvestment Static config

17. Panel State Model

Source: src/components/Panel.ts

PanelOptions

Constructor options for creating a panel widget.

interface PanelOptions {
  id: string;
  title: string;
  showCount?: boolean;
  className?: string;
  trackActivity?: boolean;
  infoTooltip?: string;
}

Panel Persistence

Panels persist their size and ordering in localStorage:

Key Constant Value Schema
worldmonitor-panel-spans PANEL_SPANS_KEY Record<string, number> — panel ID → grid span (14)
panel-order PANEL_ORDER_KEY string[] — ordered panel IDs

Span/Resize Logic

heightToSpan(height: number) → number converts a pixel height to a grid span:

Pixel Height Grid Span
< 250px 1
250349px 2
350499px 3
≥ 500px 4

Functions: loadPanelSpans() reads from localStorage, savePanelSpan(panelId, span) writes back.


18. Variant Configuration

Source: src/config/variants/base.ts

The variant system supports multiple dashboard configurations (full, tech, finance) via an override chain.

VariantConfig

interface VariantConfig {
  name: string;
  description: string;
  panels: Record<string, PanelConfig>;
  mapLayers: MapLayers;
  mobileMapLayers: MapLayers;
}

Shared Constants

const API_URLS = {
  finnhub: (symbols: string[]) => `/api/finnhub?symbols=...`,
  yahooFinance: (symbol: string) => `/api/yahoo-finance?symbol=...`,
  coingecko: '/api/coingecko?...',
  polymarket: '/api/polymarket?...',
  earthquakes: '/api/earthquakes',
  arxiv: (category, maxResults) => `/api/arxiv?...`,
  githubTrending: (language, since) => `/api/github-trending?...`,
  hackernews: (type, limit) => `/api/hackernews?...`,
};

const REFRESH_INTERVALS = {
  feeds:           5 * 60 * 1000,   // 5 min
  markets:         2 * 60 * 1000,   // 2 min
  crypto:          2 * 60 * 1000,   // 2 min
  predictions:     5 * 60 * 1000,   // 5 min
  ais:            10 * 60 * 1000,   // 10 min
  arxiv:          60 * 60 * 1000,   // 1 hr
  githubTrending: 30 * 60 * 1000,   // 30 min
  hackernews:      5 * 60 * 1000,   // 5 min
};

const STORAGE_KEYS = {
  panels:        'worldmonitor-panels',
  monitors:      'worldmonitor-monitors',
  mapLayers:     'worldmonitor-layers',
  disabledFeeds: 'worldmonitor-disabled-feeds',
} as const;

Override Chain

base.ts (defaults) → full.ts / tech.ts / finance.ts (overrides)

Each variant file imports from base.ts and selectively overrides panels, mapLayers, and mobileMapLayers to tailor the dashboard for its domain.


19. Risk Scoring Models

Country Instability Index (CII)

Source: src/services/country-instability.ts (703 lines)

Computes a real-time instability score per country from four components.

interface CountryScore {
  code: string;
  name: string;
  score: number;
  level: 'low' | 'normal' | 'elevated' | 'high' | 'critical';
  trend: 'rising' | 'stable' | 'falling';
  change24h: number;
  components: ComponentScores;
  lastUpdated: Date;
}

interface ComponentScores {
  unrest: number;       // Protests, riots, civil unrest
  conflict: number;     // Armed conflict, UCDP events
  security: number;     // Military activity, internet outages
  information: number;  // News volume, velocity
}

Learning mode: 15-minute warmup period during which scores are unreliable. Bypassed when cached scores are available from the backend (setHasCachedScores(true)).

Input data per country: SocialUnrestEvent[], ConflictEvent[], UcdpConflictStatus, HapiConflictSummary, MilitaryFlight[], MilitaryVessel[], ClusteredEvent[], InternetOutage[], displacement outflow, climate stress.

Cached Risk Scores

Source: src/services/cached-risk-scores.ts

Pre-computed scores fetched from the backend to eliminate the learning mode delay.

interface CachedCIIScore {
  code: string;
  name: string;
  score: number;
  level: 'low' | 'normal' | 'elevated' | 'high' | 'critical';
  trend: 'rising' | 'stable' | 'falling';
  change24h: number;
  components: ComponentScores;
  lastUpdated: string;
}

interface CachedStrategicRisk {
  score: number;
  level: string;
  trend: string;
  lastUpdated: string;
  contributors: Array<{
    country: string;
    code: string;
    score: number;
    level: string;
  }>;
}

interface CachedRiskScores {
  cii: CachedCIIScore[];
  strategicRisk: CachedStrategicRisk;
  protestCount: number;
  computedAt: string;
  cached: boolean;
}

Hotspot Escalation

Source: src/services/hotspot-escalation.ts (349 lines)

Combines a static baseline with four dynamic components to produce a real-time escalation score per hotspot.

Component weights:

Component Weight Description
newsActivity 0.35 Keyword matches, breaking news, velocity
ciiContribution 0.25 Country instability score for hotspot's country
geoConvergence 0.25 Nearby geospatial signal density
militaryActivity 0.15 Military flights/vessels within radius

Constraints:

  • 24-hour history window, maximum 48 history points
  • 2-hour signal cooldown between updates per hotspot
  • Static baseline from Hotspot.escalationScore (default: 3)

20. Cache & Storage Schemas

Upstash Redis (Server-side)

Source: api/_upstash-cache.js

  • TTL-based expiration per endpoint
  • In sidecar mode: in-memory Map with max 5,000 entries, disk-persisted to api-cache.json

IndexedDB (Client-side)

Source: src/services/storage.ts (230 lines)

Database: worldmonitor_db, version 1.

Store: baselines

Rolling window statistics for temporal anomaly detection.

// keyPath: 'key'
interface BaselineEntry {
  key: string;
  counts: number[];      // Historical count values
  timestamps: number[];  // Corresponding timestamps (ms)
  avg7d: number;         // 7-day rolling average
  avg30d: number;        // 30-day rolling average
  lastUpdated: number;   // Timestamp (ms)
}

Deviation calculation:

function calculateDeviation(current: number, baseline: BaselineEntry): {
  zScore: number;
  percentChange: number;
  level: 'normal' | 'elevated' | 'spike' | 'quiet';
}
z-score Level
> 2.5 spike
> 1.5 elevated
< 2.0 quiet
otherwise normal

Store: snapshots

Periodic dashboard state captures for historical comparison.

// keyPath: 'timestamp', index: 'by_time'
interface DashboardSnapshot {
  timestamp: number;
  events: unknown[];
  marketPrices: Record<string, number>;
  predictions: Array<{ title: string; yesPrice: number }>;
  hotspotLevels: Record<string, string>;
}

Retention: 7 days. Cleaned via cleanOldSnapshots().

Persistent Cache (Client-side)

Source: src/services/persistent-cache.ts

Cross-runtime cache with Tauri invoke → localStorage fallback.

type CacheEnvelope<T> = {
  key: string;
  updatedAt: number;
  data: T;
};
  • Key prefix: worldmonitor-persistent-cache:
  • Desktop runtime: Tauri read_cache_entry / write_cache_entry commands
  • Web runtime: localStorage fallback
  • Helper: describeFreshness(updatedAt)"just now" | "5m ago" | "2h ago" | "1d ago"

Relationship Overview

erDiagram
    Feed ||--o{ NewsItem : "parsed into"
    NewsItem }o--|| ClusteredEvent : "clustered into"
    ClusteredEvent ||--o| VelocityMetrics : "scored with"
    ClusteredEvent ||--o| ThreatClassification : "classified as"
    ClusteredEvent }o--o{ EntityEntry : "mentions"

    Hotspot ||--|| DynamicEscalationScore : "scored by"
    DynamicEscalationScore }o--|| CountryScore : "uses CII from"

    GeoSignal }o--|| CountrySignalCluster : "grouped into"
    CountrySignalCluster }o--|| RegionalConvergence : "aggregated into"
    RegionalConvergence }o--|| SignalSummary : "summarized in"

    FocalPoint }o--|| EntityEntry : "references"
    FocalPoint }o--|| SignalSummary : "correlated with"

    InfrastructureNode }o--o{ DependencyEdge : "connected by"
    DependencyEdge }o--|| CascadeResult : "produces"

    CountryScore }o--|| CachedRiskScores : "cached in"
    BaselineEntry }o--|| DashboardSnapshot : "compared against"