Skip to content

saroshfarhan/Project-Voyage

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Project Voyage

Real-time logistics intelligence platform. Tracks ships and aircraft across the globe, scores route risk using geopolitical, weather, and disaster signals, and surfaces everything in a Palantir-grade dark UI — with a route planner that finds the optimal cargo path between any two cities on Earth.

Built for the mission: life-saving drugs and critical cargo must reach their destination even when wars, disasters, and sanctions disrupt normal logistics.

Route Planning taking geo-politics and natural disasters into consideration

alt text

Different mode commonly cargo flights and cargo vessels with realtime vessel positions

alt text

Risk Modeling to showcase common routes with risks

alt text


Quick Start

git clone <repo-url> && cd project-voyage
make up          # builds images, runs tests, starts everything

Everything runs in Docker. You don't need Python or Node installed locally.

Service URL
Frontend (Next.js) http://localhost:3000
API (REST + WebSocket) http://localhost:8000
API docs (OpenAPI) http://localhost:8000/docs
Redpanda Console (Kafka UI) http://localhost:8080
MLflow http://localhost:5001
Grafana http://localhost:3001admin / voyage
Prometheus http://localhost:9090
make reset && make up    # wipe all data and start fresh
make test                # unit tests (no Docker needed) — currently 281 passing, 89% coverage
make logs-api            # tail API logs
make shell-db            # open psql

What It Does

Route Planner

Enter any two cities, ports, or countries. The planner:

  • Resolves every country name to its nearest major cargo port (e.g. "China" from LA → Shanghai; "USA" from Rotterdam → New York)
  • Generates 3 route variants depending on cargo priority:
    • HIGH (pharma/medicine): Air Express + Safest Sea + Standard Sea
    • MEDIUM/LOW: Safest Sea + Fastest Sea + Cheapest Sea
  • Scores each route against live geopolitical events (GDELT, HAPI), weather, earthquakes (USGS), and natural disasters (NASA EONET)
  • Automatically reroutes around the Red Sea via Cape of Good Hope when conflict severity ≥ 0.6
  • Routes follow real-world shipping lanes using a maritime routing graph (prebuilt from IMO/UNCTAD data) — routes are guaranteed to stay in navigable water, correctly threading through the Strait of Hormuz, Malacca, Suez, Panama, and every other major chokepoint
  • Fallback corridor system with Catmull-Rom spline smoothing and antimeridian handling for Cape-of-Good-Hope reroutes

Live Tracking

  • Vessel positions via AISstream.io WebSocket — updated continuously
  • Flight positions via OpenSky Network — polled every 60s
  • Real-time overlay via Redis pub/sub → WebSocket /ws/live

Risk Intelligence

  • 876+ geopolitical events in the DB (GDELT conflict, HAPI displacement, USGS earthquakes M4.5+, EONET cyclones/floods/wildfires)
  • Each route gets a composite risk score from DB bounding-box queries against all event types
  • Risk level: low / medium / high / critical

Architecture

EXTERNAL DATA SOURCES
────────────────────────────────────────────────────────────────────────
AISstream.io        OpenSky Network     Open-Meteo          GDELT Project
(vessel AIS)        (flights)           (weather)           (geopolitical)

USGS Earthquake     NASA EONET          HAPI (UN)           NewsAPI / ACLED
(earthquakes)       (disasters)         (humanitarian)      (optional)

        │ WebSocket / REST / polling
        ▼
INGESTION LAYER  (Python ARQ workers + Kafka consumers)
────────────────────────────────────────────────────────────────────────
[AIS Worker]   [Flight Worker]   [Weather Worker]   [OSINT Workers]
    │               │                  │            GDELT · HAPI · USGS · EONET
    └───────────────┴──────────────────┴─────────────────────┐
                                                              ▼
                                              REDPANDA (Kafka-compatible)
                                              vessel_positions · flight_positions
                                              weather_events  · osint_events
                                                              │
                                          ┌───────────────────┤
                                          ▼                   ▼
                                    DB WRITERS           ARQ WORKERS
                                    (consumers)          (cron jobs)
                                          │
                                          ▼
                          PostgreSQL 16 + TimescaleDB + PostGIS
                          ─────────────────────────────────────
                          vessel_positions   (hypertable, 7d retention)
                          flight_positions   (hypertable, 7d retention)
                          weather_snapshots  (hypertable, 30d retention)
                          geopolitical_events(hypertable, 90d retention)
                                          │
                              ┌───────────┴────────────┐
                              ▼                        ▼
                    FASTAPI REST API             REDIS pub/sub
                    ─────────────────           ────────────────
                    /api/v1/vessels             voyage:live:*
                    /api/v1/flights                   │
                    /api/v1/routes/plan               ▼
                    /api/v1/routes/risk          WS /ws/live
                    /api/v1/routes/eta
                              │
                              ▼
                    NEXT.JS 14 FRONTEND
                    ─────────────────────────────────────────────
                    deck.gl PathLayer  (route arcs, vessel dots)
                    Catmull-Rom splines (smooth geodesic curves)
                    Zustand + React Query
                    shadcn/ui dark theme

Architecture Decisions

# Decision Choice Why
001 Database PostgreSQL + TimescaleDB + PostGIS One engine: time-series + geospatial + relational
002 Message Queue Redpanda Kafka API, no JVM, single binary
003 Cache + Pub/Sub Redis WebSocket fan-out across API replicas
004 Task Queue ARQ asyncio-native, pairs perfectly with FastAPI
005 Package Manager uv 100× faster than pip, unified lockfile
006 Backend FastAPI Async, auto OpenAPI docs, native WebSocket
007 ML Separate FastAPI microservice Heavy deps isolated, independent scaling
008 Map deck.gl + MapLibre WebGL — renders 500k+ points at 60fps
009 Real-time WebSocket over SSE Bidirectional filter commands from browser
010 Frontend State Zustand + React Query Lightweight, no Redux boilerplate
011 UI shadcn/ui + Tailwind Copy-paste ownership, full dark theme
012 Containers Docker Compose → K8s Local free, prod portable via Helm
013 CI/CD GitHub Actions PR tests + image build + deploy
014 Monitoring Prometheus + Grafana + Sentry Metrics, dashboards, error tracking

Route Planning API

POST /api/v1/routes/plan
Content-Type: application/json
X-API-Key: <key>

{
  "origin":            "Oman",
  "destination":       "China",
  "priority":          "high",        // "high" | "medium" | "low"
  "cargo_weight_tons": 10.0,
  "cargo_description": "Vaccines"     // optional
}

Response includes:

  • origin_coords / destination_coords — resolved to nearest major cargo port
  • routes[] — 3 route objects, each with:
    • waypoints — dense [[lon, lat], ...] Catmull-Rom spline (ready for deck.gl PathLayer)
    • distance_km, eta_days, cost_usd, risk_score, risk_level
    • carriers[] — top 3 carrier quotes sorted by price
    • via[] — human-readable chokepoint labels (Suez Canal, Singapore Strait…)
    • risk_factors[] — per-factor breakdown (conflict, weather, earthquake…)

All API Endpoints

Vessels

GET /api/v1/vessels/?limit=500               Latest position per vessel
GET /api/v1/vessels/{mmsi}                   Single vessel
GET /api/v1/vessels/{mmsi}/track?hours=24    Position history

Flights

GET /api/v1/flights/?limit=500&airborne_only=false   Latest state vectors
GET /api/v1/flights/{icao24}                          Single aircraft

Routes

POST /api/v1/routes/plan                Route planner (see above)
GET  /api/v1/routes/risk                Route risk score (ML microservice proxy)
GET  /api/v1/routes/eta                 ETA estimate (ML microservice proxy)

System

GET /health                  Liveness probe
GET /ready                   Readiness probe
GET /api/v1/health/freshness Data freshness (last ingest timestamp per source)

WebSocket

WS /ws/live          Real-time vessel + flight position stream

Send to filter:
  {"type": "vessel"}    vessel updates only
  {"type": "flight"}    flight updates only
  {"type": "all"}       everything (default)

Vessel message: { type, mmsi, vessel_name, lat, lon, speed, heading, ts }
Flight message: { type, icao24, callsign, lat, lon, altitude, heading, velocity, ts }

Data Sources (All Free)

Type Source Update interval Key needed
Vessel AIS AISstream.io WebSocket Continuous AISSTREAM_API_KEY (optional, mocks if blank)
Flights OpenSky Network REST Every 60s None
Weather Open-Meteo Every hour None
Geopolitical events GDELT Project Every 15 min None
Humanitarian data UN OCHA HAPI Every 6 hr None
Earthquakes M4.5+ USGS GeoJSON feed Every 6 hr None
Natural disasters NASA EONET Every 6 hr None
Armed conflict ACLED API Every 6 hr ACLED_API_KEY (optional)
News signals NewsAPI On demand NEWSAPI_KEY (optional)

Environment Variables

cp .env.example .env
Variable Required Default Description
API_KEY changeme-... Protects all API endpoints via X-API-Key header
DATABASE_URL auto set by compose asyncpg connection string
REDIS_URL auto set by compose Redis connection string
KAFKA_BOOTSTRAP_SERVERS auto set by compose Redpanda broker address
AISSTREAM_API_KEY optional Real vessel AIS data; falls back to 10 mock vessels on major shipping lanes
ACLED_API_KEY optional Armed conflict data (free registration at acleddata.com)
NEWSAPI_KEY optional News signal enrichment (100 req/day free)
ML_SERVICE_URL auto set by compose Internal URL of the ML microservice

Development

Prerequisites

First time setup

make install   # creates backend/.venv for IDE support + local test runs
make up        # starts the full stack

Running tests

make test              # 281 unit tests, no Docker needed (~0.6s)
make test-cov          # with HTML coverage report
make check             # lint + type-check + tests (same as CI)
make test-integration  # requires infra running (make infra first)

Project layout

project-voyage/
├── backend/
│   ├── app/
│   │   ├── api/v1/endpoints/     # REST handlers: vessels, flights, routes, health
│   │   ├── core/                 # config, database, redis, security, logging
│   │   ├── models/               # SQLAlchemy ORM (TimescaleDB hypertables)
│   │   ├── schemas/              # Pydantic v2 schemas (route_plan, vessel, flight)
│   │   ├── services/             # Business logic
│   │   │   └── route_planner.py  # Corridor templates, Catmull-Rom smoothing,
│   │   │                         # port resolution, risk scoring, carrier quotes
│   │   └── workers/              # ARQ cron jobs + startup tasks
│   ├── ingestion/
│   │   ├── ais/                  # AISstream.io WebSocket vessel worker
│   │   ├── flights/              # OpenSky flight worker
│   │   ├── weather/              # Open-Meteo weather worker
│   │   ├── osint/                # GDELT · HAPI · USGS · EONET workers
│   │   └── consumers/            # Kafka → TimescaleDB writers
│   ├── migrations/               # Alembic migration files
│   └── tests/
│       ├── unit/                 # 281 fast tests, no DB or network required
│       └── integration/          # Tests against live Docker services
├── frontend/
│   └── src/
│       ├── app/                  # Next.js 14 App Router pages
│       ├── components/
│       │   ├── map/              # VoyageMap (deck.gl), EntityTooltip
│       │   └── panels/           # RoutePlannerPanel, VesselPanel, FlightPanel, RiskPanel
│       ├── hooks/                # useVessels, useFlights, useWebSocket
│       ├── stores/               # Zustand: mapStore, liveStore, routeStore
│       └── types/                # TypeScript interfaces (route, vessel, flight)
├── infra/
│   ├── docker/                   # docker-compose.yml, Dockerfiles, entrypoints
│   ├── k8s/                      # Kubernetes manifests (base + kustomize overlays)
│   └── terraform/                # AWS Fargate (demo) + EKS (prod) modules
└── .github/workflows/            # CI: lint → type-check → test → build → deploy

Phase Status

Phase Description Status
0 Repo scaffold, Docker Compose, CI/CD, DB migrations, monitoring ✅ Complete
1 Real data ingestion — AIS vessels, flights, weather, GDELT/HAPI/USGS/EONET ✅ Complete
2 Route Planner — geodesic routing, risk scoring, carrier quotes, smooth map arcs ✅ Complete
3 ML microservice — route risk model v2, ETA forecasting, anomaly detection 🔲 Next
4 Testing hardening, performance tuning, tech debt 🔲 Planned
5 AI intelligence layer — LLM route explanations, natural language alerts 🔲 Planned

Cloud Deployment

# Spin up a demo on AWS ECS Fargate (~$5–15 for a session)
cd infra/terraform/aws
terraform init && terraform apply -var-file=fargate.tfvars

# Tear down after the demo
terraform destroy -var-file=fargate.tfvars

Production uses EKS (AWS) or GKE (GCP) with Helm — same Docker images, portable manifests.


Tech Stack

Backend:    Python 3.12 · uv · FastAPI · SQLAlchemy 2 · Alembic · Pydantic v2 · ARQ · searoute
Database:   PostgreSQL 16 · TimescaleDB · PostGIS
Streaming:  Redpanda (Kafka API, no JVM)
Cache:      Redis 7
ML:         scikit-learn · XGBoost · Prophet · Polars · MLflow · ONNX
Frontend:   Next.js 14 · TypeScript · Tailwind · shadcn/ui · deck.gl · Zustand · React Query
Infra:      Docker Compose · Kubernetes · Helm · Terraform (AWS + GCP)
CI/CD:      GitHub Actions (lint → type-check → test → build → deploy)
Monitoring: Prometheus · Grafana · Sentry · Loki