MindStone-Agent/aegis-dashboard
GitHub: MindStone-Agent/aegis-dashboard
一款 OT/ICS 威胁情报只读仪表板,将 AI Agent 生成的结构化数据渲染为六大操作面板并集成实时 AI 分析师聊天。
Stars: 1 | Forks: 0
# AEGIS — OT/ICS 威胁情报仪表板
一个暗黑模式的战术界面,用于展示可操作的 OT/ICS 威胁情报,并配有实时的 AI 分析师聊天面板。作为 MindStone 平台 Phase 1 的一部分构建。
**版本:** 1.0 — Phase 1 前端原型(交付于 2026-03-18)
**状态:** 生产级前端;Phase 2(后端代理 + WebSocket)已规划。
## 功能简介
Aegis Dashboard 是一个单页应用,它读取由 MindStone Threat Analyst AI Agent 生成的五个结构化 JSON 文件,并将它们渲染到六个专门设计的操作面板中。其美学和信息密度源自专业的 SIEM/SOC 工具:Dragos Platform、暗黑模式 Splunk、Elastic Security。右侧聊天面板连接到 Open WebUI API(通过 SSE token 流式传输),并在未配置 API 时优雅降级到演示模式。
仪表板是只读的。不会向 JSON 文件写入任何数据。
## 技术栈
| 层级 | 技术 | 版本 |
|-------|-----------|---------|
| 框架 | React | 18.3 |
| 构建工具 | Vite | 6.x |
| 语言 | TypeScript | 5.7 strict |
| UI 状态 | Zustand | 5.x |
| 服务端状态 / 轮询 | TanStack Query | 5.x |
| 样式 | Tailwind CSS | 3.x |
| Schema 验证 | Zod | 3.x |
| Markdown 渲染 | react-markdown + rehype-highlight | 9.x / 7.x |
| 图标 | lucide-react | 0.469 |
| 日期格式化 | date-fns | 4.x |
| ID 生成 | uuid | 11.x |
没有使用外部组件库。所有面板组件均基于 Aegis 设计 token 系统定制构建。
## 快速开始
### 前置条件
- Node.js 18+ 和 npm
- 现代浏览器(推荐使用 Chrome 或 Edge;Phase 1 不支持 Safari)
### 安装与运行
```
# 从项目根目录
npm install
# 启动开发服务器 (http://localhost:5173)
npm run dev
```
仪表板会立即在演示模式下打开——无需配置。所有五个面板将使用 `public/data/` 中真实的 OT/ICS 模拟数据进行渲染。
### 生产环境构建
```
npm run build
```
输出到 `dist/`。使用任何静态文件服务器提供服务,或运行 `npm run preview` 进行生产环境包的本地预览。
## 配置
复制示例环境文件并根据需要进行编辑:
```
cp .env.example .env.local
```
| 变量 | 默认值 | 描述 |
|----------|---------|-------------|
| `VITE_OPENWEBUI_URL` | _(空)_ | Open WebUI / MindStone 实例的 Base URL(例如 `http://localhost:3000`)。**留空将以演示模式运行。** |
| `VITE_OPENWEBUI_API_KEY` | _(空)_ | Open WebUI API 的 Bearer token。仅在开发环境中使用;Vite 代理会注入它,因此在生产环境中该密钥永远不会到达浏览器。 |
| `VITE_MODEL_ID` | `threat-analyst` | 在聊天补全请求中传递的 Model ID。 |
此处设置的环境变量仅为开发环境的默认值。在运行时,这三个值也可以通过应用内的 Settings 面板进行配置(持久化存储在 `localStorage` 中 `aegis-ui-store` 键下)。
## 项目结构
```
aegis-dashboard/
├── public/
│ └── data/ # Mock JSON data files (served as static assets)
│ ├── intel-feed.json
│ ├── threat-groups.json
│ ├── investigations.json
│ ├── daily-summary.json
│ └── system-health.json
├── src/
│ ├── App.tsx # TanStack Query provider + AppShell root
│ ├── main.tsx # React DOM entry point
│ ├── index.css # Global styles (scanline texture, animations)
│ ├── schemas/ # Zod schemas — single source of truth for all types
│ │ ├── intel-feed.ts
│ │ ├── threat-groups.ts
│ │ ├── investigations.ts
│ │ ├── daily-summary.ts
│ │ └── system-health.ts
│ ├── hooks/ # Custom React hooks
│ │ ├── useIntelFeed.ts
│ │ ├── useThreatGroups.ts
│ │ ├── useInvestigations.ts
│ │ ├── useDailySummary.ts
│ │ ├── useSystemHealth.ts
│ │ └── useStreamingChat.ts
│ ├── store/
│ │ └── uiStore.ts # Zustand store (chatOpen, settingsPanelOpen, settings)
│ ├── lib/
│ │ ├── sort.ts # Sorting and deduplication utilities
│ │ ├── staleness.ts # Staleness badge computation
│ │ └── demoConversation.ts # Pre-loaded demo chat messages
│ └── components/
│ ├── layout/
│ │ ├── AppShell.tsx # Root layout; keyboard shortcuts; offline detection
│ │ ├── TopNav.tsx # 48px header; last-updated timestamp; refresh/settings
│ │ ├── MainCanvas.tsx # Left intel column + right chat pane split
│ │ └── FooterBar.tsx # 40px fixed footer; system health widget
│ ├── panels/
│ │ ├── IntelFeedPanel.tsx + IntelFeedItem.tsx
│ │ ├── ThreatGroupPanel.tsx + ThreatGroupCard.tsx
│ │ ├── InvestigationsPanel.tsx + InvestigationCard.tsx
│ │ └── DailySummaryPanel.tsx
│ ├── chat/
│ │ ├── ChatPane.tsx
│ │ ├── MessageThread.tsx
│ │ ├── MessageInput.tsx
│ │ ├── AgentMessage.tsx
│ │ ├── UserMessage.tsx
│ │ └── DemoModeOverlay.tsx
│ └── shared/
│ ├── PriorityBadge.tsx
│ ├── StatusBadge.tsx
│ ├── ConfidenceBadge.tsx
│ ├── StalenessBadge.tsx
│ ├── SourceChip.tsx
│ ├── CveTag.tsx
│ ├── SkeletonPanel.tsx
│ ├── ErrorBoundary.tsx
│ ├── OfflineBanner.tsx
│ └── SettingsPanel.tsx
├── .env.example
├── tailwind.config.ts
├── vite.config.ts
├── tsconfig.json
└── package.json
```
## 六大面板
### 1. 威胁情报流 (`IntelFeedPanel`)
渲染来自 `intel-feed.json` 的条目,按 HIGH → MEDIUM → LOW 优先级排序。每个条目都可以展开以显示完整的 OT 相关性评估和分析师笔记。CVE 标签直接链接到 NVD 条目。在新的轮询周期中出现的条目会闪烁简短的高亮动画。
**数据结构概览:** `id`、`priority` (HIGH/MEDIUM/LOW)、`title`、`source`、`url`、`publishedAt`、`vendors[]`、`cves[]`、`otRelevance`、`analystNote`、`updatedAt`。
### 2. 威胁组织追踪器 (`ThreatGroupPanel`)
被追踪威胁组织的卡片网格。在大屏幕上为两列,在小屏幕下为单列。每张卡片显示 nexus、状态 (ACTIVE/SILENT/PREPOSITIONING)、目标行业、ICS ATT&CK TTPs(带有“+N 更多”切换)、置信度评级以及可选的分析师笔记。
**数据结构概览:** `name`、`nexus`、`status`、`lastActivityDate`、`targetSectors[]`、`ttps[]`、`confidence` (HIGH/MEDIUM/LOW)、`notes`。
### 3. 活跃调查 (`InvestigationsPanel`)
仅显示来自 `investigations.json` 的 ACTIVE 调查。每张卡片包含一个 9 阶段的 MITRE ATT&CK for ICS 阶段追踪器(从 INITIAL_ACCESS 到 IMPACT)、一个 fill/current/future 视觉进度条、带有置信度评级的假设,以及建议的后续行动列表。
**数据结构概览:** `id`、`scenarioName`、`sector`、`stage`(9 个 ATT&CK ICS 阶段之一)、`hypotheses[]`(hypothesis + confidence + notes)、`nextActions[]`、`analystNotes`、`status` (ACTIVE/CLOSED)。
### 4. 每日情报摘要 (`DailySummaryPanel`)
显示 AI Agent 的每日摘要报告。通过 Previous/Next 导航浏览 `daily-summary.json` 中的历史记录(按最新优先排序,纯内存操作——导航时不会触发网络重新获取)。显示已检查的来源、按相关性排名前 3 的发现,以及当天触发的任何警报。
**数据结构概览:** `date` (YYYY-MM-DD)、`sourcesChecked[]`、`sourceCount`、`topFindings[]`(rank 1–3,description,source)、`alertsTriggered[]`(title,severity,triggeredAt)。
### 5. 系统健康小组件 (`SystemHealthWidget`)
固定在 40px 的页脚处。一览显示 MindStone 平台的运行状态:上次 dream cycle 运行、向量库文档计数、剩余的 Brave Search 配额(归零时变红),以及 Anthropic 和 OpenAI 的 API 状态点。悬停或聚焦任何状态点会显示一个工具提示,其中包含上次检查的时间戳和错误信息(如果存在)。可以通过 Tab 焦点使用键盘访问工具提示。
**数据结构概览:** `lastDreamCycle` (runAt, chunksStored, status)、`vectorStore` (totalDocuments, lastUpdated)、`braveSearch` (estimatedQueriesRemaining, dailyQuota, queriesUsedToday)、`apis.anthropic`、`apis.openai`、`updatedAt`。
### 6. 实时聊天面板 (`ChatPane`)
可折叠的右侧聊天界面。在大屏幕断点处宽度为 `w-80` (320px),在 xl 断点处为 `w-96` (384px)。在移动设备(`md` 断点以下)上隐藏。使用 `fetch()` + `ReadableStream` 通过 SSE 流连接到 Open WebUI API —— 不使用 EventSource 是因为它不支持 POST 请求。折叠时,面板会显示一个向右的箭头(指示展开方向)、一个放大的“ANALYST CHAT”标签,以及当会话包含消息时的脉冲活动指示器圆点。
面板顶部的会话选择下拉菜单列出了最近的会话。在演示模式下,提供三个预加载且包含完整消息历史的会话。在实时模式下,会从 `GET /api/v1/chats/` 获取会话。
## 模拟数据
所有五个 JSON 文件都位于 `public/data/` 中,并作为 Vite 静态资源提供服务。它们包含相对于参考日期 2026-03-18 的真实的 OT/ICS 领域情报:
| 文件 | 内容 |
|------|----------|
| `intel-feed.json` | 来自 CISA、Dragos、CloudSEK、Claroty 等的 11 条公告。包含多个 HIGH 优先级项目,包括 CVE-2024-43647 (Siemens S7-1500)。 |
| `threat-groups.json` | 6 个被追踪的组织:VOLTZITE、ELECTRUM、KAMACITE、AZURITE、PYROXENE、SYLVANITE —— 源自公开的 Dragos 威胁组织命名约定。 |
| `investigations.json` | 4 项调查:2 个 ACTIVE(一个早期阶段,一个晚期阶段),1 个 CLOSED,以及 1 个用于增加多样性的额外调查。 |
| `daily-summary.json` | 截至 2026-03-18 的连续 7 份每日摘要。 |
| `system-health.json` | 反映 MindStone 平台状态的单对象文件。 |
要使用真实的 Agent 输出仪表板,请用 MindStone Threat Analyst AI Agent 生成的 JSON 替换这些文件。这些文件必须继续通过 `src/schemas/` 中的 Zod schema 验证。
轮询间隔默认为 30 秒,可在 Settings 面板中进行配置(范围:10–300 秒)。
## Open WebUI 聊天集成
### 演示模式(默认)
当未设置 `VITE_OPENWEBUI_URL`,或 Settings 面板中的 Open WebUI URL 字段为空时,会自动激活演示模式。在演示模式下:
- 显示分析师与 AI Agent 之间的预加载对话 (`src/lib/demoConversation.ts`)
- 会话下拉菜单中提供三个演示会话(VOLTZITE 分析、GRAPHITE IOC、公告审查)
- 发送消息会触发模拟的逐字流式响应,解释如何连接实时 endpoint
- 不会向任何 API 发起网络调用
### 连接到实时的 Open WebUI 实例
1. 点击顶部导航栏中的 **SETTINGS**(或在输入框外任意位置按 `S` 键)
2. 输入您的 Open WebUI URL(例如 `http://localhost:3000`)
3. 输入您的 API key
4. (可选)更改 Model ID(默认:`threat-analyst`)
5. 点击 **SAVE SETTINGS**
Vite 开发服务器将所有 `/api` 请求代理到配置的 Open WebUI URL,并在服务端注入 Authorization 标头,因此 API key 不会暴露在浏览器的网络请求中。
设置会持久化存储在 `localStorage`(键:`aegis-ui-store`)中,并在页面重新加载后依然保留。
### SSE 流协议
聊天 hook (`useStreamingChat`) 发送 `POST /api/chat/completions` 请求并带有 `"stream": true`。它将响应体作为 `ReadableStream` 读取,解析 `data:` 行,并在到达时将 delta token 追加到 Agent 消息状态中。收到 `data: [DONE]` 时,它会触发 `POST /api/chat/completed` 来持久化会话(即发即弃,带有一次静默重试)。在流错误或用户取消时,该消息会被标记为 `[stream interrupted]`,并跳过 completed 调用。
## 键盘快捷键
| 快捷键 | 操作 |
|----------|--------|
| `R` | 刷新所有数据(使所有 TanStack Query 缓存失效) |
| `C` | 切换聊天面板的打开/关闭状态 |
| `Ctrl+Enter` | 发送聊天消息(当输入框获得焦点时) |
| `Escape` | 关闭 Settings 面板 |
当焦点位于 `INPUT` 或 `TEXTAREA` 元素内时,快捷键 `R` 和 `C` 会被禁用。
## 无障碍设计
仪表板致力于符合 WCAG 2.1 AA 标准。作为原型后 UX 审查 (2026-03-18) 的一部分,实现了以下功能:
- **非颜色徽章编码**:所有四个徽章组件(`PriorityBadge`、`StatusBadge`、`ConfidenceBadge`、`StalenessBadge`)除了颜色外,还包含图标和形状的冗余。没有状态信号仅依赖于颜色。这确保了色盲分析师(例如,绿色弱视影响约 8% 的男性)能够正确读取 HIGH/MEDIUM/LOW、ACTIVE/SILENT/PREPOSITIONING 和 staleness 状态。
- **Settings 面板焦点陷阱**:Settings 面板 (`SettingsPanel`) 实现了完全的键盘焦点陷阱,符合 ARIA Modal Dialog 模式(WCAG 2.1 SC 2.1.2)。打开时,焦点移动到对话框内的第一个可聚焦元素;关闭时,焦点返回到 TopNav 中触发它的 Settings 按钮。
- **文本对比度 — `aegis-text-muted`**:弱化文本颜色从 `#4b5563`(对比度约 3.1:1)提高到了 `#6b7280`(与 `#0d1117` 的对比度约 4.6:1),满足 WCAG AA 普通文本 .5:1 的要求。该 token 贯穿应用于时间戳、元数据行、TTP 项目符号、会话标签和系统健康指标。
- **TopNav 警报徽章**:当轮询周期中出现新的 HIGH 优先级情报项时,TopNav 中的盾牌图标上会出现一个闪烁的红色徽章。徽章计数反映了自分析师上次访问 Intel Feed 面板以来未读的 HIGH 项目。通过 `uiStore` 的未读追踪实现。
- **聊天面板折叠状态**:修正了折叠状态下聊天面板箭头的方向(现在指向右侧,即展开方向)。增加了“ANALYST CHAT”垂直标签的字体大小以提高可读性。当前会话包含消息时会出现一个脉冲活动指示器圆点,这为分析师提供了一个无需事先了解其存在即可打开面板的理由。
- **System Health 工具提示 — 键盘访问**:`SystemHealthWidget` 中的 `Tooltip` 包装器现在可以通过 `tabIndex={0}` 获得 `onFocus`/`onBlur` 处理程序聚焦,镜像了现有的 `onMouseEnter`/`onMouseLeave` 行为。工具提示内容(上次检查时间戳、配额值、错误消息)可供仅使用键盘和屏幕阅读器的用户访问。
## 弹性与边缘情况
- **面板级 Error boundaries**:每个面板将其内容包装在 `ErrorBoundary` 中。一个面板中的 Zod 解析失败或网络错误不会影响其他面板。
- **加载骨架**:在获取数据时显示结构性微光骨架(而不是加载转圈)。
- **离线横幅**:当 `navigator.onLine` 为 false 时,会在 TopNav 上方渲染一个 `OfflineBanner` 组件,并带有最后一次检测到连接的时间戳。
- **Staleness 徽章**:在渲染时使用 `Date.now()` 与每个 JSON 条目中的 `updatedAt` 字段进行对比计算 —— 不存储 staleness 状态。
- **减少动态效果**:所有动画均通过 Tailwind 的 `motion-safe:` 变体遵循 `prefers-reduced-motion` 设置。
## 数据文件 Schema 参考
所有 TypeScript 类型均从 Zod schema 推断 —— 从不手动复制。这些 schema 位于 `src/schemas/` 中,是 JSON 文件必须包含什么内容的权威事实来源。
```
IntelFeed = z.array(IntelFeedEntrySchema)
ThreatGroups = z.array(ThreatGroupEntrySchema)
Investigations = z.array(InvestigationEntrySchema)
DailySummary = z.array(DailySummaryEntrySchema)
SystemHealth = SystemHealthSchema (single object, not array)
```
解析失败(无效的 JSON 或 schema 不匹配)会触发面板级 Error boundary,该边界会渲染一个内联错误状态,而不会导致仪表板的其余部分崩溃。
## Phase 2 路线图
以下内容明确不在 Phase 1 的范围内,已规划在 Phase 2 实现:
- Node.js/Express 后端代理(移除了对 Vite 开发代理的需求;在生产环境中保护 API key)
- REST 推送 endpoint 以取代文件轮询
- WebSocket 实时更新 (Phase 3)
- Docker Compose 部署配置
- 身份验证 / 登录界面
- Vitest 单元测试、React Testing Library 组件测试和 Playwright E2E 测试(从 Phase 1 推迟)
## 相关文档
| 文档 | 路径 |
|----------|------|
| 插件 / 安装指南 | `PLUGIN.md` |
| 数据契约 (Zod schemas) | `src/schemas/` |
| 配套角色包 | `mindstone/cti-analyst-lite` |
标签:PKINIT, React, SIEM/SOC, Syscalls, 仪表盘, 前端可视化, 威胁情报, 工控安全, 开发者工具, 自动化攻击