AreteDriver/overwatch
GitHub: AreteDriver/overwatch
该项目是一个战术 ISR 仪表板,旨在将 YOLO 目标检测、OSINT 情报和无人机遥测数据融合为统一的作战态势图以辅助决策。
Stars: 0 | Forks: 0
# Overwatch
战术 ISR 仪表板,将 YOLO 目标检测、OSINT 情报源和无人机遥测数据整合为统一的作战态势图。
专为 mesh-net ISR 工作流构建 —— 从摄像头、无人机和新闻管道摄取数据,然后在一个仪表板中进行可视化、关联和决策。
## 功能
- **多源数据摄取** — 用于 YOLO 检测、OSINT 情报(TheWire-STT 格式)以及无人机/传感器遥测的 REST 端点
- **YOLO 自动监控器** — CLI 监控目录中的 ultralytics JSON 输出,并自动将其发送到 API
- **实体解析** — 将检测数据与情报提及进行交叉关联(摄像头中的人物 + 报告中提及的姓名 = 同一实体)
- **自动简报** — 从摄取的数据生成 SITREP。默认基于模板,或由 Ollama 驱动 (qwen2.5:14b)
- **地理围栏** — 定义多边形区域,在进出时获取警报
- **Mesh 健康** — 设备心跳追踪(在线/滞后/离线状态)
- **Discord 警报** — 通过 Webhook 发送高置信度检测、低电量、地理围栏违规警报
- **实时推送** — 位于 `/ws/feed` 的 WebSocket 实时广播所有发生的事件
- **检测热力图** — 地图上随时间变化的密度可视化
- **回放模式** — 拖动时间轴进行任务后审查
- **8 标签页 Streamlit 仪表板** — 地图、时间轴、情报源、简报、实体、Mesh 健康、警报、回放
## 快速开始
```
git clone https://github.com/AreteDriver/overwatch
cd overwatch
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev,dashboard]"
# 运行数据库迁移(创建/覆盖 SQLite schema)
alembic upgrade head
# 启动 API server
uvicorn overwatch.app:app --reload --port 8080
# 启动 dashboard(单独的终端)
streamlit run dashboard/app.py --server.port 8520
# 将 YOLO output 指向它(可选)
python tools/yolo_watcher.py --dir /path/to/yolo/runs --lat 46.05 --lon 14.5
```
API 文档可在 http://localhost:8080/docs (Swagger UI) 查看。
## 架构
```
overwatch/
├── overwatch/
│ ├── app.py # FastAPI entry point + WebSocket
│ ├── config.py # Env-driven configuration
│ ├── models.py # SQLAlchemy ORM + Pydantic schemas
│ ├── database.py # Engine + session factory
│ ├── events.py # In-process async event bus
│ ├── security.py # Auth, rate-limit, headers middleware
│ ├── crypto.py # Optional Fernet field encryption
│ ├── api/routes.py # 30+ REST endpoints
│ ├── ingest/ # Detection, intel, telemetry adapters
│ │ ├── detections.py # YOLO detection ingestion
│ │ ├── intel.py # OSINT intel ingestion
│ │ ├── telemetry.py # Drone/sensor telemetry
│ │ └── thewire_adapter.py # TheWire-STT format adapter
│ └── analysis/
│ ├── alerts.py # Threshold alerts + Discord webhook
│ ├── briefing.py # Template briefing generator
│ ├── ollama_briefing.py # Local Ollama LLM briefings
│ ├── entities.py # Entity extraction + resolution
│ ├── geofence.py # Geofence CRUD + point-in-polygon
│ ├── mesh_health.py # Device heartbeat tracking
│ └── replay.py # Time-windowed data retrieval
├── alembic/ # Database migrations (Alembic)
├── dashboard/app.py # Streamlit dashboard (8 tabs)
├── tools/yolo_watcher.py # CLI: watch dir for YOLO output
├── scripts/ # Dev tooling (mypy ratchet, etc.)
├── retention.py # Data retention + auto-purge
└── tests/ # 290+ tests, 85% coverage
```
**技术栈**:FastAPI + SQLAlchemy + SQLite (WAL 模式) + Streamlit + Folium + Plotly
## API 端点
### 摄取
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| POST | `/api/detections` | 摄取 YOLO 检测数据 |
| POST | `/api/detections/batch` | 批量摄取检测数据 |
| POST | `/api/intel` | 摄取情报报告 |
| POST | `/api/intel/batch` | 批量摄取情报 |
| POST | `/api/telemetry` | 摄取遥测读数 |
| POST | `/api/telemetry/batch` | 批量摄取遥测数据 |
### 查询
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| GET | `/api/detections` | 列出检测数据(可过滤) |
| GET | `/api/intel` | 列出情报报告 |
| GET | `/api/telemetry` | 列出遥测读数 |
| GET | `/api/entities` | 列出已解析的实体 |
| GET | `/api/entities/{id}/timeline` | 实体事件时间轴 |
| GET | `/api/alerts` | 列出警报 |
| PATCH | `/api/alerts/{id}/acknowledge` | 确认警报 |
### 分析
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| POST | `/api/briefing/generate` | 生成 SITREP 简报 |
| GET | `/api/briefing/latest` | 获取最新简报 |
| GET | `/api/mesh/health` | Mesh 节点健康状态 |
| GET | `/api/replay` | 时间窗口回放数据 |
| GET | `/api/dashboard/stats` | 仪表板统计摘要 |
### 地理围栏
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| POST | `/api/geofences` | 创建地理围栏区域 |
| GET | `/api/geofences` | 列出地理围栏 |
| DELETE | `/api/geofences/{id}` | 删除地理围栏 |
### 导出
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| GET | `/api/export/detections.csv` | 将检测数据导出为 CSV |
| GET | `/api/export/detections.geojson` | 将检测数据导出为 GeoJSON |
| GET | `/api/export/intel.csv` | 将情报报告导出为 CSV |
| GET | `/api/export/telemetry.csv` | 将遥测数据导出为 CSV |
| GET | `/api/export/telemetry.geojson` | 将遥测数据导出为 GeoJSON |
### 管理
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| POST | `/api/admin/purge` | 手动清理旧记录 |
### 系统
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| GET | `/health` | 健康检查(丰富版 — 计数、数据库大小、WS 连接数) |
| WS | `/ws/feed` | 实时事件流 |
## 环境变量
| 变量 | 默认值 | 描述 |
|----------|---------|-------------|
| `OVERWATCH_DATABASE_URL` | `~/.overwatch/overwatch.db` | SQLite 数据库路径 |
| `OVERWATCH_API_KEY` | _(空 = 开放模式)_ | 用于身份验证的 API key |
| `OVERWATCH_CORS_ORIGINS` | `*` | 允许的 CORS 来源(逗号分隔) |
| `OVERWATCH_RATE_LIMIT` | `120` | 每个 IP 每个时间窗口的最大请求数 |
| `OVERWATCH_RATE_WINDOW` | `60` | 速率限制时间窗口(秒) |
| `OVERWATCH_DISCORD_WEBHOOK` | _(空)_ | 用于警报的 Discord Webhook URL |
| `OVERWATCH_ALERT_CONFIDENCE` | `0.9` | 高置信度检测阈值 |
| `OVERWATCH_ALERT_BATTERY` | `20.0` | 低电量警报阈值 (%) |
| `OVERWATCH_DEVICE_STALE_SECONDS` | `300` | 设备被标记为滞后前的秒数 |
| `OVERWATCH_DEVICE_OFFLINE_SECONDS` | `900` | 设备被标记为离线前的秒数 |
| `OVERWATCH_ENCRYPTION_KEY` | _(空)_ | 用于字段加密的 Fernet key |
| `OLLAMA_URL` | `http://localhost:11434` | Ollama API 端点 |
| `OLLAMA_MODEL` | `qwen2.5:14b` | 用于 LLM 简报的模型 |
| `OLLAMA_ENABLED` | `false` | 启用 Ollama 驱动的简报 |
| `OVERWATCH_RETENTION_DAYS` | `30` | 自动清理超过 N 天的记录(0 = 永久保留) |
| `OVERWATCH_PURGE_INTERVAL_HOURS` | `6` | 运行自动清理的频率(小时) |
## 安全
- **API key 认证**:设置 `OVERWATCH_API_KEY` 以启用。支持 `Authorization: Bearer ` 标头、`X-API-Key` 标头或 WebSocket `?key=` 查询参数。留空 = 开放模式(开发环境)
- **安全标头**:HSTS、X-Content-Type-Options、X-Frame-Options、XSS-Protection、Referrer-Policy、Permissions-Policy
- **速率限制**:基于 IP 的滑动窗口
- **CORS**:可配置的允许来源
- **字段加密**:针对敏感字段的可选 Fernet (AES-128-CBC)。需要 `cryptography` 包
## 部署
作为两个应用部署在 [Fly.io](https://fly.io) 上:
| 应用 | URL | 配置 |
|-----|-----|--------|
| API | https://overwatch-isr.fly.dev | `fly.toml` |
| 仪表板 | https://overwatch-dashboard.fly.dev | `fly.dashboard.toml` |
```
# 部署 API
flyctl deploy -a overwatch-isr --wait-timeout 600
# 部署 Dashboard
flyctl deploy --config fly.dashboard.toml --wait-timeout 600
```
## 开发
```
# 运行测试
pytest # All tests
pytest -m smoke # Smoke/integration tests
pytest --cov=overwatch # With coverage report
# Lint(始终同时运行两者)
ruff check .
ruff format .
# Type check
python -m mypy overwatch --ignore-missing-imports --show-error-codes --no-error-summary
# Type ratchet(如果任何 module 超过其 error ceiling 则失败)
python scripts/mypy-ratchet.py
```
## 集成点
- **[Dossier](https://github.com/AreteDriver/Dossier)** — 使用基于 ML 的 NER + 实体解析器直接替代正则表达式实体提取
- **[Animus](https://github.com/AreteDriver/animus)** — 用 AI 编排的上下文感知生成替代模板/Ollama 简报
- **TheWire-STT** — 从现有的 OSINT API 格式拉取 (GET `/api/stories`)
- **YOLO** — 通过监控器 CLI 或直接 POST 接收 ultralytics JSON 输出
- **Discord** — 针对高置信度检测、低电量、地理围栏违规的 Webhook 警报
## 许可证
私有仓库。
标签:AI风险缓解, DFIR, Kubernetes, 逆向工具