Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 103 additions & 74 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,110 +1,139 @@
# TERA — Tactical Edge Route Agent
# TERA -- Offline-first AI Emergency Logistics Coordination Agent

> **By Team TruePoint** — competing as members of the **[Naval Postgraduate School Foundation](https://npsfoundation.org/) Entrepreneurship Club** · National Security Hackathon 2026 (Cerebral Valley × US Army xTech)
>
> A pocket-sized, fully-offline AI agent that turns natural language into trustworthy tactical routes inside ATAK, on a Jetson Orin Nano, with no cloud and no outbound packets. Voice in, voice and visual out — operators can navigate hands-free while climbing, fast-roping, or running another task.
> **By Team TruePoint** -- Naval Postgraduate School Foundation Entrepreneurship Club.

**TERA / Terra / Terraform / Terrain** — the product's name carries the thesis: an operator with TERA can shape their own path across any terrain, anywhere on earth. The Figma design language leans on earth-tones, contour-line motifs, and terraforming-as-empowerment imagery (Jon owns).
TERA is an offline-first AI coordination platform for disaster response. It helps emergency teams detect active hazards, identify hospitals and shelters, allocate scarce resources, assign vehicles, choose safer routes, explain operational decisions, and keep working when connectivity is degraded.

**Hackathon:** 3rd Annual National Security Hackathon · San Francisco · May 2–3, 2026.
**Problem statements:** PS2 (Edge Deployments) · PS3 (Mission C2) · PS4 (Cybersecurity).
**Source of truth:** [`docs/PRD.md`](docs/PRD.md) — read this first.
Originally built as a tactical edge routing prototype, TERA is now extended into a humanitarian disaster response platform powered by Gemini, Gemma, Google Maps, Firebase, and live US disaster APIs. The original ATAK, Jetson, signed CoT, and offline tactical route architecture remains available as a legacy/optional capability.

---
## Problem

## Read this before writing any code
Disaster responders make time-critical logistics decisions with incomplete information. Wildfire perimeters, flood gauges, smoke exposure, road closures, hospital availability, shelter capacity, vehicle status, and inventory all move faster than teams can manually reconcile. During the same window, fraud and misinformation can push fake donation links, fake FEMA portals, unverified shelter instructions, and fraudulent supply requests into the response loop.

1. [`AGENTS.md`](AGENTS.md) — agent guardrails. **AI agents must read this every task.**
2. [`docs/PRD.md`](docs/PRD.md) — product, architecture, security, demo plan.
3. [`.agents/00-team.md`](.agents/00-team.md) — stack + style + non-negotiables.
4. [`.agents/10-architecture.md`](.agents/10-architecture.md) — system design summary.
5. [`.agents/2X-<lane>.md`](.agents/) — your lane's specific conventions.
6. [`TASKS.md`](TASKS.md) — seed issues for the GitHub board.
## Solution

## Quickstart for new teammates
TERA turns a natural-language emergency objective into an explainable mission plan:

After cloning, **run this and follow the prompts:**
- active hazards and official disaster context
- hospital, shelter, fuel, bridge, and critical infrastructure options
- route candidates and route risk scoring
- deterministic offline resource allocation
- optional Google Maps Routes and Route Optimization when credentials and network are available
- TERA Trust Shield checks for disaster-fraud links, suspicious supply requests, unverified shelter claims, and conflicting field reports
- offline Gemma fallback and Firebase-ready shared state for degraded operations

## Why Offline-first Matters

TERA defaults to cached/sample/local state and deterministic fallbacks. Live APIs are opt-in on the v2 mission endpoint with `use_live_apis=true`. This keeps the legacy zero-outbound tactical demo intact while giving humanitarian teams richer live data when the network allows it.

## Google I/O Hackathon Fit

- **Gemini:** emergency reasoning, tool calling, multimodal explanation, and decision summaries.
- **Gemma:** local/offline fallback reasoning when connectivity drops.
- **Google Maps Routes API:** route generation, ETA, and alternatives.
- **Google Route Optimization API:** vehicle and resource allocation.
- **Firebase:** offline-first shared state for shelters, vehicles, inventory, missions, field reports, and hazard cache.
- **Google Safe Browsing:** phishing and malware URL checks for crisis-related links.

## Architecture v2

Legacy `/plan` remains available for tactical ATAK routing. The humanitarian layer adds:

- `POST /mission/plan` -- emergency logistics mission planning
- `GET /mission/health` -- v2 liveness and offline default status
- `GET /mission/api-status` -- API-key presence without exposing values
- `GET /mission/demo/bay-area-wildfire` -- no-key, no-network wildfire logistics demo
- `POST /trust/check-url` -- crisis-link trust assessment
- `POST /trust/check-message` -- field-message trust assessment
- `POST /trust/check-supply-request` -- supply-request trust assessment
- `GET /trust/api-status` -- Trust Shield API-key presence without exposing values

See [`docs/architecture_v2.md`](docs/architecture_v2.md).

## TERA Trust Shield

During disasters, fraud and misinformation can disrupt response operations. TERA Trust Shield verifies crisis-related links, supply requests, shelter claims, and field reports using Google Safe Browsing, optional threat intelligence providers, official-source matching, and human approval workflows. Suspicious information is isolated from mission planning until approved.

See [`docs/trust_shield.md`](docs/trust_shield.md).

## API Integrations

TERA includes thin adapters for NOAA/NWS, FEMA, HIFLD, NIFC/WFIGS, AirNow, SF511, NASA FIRMS, USGS, NOAA NWPS, National Bridge Inventory, NREL, EONET, ReliefWeb, Google Maps Routes, Google Route Optimization, Firebase status, Google Safe Browsing, VirusTotal, urlscan.io, and RDAP.

See [`docs/api_inventory.md`](docs/api_inventory.md).

## Demo: Bay Area Wildfire Logistics

```bash
make onboard
make run
curl -s http://localhost:8000/mission/demo/bay-area-wildfire | jq .
```

It asks who you are (Jon / Satriyo / Kyle / Ben), checks your environment, lists your assigned GitHub issues, and writes a tailored Codex/Cursor kickoff prompt to `/tmp/codex-<name>.md` (also copied to clipboard on macOS). Paste that prompt into your AI agent and start coding.
The demo identifies Shelter North as overloaded and smoke-exposed, selects Shelter West as the safer logistics destination, assigns trucks to verified needs, flags a fake FEMA login link, blocks an unverified supply request from changing dispatch, and explains the decision with offline fallback state.

Non-interactive: `make onboard NAME=ben`.
See [`docs/demo_google_io.md`](docs/demo_google_io.md).

## Quickstart for development
## Quickstart for Development

```bash
git clone https://github.com/jdev-02/tera.git tera && cd tera
make install # venv + core deps (~2 min)
lefthook install # pre-push hook (blocking)
cp .env.example .env # set OPENAI_API_KEY for Phase 1
make run # stub service on :8000
make ci # the gate (must pass before push)
make install
lefthook install
cp .env.example .env
make run
make ci
```

Lane-specific extras:
- **Jon** (voice work): `make install-voice`
- **Satriyo** (crypto work): `brew install liboqs && make install-crypto` (macOS) or `bash infra/install_liboqs.sh && make install-crypto` (Linux/Jetson)

Smoke check from another terminal:
Mission demo:

```bash
curl -s -X POST http://localhost:8000/plan \
-H 'Content-Type: application/json' \
-d '{"prompt": "route to nearest freshwater within 5km", "current": {"lat": 37.7955, "lon": -122.3937}}' | jq .
curl -s http://localhost:8000/mission/demo/bay-area-wildfire | jq .
```

## Repo layout (PRD §13.2)
Trust Shield demo:

```
agent/ # Jon (P1) — orchestrator, /plan endpoint
ontology/ # Jon (P1) — NL term -> OSM tag mapping
voice/ # Jon (P1) — Whisper-tiny (in) + Piper TTS (out)
eval/ # Jon (P1) — 20-prompt regression set
figma/ # Jon (P1) — UI/UX mockups (TERA / terra / terraform palette)
atak/ # Ben (P4) — CoT bridge (Android + WinTAK)
routing/ # Ben (P4) — Valhalla + custom cost
data/ # Ben (P4) — OSM PBF + DEM extracts + Cesium tile cache
hardware/ # Kyle (P3) — Jetson bring-up
deploy/ # Kyle (P3) — systemd, rsync
models/ # Kyle (P3) — Gemma + Whisper + Piper, manifest
mesh/ # Kyle (P3) — stretch (WiFi-Direct / BLE)
security/ # Satriyo (P2) — threat model, parse-verify
crypto/ # Satriyo (P2) — ML-DSA / ML-KEM
infra/ # Satriyo (P2) — Jetson hardening, liboqs install
.github/ # Satriyo (P2) — CI workflows
.agents/ # Satriyo (P2) maintains — agent rules per lane
docs/ # shared — PRD, contracts, ADRs
```bash
curl -s -X POST http://localhost:8000/trust/check-url \
-H 'Content-Type: application/json' \
-d '{"url":"https://fema-aid-claim-example.com/login","context":"wildfire relief claim link"}' | jq .
```

## Team TruePoint
Optional live API preflight:

| Member | Lane | Background | Pitch role |
|---|---|---|---|
| **P1 — Jon** (`@jdev-02`) | agent · ontology · voice (in+out) · eval · figma | Navy CWO, CS + AI (ontology), UI/UX | Floor support (AI questions) |
| **P2 — Satriyo** (`@aleens-labs`) | security · crypto · infra · CI | Indonesian Navy, cybersecurity | Floor support (security/PQC) |
| **P3 — Kyle** (`@khicks1724` / `@kylemhicks`) | hardware · deploy · models · mesh | USMC SIGINT, robotics. Brought the Jetson. Provided Cesium Ion token. | Presenter B (drives the demo) |
| **P4 — Ben** (`@benschwierking`) | atak · routing · data | USMC Combat Engineer, Mountain Warfare School | Presenter A (lead narrator) |
```bash
python scripts/test_live_apis.py
python scripts/test_live_apis.py --submit-urlscan
```

Source of truth: [`team.yml`](team.yml). See [`docs/PRD.md`](docs/PRD.md) §13 for the full lane split.
`--submit-urlscan` is explicit because urlscan.io consumes quota and may load the target page.

## Phased build
## Legacy Tactical Mode

- **P1 — Web MVP** (Sat 1800): laptop + frontier API + CesiumJS (Cesium Ion).
- **P2 — Edge w/ frontier** (Sun 0200): Jetson + frontier API + signed CoT to ATAK.
- **P3 — Fully local HERO** (Sun 1000): Jetson + local Gemma + WiFi off + voice + signed CoT.
- **Stretch — Mesh + PQC reject**: phone + laptop + Nano on a mesh; inject-reject-accept demo.
The original tactical route agent is preserved:

## Demo
- `GET /health`
- `POST /plan`
- `POST /plan/approve`
- `POST /plan/verify`
- ML-DSA/Ed25519 fallback signing
- ATAK/CoT render-gate compatibility
- Jetson/Gemma offline deployment path

Hero scenario: *"Route me to the nearest freshwater source within 5km, on foot, covered terrain."* Voice prompt → Jetson → ATAK draws a signed blue line **and** Piper TTS speaks the rationale + waypoints in the operator's headset. WiFi off the entire time.
The tactical docs and contracts remain in [`docs/PRD.md`](docs/PRD.md), [`docs/contracts/agent_routing.schema.json`](docs/contracts/agent_routing.schema.json), and [`docs/contracts/cot_signed.md`](docs/contracts/cot_signed.md).

## License
## Repo Layout

MIT. (Per hackathon rules: open source at submission.)
```text
agent/ # legacy /plan plus v2 mission/trust endpoints
integrations/ # Google, US disaster, and Trust Shield adapters
data/ # sample scenarios and fixtures
security/ # threat model, parse-verify, security demos
crypto/ # ML-DSA / ML-KEM signing lane
atak/ # CoT bridge and render gate
routing/ # Valhalla/local routing lane
docs/ # PRD, contracts, v2 architecture, API inventory
```

---
## License

**For everything else, read the PRD.**
MIT.
70 changes: 69 additions & 1 deletion agent/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@
import structlog
from fastapi import FastAPI, HTTPException

from agent.mission_orchestrator import (
demo_bay_area_wildfire,
mission_api_status,
mission_health,
plan_mission,
)
from agent.mission_schemas import MissionPlanRequest, MissionPlanResponse
from agent.orchestrator import PlanBlockedError, approve_plan, verify_plan_response
from agent.orchestrator import plan as orchestrate_plan
from agent.schemas import (
Expand All @@ -31,6 +38,18 @@
PlanResponse,
PlanVerifyResponse,
)
from agent.tools.trust import (
assess_message_trust,
assess_supply_request_trust,
assess_url,
trust_api_status,
)
from agent.trust_schemas import (
MessageTrustRequest,
SupplyRequestTrustRequest,
TrustAssessment,
UrlCheckRequest,
)

log = structlog.get_logger(__name__)

Expand Down Expand Up @@ -65,7 +84,10 @@ async def _lifespan(_app: FastAPI) -> AsyncIterator[None]:
app = FastAPI(
title="TERA Agent",
version="0.1.0",
description="Tactical Edge Route Agent. PRD: docs/PRD.md. By Team TruePoint.",
description=(
"TERA emergency logistics coordinator with legacy tactical route mode. "
"PRD: docs/PRD.md. By Team TruePoint."
),
lifespan=_lifespan,
)

Expand All @@ -80,6 +102,11 @@ def health() -> dict[str, Any]:
}


@app.get("/mission/health")
def mission_health_endpoint() -> dict[str, Any]:
return mission_health()


@app.post("/plan", response_model=PlanResponse, responses={403: {"model": PlanBlocked}})
async def plan_endpoint(
req: PlanRequest,
Expand Down Expand Up @@ -134,6 +161,47 @@ async def plan_endpoint(
raise HTTPException(status_code=503, detail=str(e)) from e


@app.post("/mission/plan", response_model=MissionPlanResponse)
async def mission_plan_endpoint(req: MissionPlanRequest) -> MissionPlanResponse:
try:
return plan_mission(req)
except RuntimeError as e:
log.exception("mission_plan_failed", error=str(e))
raise HTTPException(status_code=503, detail=str(e)) from e


@app.get("/mission/api-status")
def mission_api_status_endpoint() -> dict[str, bool]:
return mission_api_status()


@app.get("/mission/demo/bay-area-wildfire", response_model=MissionPlanResponse)
def mission_demo_bay_area_wildfire_endpoint() -> MissionPlanResponse:
return demo_bay_area_wildfire()


@app.post("/trust/check-url", response_model=TrustAssessment)
async def trust_check_url_endpoint(req: UrlCheckRequest) -> TrustAssessment:
return assess_url(req.url, req.context)


@app.post("/trust/check-message", response_model=TrustAssessment)
async def trust_check_message_endpoint(req: MessageTrustRequest) -> TrustAssessment:
return assess_message_trust(req.message, req.source)


@app.post("/trust/check-supply-request", response_model=TrustAssessment)
async def trust_check_supply_request_endpoint(
req: SupplyRequestTrustRequest,
) -> TrustAssessment:
return assess_supply_request_trust(req.request)


@app.get("/trust/api-status")
def trust_api_status_endpoint() -> dict[str, bool]:
return trust_api_status()


@app.post("/plan/approve", response_model=PlanApprovalResponse)
async def plan_approve_endpoint(req: PlanApprovalRequest) -> PlanApprovalResponse:
try:
Expand Down
Loading
Loading