Skip to content

About

AI-assisted predictive logistics and forward supply chain decision-support platform for SIH 2026 Problem Statement 26251.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

20 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Predictive Logistics & Forward Supply Chain — SIH · PS 26251

Illustrative scenario: fictional locations and simulated telemetry, not operational records. Decision support only.

All depots, forward locations, routes, vehicles, terrain, weather, consumption and sensor telemetry in this repository are fictional and generated by a seeded script. Nothing here represents real Army data, real bases, real operational routes, troop/unit positions, deployments or real sensors, and this is not production military software. Every recommendation is a decision-support output computed from a simulated scenario; final decisions rest with authorised personnel.

The machine-learning components were trained on ISOMORPH, a simulator-generated research benchmark (CC-BY-4.0) - see ml/. Benchmark scores are not evidence of accuracy on real operations.

Full-stack upgrade of the original v3 HTML version (not shipped in V7; its calculations are pinned by backend/tests/golden_v3.json) into React + Vite + TypeScript + Tailwind · FastAPI + Pydantic + SQLAlchemy · PostgreSQL + PostGIS · Docker Compose, with a simulated ESP32/RFID layer.


1. Problem statement (PS 26251)

Indian Army – Predictive Logistics & Forward Supply Chain. Forward locations in difficult terrain are resupplied over long, weather-exposed routes. Planners need to predict consumption, see shortages before they happen, decide what to send first, and pick routes and vehicles that can actually deliver — and to understand why a location is at risk.

SIH 2026 Context & Historical Evidence: Developed for Smart India Hackathon (SIH) Problem Statement 26251. The original prototype UI demonstrations, dark/light interface captures, and legacy artifacts are preserved for historical continuity:

2. Solution overview

Need What the system does
Predict demand Weather-aware statistical forecast (default) or a trained LightGBM model (opt-in / promotion-gated), per location × supply, 7/14/30-day horizons, 80 % interval, backtest MAPE, confidence, per-row model attribution; Random Forest cross-check
See shortages early Days-of-supply, 14-day predicted shortage, stock-out date, GREEN/YELLOW/RED (NORMAL/WARNING/CRITICAL) classification, explainable "Why at risk"
Decide what first Supply priority queue (score 0–100) from shortage, stock deficit, criticality, lead time, route feasibility, transport capacity
Decide how Route optimisation (distance, ETA, vehicle capacity, road, weather, terrain) with alternatives and a stated reason; allocation within real depot stock and vehicle capacity
Test resilience What-If simulation: demand, weather, road, vehicle availability → before/after metrics + explanations
Near-real-time inventory Simulated ESP32/RFID events → FastAPI → PostgreSQL → inventory, alerts, priority, allocation, dashboard

UI/UX highlights (presentation only — engines, API contracts, schema and tests untouched)

  • Dark / Light theme — Dark is the default; the sidebar switch (keyboard-accessible, role="switch") persists the choice in localStorage and applies it before first paint. Light-theme text colours are darkened so sampled text pairs measure ≥ 4.5:1 (WCAG AA) in both themes, while GREEN / YELLOW(amber) / RED keep their meaning (status is also always written out: CRITICAL / WARNING / NORMAL).
  • Command Dashboard opens with a Command Briefing: overall risk gauge, critical locations, predicted shortages, transport capacity vs need, active alerts and the top 3 recommended actions, followed by "Why this recommendation?" (stock-out horizon, shortage, lead time, criticality, route risk, vehicle/dispatch, and the weighted score breakdown for any of the top priorities).
  • GIS shows source → destination direction arrows, the selected route (thick, labelled) vs alternatives (dotted, labelled), SOURCE / DESTINATION tags, and a Route Selection Explained panel with a per-alternative "why not" (score / risk / ETA / capacity deltas).
  • Forecast separates the active model (statistical by default; trained model when promoted or opted in), the trained-model preview / Random Forest cross-check (never feed decisions), the validation metrics and the confidence, and states plainly what is and is not AI.
  • What-If adds a concise Recommended Response derived from the backend's simulation result plus the scenario's own /api/priority and /api/allocation.
  • IoT shows the flow Telemetry → Database → Inventory/Risk impact for the latest simulated scan (stock before/after, iot_events id, status, critical-item count and risk index before/after).
  • The header now reads SIMULATION TIME · 19 JUN 2026 and DATA · ILLUSTRATIVE SCENARIO (date-level only; hover: fictional clock anchored at 2026-06-19, 60×, not real time). The underlying simulation clock is unchanged.

V4 polish pass (presentation only — backend/, engines, forecasting/routing/allocation logic, schema and API contracts untouched)

  • Confidence Index — forecast confidence is shown as Confidence Index: 99/100 — HIGH with an info tooltip: heuristic confidence index derived from historical backtest error; not a probability of forecast correctness. The backend value/label/formula are unchanged.
  • System Decision Flow strip at the top of the Command Dashboard: DATA → FORECAST → RISK → PRIORITY → ALLOCATION → ROUTE → DECISION, each step showing an existing backend figure (records, units short, risk index, top priority, allocated/need, top route) and ending in human decision support.
  • Why this recommendation? gains a Recommendation · decision support banner naming source depot → destination via route (from the allocation legs) and stating it is advisory, not an autonomous command.
  • Why this route? heading plus Total route risk and Alternatives tiles in the GIS route explanation.
  • IoT value flow: ESP32 / RFID TELEMETRY → API → PostgreSQL → INVENTORY / RISK → DECISION SUPPORT, stating that all telemetry is simulated and no hardware is required.
  • Recommended Response adds a route-risk line (only when the backend's mean route risk rose), a fleet-availability line (only when vehicles < 100% and capacity still suffices) and a note to use APPLY TO ALL SCREENS to rerun allocation; every line is derived from the simulation result.
  • The recommendation engine is labelled RULE-BASED — not machine learning, not an LLM wherever it appears. (The legacy card name “AI Logistics Insight” is kept as a substring because the pre-existing E2E suite asserts it; the label always carries the rule-based qualifier. Renaming it is a one-line change plus that assertion.)

Screenshots (final build): docs/screenshots/ — each screen in Dark and Light.

2a. ML upgrade (v5)

  • Training pipeline in ml/: ISOMORPH benchmark -> chronological split -> baselines (existing EWMA, seasonal naive, last value, trailing mean) vs Random Forest vs LightGBM -> one-shot test evaluation -> versioned, checksum-verified artefacts -> scenario holdout and a pre-registered promotion rule.
  • Measured (details: ml/reports/EVALUATION_REPORT.md): on the benchmark test split the trained model reaches 9.32% WAPE vs 11.12% for the best simple baseline and 11.83% for the existing statistical model (run without weather). On this application's own scenario the statistical model is better (4.00% vs 4.34% WAPE, days 1-14), so the trained model is not promoted and the default forecast remains statistical. Opt in with FORECAST_MODEL_MODE=ml.
  • Backend: GET /api/ml/models, GET /api/ml/evaluation, POST /api/ml/shortage-risk (benchmark-format scoring); GET /api/forecast now reports model id, family, generation time, data freshness, interval method and any fallback reason; every forecast row stores the model that produced it. A failed or missing model falls back visibly to the statistical model.
  • Frontend: Forecast page shows attribution, a labelled trained-model preview and the holdout comparison; new Model Evaluation page with benchmark/scenario/shortage tables, licences and limitations; keyboard-operable rows, skip link, accessible chart labels, page titles.
  • Shortage-onset model: trained and evaluated on the benchmark (ROC-AUC 0.988) but deliberately not wired into inventory status: the scenario has no backlog or in-transit ledger and the probabilities are calibrated to ISOMORPH's replenishment policy.
  • Not done / not claimed: no route-disruption model (no outcome labels exist), no accuracy claim for real operations, Dataset_AI_Supply_Optimization.csv not used for training (no dates/IDs; columns behave like independent uniform draws - see ml/DATA_CARD.md).
  • Audit: python scripts/audit_terminology.py scans user-facing sources for prohibited development terminology (also enforced by backend/tests/test_terminology.py).

2. V7.1: deployment verification and hardening

See docs/CHANGES_V7_1.md: Compose now separates the administrative, owner (migrations) and application database roles; a CLI crash under the restricted role, a shared-client-address problem behind load balancers, postgres:// URLs and a map error on fast navigation were fixed; build-tool advisories reduced from 9 to 5 (all braces, build-time only); Docker and Render remain unexecuted (blocked), with a full audit and commands in docs/DEPLOYMENT.md.

2a. V7: end-to-end completion

Built on the V6 archive (see docs/CHANGES_V7.md): corridor-closure feasibility rule, idempotent inventory events, saved-scenario comparison, least-privilege database role support, concurrency/conservation/integrity tests, a deterministic evaluator walkthrough (scripts/guided_walkthrough.py) and a complete document set: ARCHITECTURE · DEPLOYMENT · SECURITY_REVIEW · ML_EVALUATION_REPORT · DATA_DICTIONARY · LIMITATIONS_AND_ASSUMPTIONS · VERIFICATION_REPORT.

Evaluator walkthrough (needs a running stack and an admin account):

PLSD_URL=http://localhost:8080 PLSD_USER=<admin> PLSD_PASSWORD=<password> python scripts/guided_walkthrough.py

2b. V6 release: hardening and verification

Incremental upgrade of V5 (nothing rebuilt): sign-in with viewer/operator/admin roles, CSRF protection, lock-out and rate limits, security headers and a strict CSP, development/production configuration profiles that refuse weak or missing secrets, non-destructive versioned migrations, atomic multi-step writes, strict input validation, layered health endpoints with model/fallback/data-coverage reporting, structured logs, an inventory-risk explanation (source, horizon, rules, limitations), and a much larger automated test suite. Details: docs/CHANGES_V6.md.

The shortage-onset model is not used for inventory status because the application has no daily on-hand history or in-transit/backlog ledger to feed it; why, and how to scrutinise that decision, is in docs/SHORTAGE_MODEL_DECISION.md.

3. Architecture

 Browser (React + Leaflet + Recharts)            iot-simulator/simulator.py  (simulated ESP32/RFID)
        │  /api/*                                         │  POST /api/iot/update
        ▼                                                 ▼
   nginx :8080 ───────────────────────────────►  FastAPI :8000  (routers → services → repository)
   (static SPA + /api proxy)                       │  pure engines: forecasting · inventory · terrain · routing
                                                   │  priority · allocation · simulation · recommendation · iot
                                                   ▼
                                  PostgreSQL 16 + PostGIS 3.4 :5432  (migrations, seed.sql)
  • Business logic lives in the backend. The frontend only renders API responses (scenario sliders are sent as query parameters or to POST /api/simulation/run).
  • backend/app/services/* are pure functions over plain dataclasses (no DB) so they are unit-testable; repository.py loads a Snapshot from PostgreSQL/PostGIS and persists derived data.

Technology stack

React 18 · Vite 5 · TypeScript · Tailwind CSS 3 · Recharts 2 · Leaflet 1.9 / React-Leaflet 4 (OpenStreetMap tiles) · FastAPI · Pydantic 2 · SQLAlchemy 2 · GeoAlchemy2 · psycopg 3 · scikit-learn (challenger) · PostgreSQL 16 + PostGIS 3.4 · Docker Compose · nginx · pytest · Playwright (e2e).

4. Quick start

With Docker Compose

python scripts/generate_env.py        # writes .env with fresh random secrets (3 database passwords, JWT secret, first admin) - never overwrites
docker compose up --build             # db -> one-shot migrate -> backend -> frontend ; UI: http://localhost:8080
  • Sign in with the administrator printed by generate_env.py, then remove BOOTSTRAP_ADMIN_PASSWORD from .env. There are no default credentials: docker compose up stops with a clear message if a secret is missing.
  • Database roles (V7.1): plsd_admin only initialises the volume (roles + PostGIS); the one-shot migrate service runs migrations as the non-superuser owner plsd_owner, grants the data-only role and loads the fictional scenario into an empty database; the API runs as plsd_app (data access only, no owner credentials, AUTO_MIGRATE=0). The database and API are not published on the host.
  • APP_ENV defaults to production (Secure session cookie: works on https:// and on http://localhost); for plain-HTTP use from another machine set APP_ENV=development.
  • Not executed in the release environment: the images were not built and Compose was not started (no Docker; image registries unreachable). The Compose file passes the compose-spec schema and hadolint, its role design was executed with scripts/local_stack.sh, and the exact commands to verify it on a Docker host are in docs/DEPLOYMENT.md. See docs/VERIFICATION_REPORT.md.

Development without Docker (any PostgreSQL 16 + PostGIS)

# 1. database
createdb logistics_dev && psql logistics_dev -c 'CREATE EXTENSION postgis'
export DATABASE_URL=postgresql+psycopg://USER:PASSWORD@localhost:5432/logistics_dev
export BOOTSTRAP_ADMIN_USERNAME=admin BOOTSTRAP_ADMIN_PASSWORD='<choose a long password>'

# 2. backend   (APP_ENV defaults to development: random per-process JWT secret, API docs at /docs)
cd backend && python -m venv .venv && . .venv/bin/activate
pip install -r requirements.txt
python -m app.cli migrate && uvicorn app.main:app --reload --port 8000

# 3. frontend  (Vite proxies /api -> http://localhost:8000)
cd frontend && npm ci && npm run dev              # http://localhost:5173

Operational commands: python -m app.cli check-config | migrate | verify-schema | seed-scenario | grant-app-role ROLE | create-user NAME --role admin | set-password NAME | reset-database --confirm DB (see backend/app/cli.py).

Tests

pip install -r backend/requirements-dev.txt
# the database tests CREATE tables and users: they refuse any database whose name does not contain test, ci or scratch
createdb logistics_test && psql logistics_test -c 'CREATE EXTENSION postgis'
export DATABASE_URL=postgresql+psycopg://USER:PASSWORD@localhost:5432/logistics_test
cd backend && REQUIRE_DB=1 python -m pytest              # release mode: an unreachable database FAILS the run instead of skipping
cd ml && PYTHONPATH=../backend python -m pytest         # training/evaluation pipeline tests (needs ml/requirements-ml.txt)
python scripts/audit_terminology.py                      # user-facing terminology audit (add --dist after `npm run build`)
cd frontend && npm run typecheck && npm run build
# browser suites need a running stack (docker compose, or scripts/local_stack.sh) and an existing admin account:
APP_URL=http://localhost:8080 E2E_USER=<admin> E2E_PASSWORD=<password> AXE_JS=<path to axe.min.js> python tests/e2e/e2e_v6_security_workflows.py

pip install playwright && playwright install chromium is needed once for the browser suites (tests/e2e/).

python backend/scripts/generate_seed.py          # regenerate db/seed.sql (deterministic, seed 2026)
PLSD_USER=<operator> PLSD_PASSWORD=<password> python iot-simulator/simulator.py --count 10 --interval 0.5   # simulated scanner

Environment variables: docs/CONFIGURATION.md (every variable, per profile).

5. Project structure

├── docker-compose.yml          db (PostGIS) · backend · frontend
├── db/                         init/10-roles.sh (database roles + PostGIS, first start only) · migrations/ (0001 baseline · 0002 users+audit · 0003 integrity · 0004 event idempotency) · seed.sql (generated)
├── backend/
│   ├── app/{main,config,security,auth,migrate,observability,cli,database,models,schemas,repository,bootstrap,seed_data,serializers}.py
│   ├── app/routers/            gis · inventory · forecast · decision · iot · simulation
│   ├── app/services/           domain · forecasting · challenger · inventory · terrain · routing · priority
│   │                           allocation · simulation · recommendation · explain · iot · status · engine
│   ├── scripts/                generate_seed.py · verify_v3_parity.py
│   └── tests/                  434 tests (+ golden_v3.json produced by the original v3 JS)
├── frontend/                   React + Vite + TS + Tailwind (src/pages: Dashboard, Forecast, Gis, Inventory, Simulation;
│                               src/components: CommandBriefing, WhyRecommendation, RouteSelection, ModelRoles,
│                               RecommendedResponse, IotFlow, LogisticsMap…; src/theme.tsx: Dark/Light)
├── iot-simulator/simulator.py  stdlib-only simulated ESP32/RFID client
├── tests/e2e/                  e2e_v6_security_workflows.py (60) · e2e_v7_workflows.py (5) · e2e_v71_gis_resilience.py (14) · e2e_playwright.py (73) · e2e_ui_enhancements.py (92) · e2e_v4_polish.py (38)
├── docs/                       ARCHITECTURE · DEPLOYMENT · SECURITY_REVIEW · ML_EVALUATION_REPORT · DATA_DICTIONARY · LIMITATIONS_AND_ASSUMPTIONS · VERIFICATION_REPORT · CHANGES_V7_1/V7/V6 · CONFIGURATION · SHORTAGE_MODEL_DECISION · TROUBLESHOOTING · DEPENDENCIES

Start-up and failure behaviour

  • nginx resolves the backend per request (resolver 127.0.0.11 + variable upstream), so the frontend container starts and serves the UI even if the backend is down, restarting or not yet created; /api/* returns 502 and the UI shows "Backend unavailable" with Retry. A recreated backend with a new IP is picked up without restarting nginx. /healthz reports nginx liveness only.
  • Compose: db health uses TCP (pg_isready -h 127.0.0.1) so it cannot report ready during the image's first-run init; backend waits for a healthy db; frontend only waits for the backend to start (not to be healthy), so a slow backend never aborts docker compose up; services use restart: unless-stopped.
  • Backend: if the first bootstrap fails (database unreachable/not yet seeded), it keeps retrying in the background every 5 s until it succeeds — no manual restart. /api/health returns 503 degraded meanwhile.

6. Database & PostGIS

Versioned migrations in db/migrations/ (all tables have keys/constraints; PostGIS extension enabled; never destructive; checksum-protected):

supplies · locations (PostGIS Point,4326, GiST index) · depots · vehicles · routes (PostGIS LineString,4326, GiST) · terrain (generated column terrain_risk) · weather · consumption (5,500 rows) · inventory (forward + depot stock, safety stock) · forecasts · alerts · priority_scores · allocations · iot_events · simulation_runs, plus view v_consumption_enriched.

The backend genuinely uses the database: forecasts are computed from consumption + weather and stored in forecasts; inventory, routes, terrain and vehicles are read from their tables; coordinates/polylines are read via ST_X/ST_Y/ST_AsGeoJSON; route polyline length is measured by PostGIS (ST_Length(geography), shown on the route card); baseline alerts, priority scores and allocations are persisted and refreshed on start-up and after every IoT event; simulation runs and IoT events are stored.

Simulated scenario data (seed 2026, deterministic): 3 depots, 5 forward locations, 10 supply types, 8 routes, 8 vehicles (one in maintenance), 140 weather days (110 observed + 30 outlook), 5,500 consumption records (5 × 10 × 110). Relationships: demand = base × location factor × slow trend × weather effect (per-supply sensitivity) × weekly cycle × noise; stock levels are set relative to forecast demand; lead time derives from route ETA, which derives from distance, road, weather and terrain. Coordinates are arbitrary points in a made-up grid (Base_01 (fictional) etc.).

7. API

Scenario parameters (demand 0–0.5, weather 0–1, road 0–1, vehicles 0.5–1) can be added as query parameters to every scenario-aware GET.

Method & path Purpose
GET /api/health API + DB status (503 degraded if the DB is down)
GET /api/locations, /api/locations/{id} Depots/forward locations with risk status; detail incl. items, Why-at-risk, insight, routes
GET /api/inventory (location,supply,risk) · /api/inventory/projection Stock, days of supply, shortage, status · 14-day projection
GET /api/forecast (location,supply,horizon) · /api/forecast/challenger · POST /api/forecast/recompute Forecast, backtest, confidence · RF challenger · recompute
GET /api/alerts Alerts (baseline from the alerts table; scenario derived live)
GET /api/vehicles · /api/routes · /api/routes/compare?destination= Fleet · routes with terrain/ETA/risk · alternatives + reason
GET /api/priority · /api/priority/weights · /api/allocation · /api/insights · /api/dashboard Priority queue · weights · allocation plan · recommendations/Why-at-risk · KPIs/system status/pipeline
POST /api/simulation/run · GET /api/simulation/runs What-If run (stored) · history
GET /api/iot/events · /api/iot/feed · POST /api/iot/update · /api/iot/simulate · /api/iot/reset Simulated IoT

Interactive docs at /docs.

8. Forecasting methodology

Statistical time-series model (not a trained ML model), deterministic: history is de-weathered and de-seasonalised, smoothed with an EWMA (α = 0.2), extended with a damped linear trend (0.5 × recent 7-day slope), then re-weathered with the synthetic 30-day weather outlook and re-seasonalised (weekly cycle). Weather multiplier = 1 + sensitivity × 0.6 × weather_index. Backtest: rolling one-step-ahead over the last 60 days → MAPE, RMSE, coefficient of variation, interval coverage (±1.28 σ). Confidence = 100 − MAPE × (1 + horizon/30) (a stated heuristic). Random Forest challenger (scikit-learn, 20 trees, depth 6, seeded) is trained on days 1–90 and validated on days 91–110; on this data it scores ≈ 4.8 % hold-out MAPE vs ≈ 3.7 % for the statistical model. It is a cross-check only and does not drive any dashboard number. Caveat: the scenario history is generated from the same weather/weekly structure the model assumes, so the low error is expected and says nothing about real-world accuracy.

9. Inventory & risk engine

  • Days of supply = stock ÷ forecast daily demand (first 7 forecast days, scenario-adjusted).
  • Predicted shortage (14 d) = max(0, demand × 14 − stock). Stock-out date = sim-clock + days of supply.
  • CRITICAL (red): cover < 3 d or < lead time + 1 d · WARNING (yellow): cover < lead time + 3 d or stock < safety stock · else NORMAL (green).
  • Replenishment quantity = safety + demand × (lead + 5 d) − stock, rounded to 50-unit loads.
  • Location status: ≥ 2 critical items → CRITICAL; ≥ 1 critical or ≥ 3 warning → WARNING.
  • Overall risk index (0–100) = 100 × min(1, 2.2·crit/N + 0.8·warn/N + 0.3·mean route risk + 0.2·capacity-deficit share).
  • Why at risk: per location, the top items with demand change vs the last 7 days, stock vs safety stock, cover vs lead time, best-route risk and weather index, as a plain-language summary.

10. Terrain, route optimisation & GIS

  • Terrain risk = 0.7 × difficulty + 0.3 × elevation_band/3 (fictional bands 0–3, e.g. "High-altitude ridge").
  • Effective speed = nominal × (1 − 0.45·road) × (1 − 0.35·terrain risk) × (1 − 0.3·weather risk) (floor 8 km/h); ETA = distance ÷ effective speed. Weather risk on a route = weather × (0.5 + 0.5·terrain risk), so terrain amplifies weather.
  • Route risk = 0.25 road + 0.25 weather + 0.30 terrain + 0.20 distance factor.
  • Route selection: combined score = route risk + ETA/24 h + capacity penalty (≤ 0.2, grows when the depot's available vehicle capacity is below the quantity to move). A route is feasible only if its depot has an available vehicle. GET /api/routes/compare returns all routes, scores, SELECTED/ALTERNATIVE/NO VEHICLE and a written reason.
  • Leaflet + OpenStreetMap map: status-coloured markers (normal / warning / critical), square depot markers, risk-coloured route lines (dashed = poor road), a toggleable terrain band layer, popups with inventory, shortage, ETA, terrain, weather and capacity. If tiles cannot load, a notice appears and the overlay keeps working on a plain background.
    • Tile provider (v7.1 fix): The nginx Referrer-Policy header is set to strict-origin-when-cross-origin (the browser default). The previous no-referrer setting suppressed the HTTP Referer header, causing OSM tile servers to return 403 Access Blocked (the OSM tile usage policy explicitly requires a valid Referer from web pages). The tile URL and attribution are configurable at build time via VITE_TILE_URL / VITE_TILE_ATTRIBUTION; the default is the OSM standard tile server (https://tile.openstreetmap.org/{z}/{x}/{y}.png). OSM tiles are a best-effort volunteer service with no SLA — for a production deployment use a commercial provider (Stadia Maps, Jawg, Mapbox) and document the provider's API key as a Dockerfile build ARG; see .env.example for details.

11. Priority & allocation

Priority score (0–100) = 100 × (0.30 shortage urgency + 0.15 shortage volume + 0.15 stock deficit + 0.15 supply criticality + 0.10 lead-time pressure + 0.10 route feasibility/risk + 0.05 transport capacity). Weights are fixed, documented prototype assumptions (GET /api/priority/weights). Allocation walks the queue in priority order; for each item it tries routes in combined-score order, ships at most the depot's actual stock of that supply (depot stock is a finite synthetic quantity, ≈ 8 days of network demand) and loads vehicles within effective vehicle capacity (smallest sufficient vehicle first). Unmet quantity is reported with its binding constraint (VEHICLE CAPACITY, DEPOT STOCK, NO FEASIBLE ROUTE). The per-item "AI Logistics Insight" is a stand-alone, deterministic rule-based recommendation (no external AI model) assuming full fleet availability; the allocation plan resolves vehicle contention across all items, so the vehicle shown can differ — the UI/API say so.

12. IoT simulation

iot-simulator/simulator.py (or the UI scanner, or POST /api/iot/simulate) emits simulated ESP32/RFID scans: RECEIVE (+), ISSUE (−, never below 0), COUNT (set). Each goes through POST /api/iot/update → validated → stored in iot_events → inventory updated → alerts/priority/allocation refreshed → dashboard recalculated. Every response and UI panel is labelled simulated; the simulated column is constrained to true. No hardware is involved.

13. What-If simulation

Controls: demand +0–50 %, weather severity, road condition, vehicle availability 50–100 %. POST /api/simulation/run recomputes the baseline and the scenario and returns before/after: critical/warning items, shortage-risk locations, expected shortage, transport capacity/need/deficit, mean route risk, mean ETA delay, overall risk index, allocated/unmet units, per-location status and per-route ETA/risk, plus generated explanations (including which route terrain slows most). The run is stored in simulation_runs. "Apply to all screens" sets the scenario for every screen.

14. Walkthrough

  1. Toggle Light/Dark in the sidebar (Dark is default; the choice persists across reloads).
  2. Dashboard — the Command Briefing shows baseline risk 62/100 (HIGH), critical locations Base_03 & Base_04, 1,44,595 units predicted short, transport 34,000 vs 41,800 needed, 8 critical / 6 warning alerts and the top 3 actions; pick any priority in Why this recommendation?; then map, priority queue, allocation, insight, Why-at-risk, system status.
  3. GIS — click Base_04 → route comparison (R03 selected, R08 alternative, reason shown); click route R07 → terrain/elevation/effective speed.
  4. Forecast — switch 7/14/30 days; filter Base_04 / Medical; read methodology and the RF challenger.
  5. Inventory — filter by risk; Send scan RECEIVE Base_04/Medical 2000 → status turns NORMAL, header and dashboard update (critical 8 → 7, risk 62 → 57). Reset inventory restores the seed.
  6. Simulation — demand +30 %, severe weather, poor roads, 60 % fleet → risk 62 → 93, capacity 34,000 → 20,400; read the explanations; Apply to all screens and revisit Dashboard/GIS.

15. Testing

Exact commands and the results of the V6 verification run are in docs/VERIFICATION_REPORT.md, separated into what was executed, what was verified only statically, and what could not be verified.

  • Backend: 434 tests, all against FastAPI + PostgreSQL/PostGIS: configuration profiles, security primitives, authentication/RBAC/CSRF/lock-out, migrations (fresh, repeatable, adoption, rollback, integrity), API validation and transactions, ML feature parity and artefact integrity, health and logging, deployment-file validation, terminology.
  • ML pipeline: 14 tests (ml/tests): chronological splits, purging, leakage and metric correctness of the training/evaluation code.
  • Browser: 282 checks (281 passed, 1 deliberately skipped) in six Playwright suites, run against the production profile behind the real nginx configuration (including a WCAG 2 A/AA axe scan).
  • v3 parity: the Python engine is compared with backend/tests/golden_v3.json, captured from the original v3 JavaScript. The original page is not shipped in V7 (backend/scripts/verify_v3_parity.py explains how to regenerate the fixture).

16. Limitations (read these)

See also docs/SECURITY_REVIEW.md and docs/VERIFICATION_REPORT.md.

  • Simulated scenario data only. Findings are properties of the generator, not of any real supply chain. Forecast accuracy in particular is flattering because the data and the model share assumptions.
  • All formulas, thresholds, priority weights and the capacity penalty are documented assumptions, not calibrated against real operations.
  • The recommendation engine is rules-based; it is not an AI/LLM and does not learn.
  • Routes are drawn as simple fictional polylines; "distance" is a seeded number, not computed from road networks. No real elevation or weather data is used.
  • IoT is simulated end-to-end; no device authentication, no MQTT, no real RFID/ESP32 firmware.
  • Authentication, roles and an audit trail exist (V6) but the application has not had an independent security review or penetration test; there is no encryption at rest, no multi-factor sign-in, no device authentication for the simulated scanner, and rate limits are per process. See docs/SECURITY_REVIEW.md.
  • Allocation is a greedy, priority-ordered heuristic, not an optimal solver; vehicles serve only their own depot's routes.
  • The Docker images, docker compose up and the Render blueprint were not built or run in V6, V7 or V7.1 (no Docker, registries unreachable, no Render access); the same application settings, migrations, role design and nginx template were exercised without containers instead (scripts/local_stack.sh).
  • The simulation clock is anchored at 2026-06-19 06:00 UTC and runs at 60× for display only.
  • The bundle is ~760 kB (no code splitting).

About

AI-assisted predictive logistics and forward supply chain decision-support platform for SIH 2026 Problem Statement 26251.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages