QuyDu/Xavier
GitHub: QuyDu/Xavier
基于 Azure AI Services 的摄像头威胁情报平台,集成武器检测、校园封锁编排、儿童保护案件打包、海事深度搜索及 FBI 执法工作流等公共安全场景。
Stars: 2 | Forks: 1
# XAVIER
**v5.86** | 发布日期:2026 年 7 月 3 日 — *人脸注册强化 + Easy Auth v2 修复 + 部署锁定*
用于驱动摄像机威胁情报的 Azure AI Services 平台:武器检测、校园封锁编排、危害儿童案件打包(包含 NCMEC CyberTipline 暂存 XML)、FBI 执法工作流以及海事深度搜索。基于 Computer Vision、Face API、Speech Services、Translator、Content Safety、Document Intelligence、Azure AI Search (RAG) 和 Azure OpenAI (gpt-5.1) 构建。
## 最新发布 (v5.46)
- **CSRF token 持久化 (v5.44):** `WTF_CSRF_TIME_LIMIT=None` — token 仍然绑定到 session/SECRET_KEY,但不再在 1 小时后过期。长时间运行的管理页面(FBI 同步、批量人脸处理、摄像机仪表板)在标签页长时间打开后不再会出现 `bad_request` 错误。
- **强化的部署重试 (v5.44):** `infra/deploy-app.ps1` 现在会在任何重试之前轮询 Kudu 的完成状态,并在重试之前停止站点并清除损坏的 Oryx tarball。消除了之前导致容器崩溃的并发解压竞争问题(`panic: An error occurred when trying to extract tarball`)。
- **基于角色的路由控制 (v5.43):** 任何经过身份验证的用户都可以查看摄像机并运行人脸识别;只有管理员才能添加/编辑/删除摄像机、NVR、人员或触发训练。
- **Ozolio JPEG 快速通道 (v5.35):** 由 Ozolio JS 播放器支持的网络摄像头聚合器页面会自动解析为底层的 `relay.ozolio.com/pub.api?cmd=snap&oid=` JPEG 快照端点 — 无需 headless browser,无需 HLS 技术栈,仅需 `image/jpeg`。
- **public_stream 增强/对比 (v5.35):** AI 增强/对比的“摄像机”下拉菜单使用统一的 `CameraService.get_snapshot` 助手,因此任何 public_stream 摄像机(Ozolio,直接 HLS/MJPEG/JPEG)都可以被选作源图像。
- **公共流摄像机 (v5.34):** 可将任何开放的网络摄像头 URL(HLS `.m3u8`、MJPEG、RTSP 或直接的 JPEG/PNG 快照)添加为摄像机 — 无需凭据。完整的捕获/处理/增强和自动检测(物体、人脸、武器、FBI 匹配)功能与私有的 RTSP 摄像机完全相同。
- **校园安全:** 多摄像机扫描 + 自动封锁 + 具有自我修复 watchdog 的持久后台监视器 + 案件重新分发。
- **危害儿童:** CSAM 限制的案件打包、证据保管库、NCMEC `Report.xml` 暂存产物、可选的 NCMEC Member API 提交、案件重新分发。
- **海事深度搜索:** 多步骤 pipeline、已签名的升级 webhook、持久的海事自动监视、报告重新分发。
- **FBI 联邦提交:** 已签名的联邦格式 webhook、人员同步、档案导出、重新分发。
- **跨场景时间线:** 聚合的校园 + CAC + 海事 + FBI + 成本事件。
- **监视器设置 UI:** 设置 → 运维选项卡 — 两个监视器的实时状态 + 启动/停止/确认按钮(仅限管理员)。
- **强化:** 扫描端点上基于进程内按主体的 token-bucket 速率限制器(6次/分钟 × 突发 8 次);HTTP 429 + `retry_after_sec`。
- **CI:** GitHub Actions 在每次推送/PR 时运行完整的 pytest 测试套件(`.github/workflows/test.yml`)。
- **演示种子:** `infra/seed-demo.ps1` 生成五个固定 ID 的 Cosmos 演示文档,受 `DEMO_SEED_ENABLED` 控制。
## 部署目标
在任何 Azure 或 Azure Government 订阅中配置自包含的技术栈。资源名称派生自 `-SiteName` 以及基于部署确定的哈希值,因此每个安装都是隔离的。
| | 值 |
|--|--|
| 云端 | `AzureCloud` 或 `AzureUSGovernment` |
| 订阅 | `az login` 当前作用域内的任何订阅 |
| 资源组 | `rg-` |
| 区域 | 默认为 `eastus`(商业版)/ `usgovarizona`(政府版);使用 `-Location` 覆盖 |
| Web App | `app--` |
| URL | `https://app--.azurewebsites.{net,us}` |
| Key Vault | `kv--` |
| Cosmos DB | `cosmos--`(分区 `/file_type`) |
| Azure OpenAI | `oai--` — 模型由 `infra/discover.ps1` 根据区域可用性自动选择(偏好顺序:`gpt-5.1` → `gpt-4.1` → `gpt-4o` → `gpt-35-turbo`)外加 `text-embedding-3-large` |
| Gunicorn | `--workers=1 --threads=8 --worker-class=gthread --timeout=300`(必填 — 存在大量内存中的单例) |
## 部署
```
# 完整部署(约 10-20 分钟,自动重试 3 次 — Oryx CDN 通常会在第 1-2 次尝试时出现异常)
pwsh -NoProfile -File infra/deploy.ps1 -SiteName -AzureGov -UpdateSite -NoPrompts
# 验证线上版本(从你的部署输出中解析 URL,或者从应用中读取它)
$webApp = az webapp list -g rg- --query "[0].defaultHostName" -o tsv
(iwr "https://$webApp/api/version" -UseBasicParsing).Content
```
`SiteName` 是简短的基础名称(例如 `myapp`),而不是完整的 webapp 名称。Bicep 模板会附加一个确定的哈希值,因此完整的 webapp 名称为 `app--`。
可选标志:
- `-PreferModel ` — 优先尝试特定的 OpenAI 模型(例如 `gpt-4.1`)
- `-PinModel`(与 `-UpdateSite` 一起使用) — 保留当前部署的模型;打印差异但跳过替换
## 测试
```
cd webapp
python -m pytest tests/ -q
```
当前测试套件:**155 个测试通过**。CI 在推送/PR/手动调度时运行相同的命令。
## 配置标志 (App Settings)
| 设置 | 默认值 | 用途 |
|---|---|---|
| `THREAT_ACTIONS_ENABLED` | off | webhook 分发(封锁、LE、CAC、海事)的主开关。如果没有开启,webhook 将被构建、签名和审计,但永远不会被发送(dry-run)。 |
| `NOTIFY_SMS_ENABLED` | `false` | ACS 封锁 SMS 群发的主开关。关闭 → 消息会被构建但永远不会发送(无网络)。需要 `ACS_CONNECTION_STRING`(Key Vault)+ `ACS_SMS_FROM_NUMBER`。 |
| `ACS_SMS_FROM_NUMBER` | _(空)_ | 用于封锁 SMS 的已验证 ACS 发送方电话号码(E.164 格式,例如 `+18335551234`)。 |
| `SCHOOL_AUTO_WATCH_ENABLED` | `false` | 在 pod 启动时自动启动校园监视器 |
| `SCHOOL_AUTO_WATCH_INTERVAL_SEC` | `60` (15..3600) | 运行频率 |
| `SCHOOL_AUTO_WATCH_COOLDOWN_SEC` | `600` (60..86400) | 封锁后冷却时间 |
| `MARITIME_AUTO_WATCH_ENABLED` | `false` | 自动启动海事监视器 |
| `MARITIME_AUTO_WATCH_INTERVAL_SEC` | `300` (60..3600) | 运行频率 |
| `MARITIME_AUTO_WATCH_COOLDOWN_SEC` | `1800` (60..86400) | 升级后冷却时间 |
| `DEMO_SEED_ENABLED` | `false` | 允许 `/ai/demo-seed/*` 修改 Cosmos |
| `XAVIER_DISABLE_CSRF` | 未设置 | 仅限测试/开发 |
## Key Vault 机密
- `threat-webhook-signing-secret`
- `school-lockdown-webhook-url`
- `law-enforcement-webhook-url`
- `child-protection-webhook-url`
- `maritime-alert-webhook-url`
- `ncmec-member-api-url` *(可选,v5.33 — 启用 `/ai/cac/cases//ncmec/submit`)*
- `ncmec-member-api-key` *(可选,v5.33)*
## 顶级端点
| 路径 | 认证 | 用途 |
|---|---|---|
| `/api/version`, `/api/health` | 公开 | 存活状态 + 版本 |
| `/realtime/api/lockdown` | session + CSRF | 手动启动封锁(按钮标签:**INITIATE LOCKDOWN**) |
| `/ai/threat/scan` | session | 统一威胁扫描 |
| `/ai/school/sweep` | session(速率限制) | 校园多摄像机扫描 |
| `/ai/school/cases//redeliver` | admin | 重放校园封锁 webhook |
| `/ai/school/watch/{status\|start\|stop\|acknowledge}` | 状态公开,修改操作需 admin | 校园自动监视 |
| `/ai/maritime/analyze` | session(速率限制) | 海事深度搜索 |
| `/ai/maritime/reports//redeliver` | admin | 重放海事 webhook *(v5.33)* |
| `/ai/maritime/watch/{status\|start\|stop\|acknowledge}` | 状态公开,修改操作需 admin | 海事自动监视 |
| `/ai/cac/scan` | session(速率限制) | CAC 扫描(在证据包中打包 NCMEC XML) |
| `/ai/cac/cases//redeliver` | admin | 重放 CAC webhook |
| `/ai/cac/cases//ncmec/submit` | admin | 可选的 NCMEC Member API 提交 *(v5.33,默认处于暂存状态)* |
| `/ai/timeline`, `/ai/timeline/events` | admin | 跨场景时间线 |
| `/ai/demo-seed/{status\|run\|clear}` | admin + 标志 | 演示数据集填充/清除 |
| `/ai/fbi/*`, `/evidence/*` | admin | 联邦提交 + 证据保管库 |
| `/settings` → 运维选项卡 | admin | 监视器控制 UI *(v5.33)* |
| `/cameras/api/add` | admin | 添加摄像机(现已接受开放网络摄像头的 `manufacturer="public_stream"` + `stream_url` — *v5.34*) |
## Cosmos `file_type` 值
`fbi_submission`, `maritime_intel_report`, `child_protection_case`, `school_safety_case`, `evidence_package`, `school_watch_state`, `maritime_watch_state`,以及现有的 `analysis_result`, `cost_event`, `audit_log`, `chat_session` 等。
## 发布历史
| 版本 | 标题 |
|---|---|
| v5.22 | 海事情报(视觉 prompt + 自动升级) |
| v5.23 | CAC 证据打包程序 |
| v5.24 | FBI 联邦提交 |
| v5.25 | 海事深度搜索 |
| v5.26 | 危害儿童 |
| v5.27 | 校园安全编排 |
| v5.29 | 校园自动监视 |
| v5.30 | 跨场景时间线 + service_metadata |
| v5.31 | 监视器持久化 + 演示种子 |
| v5.32 | 强化 + 覆盖率 + 文档(速率限制、海事自动监视、NCMEC XML、CI、封锁文案) |
| v5.33 | 积压任务清理(海事重新分发、NCMEC Member API 选择性开启、监视器设置 UI) |
| v5.34 | 公共流摄像机(开放的网络摄像头 URL,具备完整的捕获/处理/增强 + 自动检测功能) |
| v5.35 | 开放网络摄像头聚合器(Ozolio JPEG 快速通道 + public_stream 增强/对比) |
| v5.43 | 基于角色的路由控制(管理员白名单 + 查看者角色) |
| v5.44 | 强化的部署重试 + 禁用 CSRF token 过期 |
| v5.45 | 人脸识别加速:即时姓名渲染、持久的 HTTP 会话、list_persons 缓存、8 倍并行 FBI 注册 |
| **v5.46** | **安全强化:SQL injection 防护、限制 localhost 绕过、有界人脸缓存 (LRU)、从 os.environ 中移除机密、在生产环境中阻断 CSRF 禁用、OpenAI 会话重用、限制 Retry-After、摄像机字段白名单、X-Request-ID 验证** |
## 架构注意事项
- **必需单一 Gunicorn worker** — JobQueue、alert_bus、watchers 和速率限制 bucket 都在内存中。
- **CSRF** 会阻止未经身份验证的 POST 请求;可以通过 `webapp/app/__init__.py` 中的 `csrf_ext.exempt(view_fn)` 豁免。
-Front Door 230 秒超时** 驱动了异步任务设计;长时间扫描会返回一个 job-id。
- **JobQueue 状态:** `succeeded`(不是 `completed`)。
- **威胁协调器 webhook 控制:** 在任何 webhook 离开 pod 之前,必须开启 `THREAT_ACTIONS_ENABLED=true`。
- **速率限制器:** 基于 pod、基于主体的 token bucket。返回 HTTP 429 + `retry_after_sec`。
- **NCMEC XML** 默认设为 `staging="true"` 并打包到 CAC 证据中。`/ai/cac/cases//ncmec/submit` Member API 调用是 *可选的* — 如果 Key Vault 中没有 `ncmec-member-api-url`+`ncmec-member-api-key`,它会以 `status="not_configured"` 短路返回,且不执行任何网络 I/O。
- **监视器状态文档** 使用其 `file_type` 作为分区键并带有固定的 `id`,因此 upsert 会直接替换。
- **演示种子** 受 `DEMO_SEED_ENABLED=true` 控制 — 如果没有该设置,永远不会填充数据。
## 仓库结构
```
azure-discovery/ # picks best-available services/models per region
infra/ # Bicep + PowerShell deploy / discover / teardown
webapp/ # Flask app
app/
routes/ # blueprints (ai, api, realtime, cameras, results, …)
services/ # singletons: openai_svc, vision, face, cosmos, school_watch,
# maritime_watch, child_protection, school_safety, ncmec,
# rate_limit, threat_orchestrator, evidence_packager, …
templates/ # Bootstrap + Jinja
static/ # css/js/icons
tests/ # pytest suite (155 tests, runs in CI)
.github/workflows/ # CI (pytest)
```
## 核心场景(均已上线)
1. **校园武器检测 + 封锁编排** — v5.27 / 29 / 31 / 32
2. **危害儿童** — v5.26 / 32 / 33
3. **FBI / 执法工作流** — v5.24
4. **海事检测** — v5.25 / 32 / 33
## 安全 / 机密处理
- **此仓库中不存储任何机密。** 所有凭据(Cosmos 密钥、OpenAI 密钥、AAD client secret、webhook 签名机密、NCMEC API key、FLASK_SECRET_KEY)都位于 Azure Key Vault 中,并通过 App Settings 中的 Key Vault 引用传递给 App Service。
- **`.env` 已被 git 忽略。** 仅跟踪了 [`webapp/.env.example`](webapp/.env.example) \u2014 它记录了变量 *名称*,其值为空,用于本地开发。
- **构建产物(`*.zip`)已被 git 忽略。** 由 `az webapp up` 生成的部署 zip 仅包含仓库源代码;它们不会被提交。如果 Microsoft Purview / DLP 在 OneDrive 中将它们标记为敏感信息,那是针对占位符字符串的误报(例如 `services/camera.py` 中的 RTSP URL 构建器 `password=\"{password}\"`,或者 `.env.example` 中的环境变量 *名称*)。删除本地 zip;它会在下次部署时重新生成。\n- **建议:** 将此工作区排除在 OneDrive 同步之外。GitHub 上的 git 远程仓库是规范的数据源;OneDrive 同步是多余的,并且会定期对瞬态构建产物触发 DLP 扫描。\n\n---\n\n## 许可证\n\n微软内部项目。保留所有权利。
标签:AI合规, Azure云服务, Flask, 威胁情报, 开发者工具, 执法与应急响应, 智慧安防, 计算机视觉, 逆向工具, 面部识别