docs(readme): 新增系统技术架构章节 + Mermaid 架构图

- 双图架构(探索图+资产图)+ 锚点连接、总体分层图与组件表
- 引擎意图闭环时序图、worker 过程级信息交换图、planner 多轮共享
  todolist 稳定攻击链路图(5 张 Mermaid,GitHub 原生渲染,无 emoji)

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Autumn-27andClaude Opus 4.8 committed 2026-08-09 01:23:59 -04:00
1 parent 6bffd491ee
commit 75ca97feb1
1 file changed
+171 -1
+171 -1
View File
@@ -142,10 +142,180 @@ CGO_ENABLED=0 go build -tags embedui -o artex ./cmd/artex
- 测试:`go test ./...`
- Mock 预览(无后端):`cd web && NEXT_PUBLIC_MOCK=1 npm run dev`
---
## 系统技术架构
ARTEX 是一套 **LLM 多 agent 驱动的自主渗透系统**:Go 单体后端(内嵌 Next.js 前端)+ PostgreSQL,agent 能力由 [`norma`](https://github.com/Autumn-27/norma) SDK 提供(`agentcore` / `tool` / `permission` / `harness` / `memory` / `transcript`)。核心是**双图架构**,以及围绕它的两条自主性机制:**worker 间过程级信息交换**与 **planner 多轮共享 todolist 稳定攻击链路**。
### 总体分层
```mermaid
flowchart TB
subgraph FE["前端 Next.js(go:embed 内嵌单二进制)"]
UI["仪表盘 · 任务 · 资产 · 覆盖图 · 流量 · 工作空间 · 系统配置"]
end
subgraph SRV["server(Go net/http)"]
API["REST /api/* JWT 鉴权 SSE"]
ENG["engine 调度循环"]
MGR["Manager 任务/引擎/store 生命周期"]
end
subgraph AG["agent(norma SDK)"]
GO["goals 目标分解 + 提取范围"]
PL["planner 规划者(唯一意图生成者)"]
WK["worker 执行者 ×N"]
MA["mainagent 人在环路"]
end
subgraph DB["PostgreSQL"]
AGRAPH["资产图 assets / companies / task_scope"]
EGRAPH["探索图 exploration_nodes / anchors / activity"]
end
subgraph SUB["支撑子系统"]
PROXY["流量记录代理 MITM + CA 留痕"]
GUARD["guard / intercept 工具审批门"]
ENR["enrich DNS / HTTP 异步补全"]
EXT["MCP · skills · memory · report"]
end
UI -->|HTTP| API
API --> MGR --> ENG
ENG --> PL
ENG --> WK
API --> MA
API --> GO
PL --> DB
WK --> DB
MA --> DB
GO --> DB
WK -->|"Bash / HTTP 全程留痕"| PROXY
WK --> GUARD
WK --> ENR
PL -.-> EXT
WK -.-> EXT
MA -.-> EXT
```
| 层 | 职责 |
| --- | --- |
| **前端** | Next.js 静态导出,`go:embed` 内嵌进单二进制;可视化任务/资产/探索链路/覆盖图,人在环路对话 |
| **server** | `net/http` 路由 + JWT 鉴权 + SSE;`Manager` 托管任务、引擎、DB store 的生命周期 |
| **engine** | 每任务一个 `plannerLoop` + N 个 worker goroutine;意图领取、超时/暂停/drain |
| **agent** | goals / planner / worker / mainagent,`ToolSet` 把双图暴露成 LLM 工具 |
| **db** | 双图的 Postgres 落地(pgx);schema 随 `go:embed` 每次启动幂等建表 |
| **支撑** | 记录型 MITM 代理、审批门、异步补全、MCP/技能/记忆/报告 |
### 双图架构:探索图 + 资产图
系统把「**目标是什么**」和「**测到了什么程度**」拆成两张相互独立、又通过锚点相连的图:
- **资产图(Asset Graph,全局共享)**:跨任务同一份的资产真值库。节点为 `root_domain / subdomain / ip / service / app / endpoint`,归属公司;域名→子域→服务→端点的父子关系与去重 key 全部由程序计算,agent 只提交原始信息。
- **探索图(Exploration Graph,每任务独立)**:一次任务的“思考与推进”过程。节点为 `goal(目标)/ intent(意图)/ fact(事实)/ finding(漏洞)/ hint(提示)`,靠 `spawns / derived_from / yields / proves` 等边连成**血缘链**,回答“哪个方向派生自哪些事实、产出了什么”。
- **两图靠锚点相连**:`exploration_anchors(node_id, asset_id)` 把意图/事实/漏洞锚定到具体资产上——于是既能从“探索方向”看它打的是哪些资产,也能从“某个资产”反查它在本任务被哪些意图测过、得出过哪些事实。这也支撑了**资产测试覆盖度**与**资产覆盖图**(范围内资产 + 已测高亮)。
```mermaid
flowchart LR
subgraph EG["探索图(每任务独立 · 推进链)"]
direction TB
G["goal 目标"]
I1["intent 意图 A"]
F1["fact 事实"]
I2["intent 意图 B"]
FD["finding 漏洞"]
G -->|spawns| I1
I1 -->|yields| F1
F1 -->|derived_from| I2
I2 -->|proves| FD
end
subgraph AG["资产图(全局共享 · 真值库)"]
direction TB
RD["root_domain"]
SD["subdomain"]
SV["service"]
EP["endpoint"]
RD --> SD --> SV --> EP
end
I1 -. anchor .-> SD
F1 -. anchor .-> SV
I2 -. anchor .-> EP
FD -. anchor .-> EP
```
> 分工:**planner** 读探索图态势、判目标、只在有未覆盖的新方向时派**意图**进 frontier;**worker** 领**一条意图**、用真实工具执行、把新资产/事实/漏洞写回两图后即停。资产图是共享事实,探索图是每任务的推进链。
### 引擎与意图生命周期(一次探索的闭环)
引擎是**事件驱动**的闭环:图一变就唤醒 planner,planner 派意图,worker 领意图执行并写回,写回又触发下一轮——直到目标被证明(`prove_goal`)。
```mermaid
sequenceDiagram
autonumber
participant EV as 图变更 debounce
participant P as planner
participant FR as frontier 意图队列
participant W as worker
participant PX as 记录代理
participant DB as 双图 + activity
EV-->>P: 唤醒
P->>DB: 读态势(graph_overview 预取 + coverage/scope)
P->>FR: 派 0..N 个意图(带 asset_ids)
Note over P,FR: 大多数唤醒派 0 个——无新方向即结束
W->>FR: claimNext 领一条意图
W->>DB: 取意图 asset_ids 的原始资产作为初始信息
W->>PX: 真实工具执行(Kali / Bash / HTTP)
PX-->>W: 响应(全程留痕 + CA 验证)
W->>DB: 写回 fact / asset / finding + 每步 activity
DB-->>EV: 图变更
EV-->>P: 再次唤醒(闭环)
```
### worker 间的过程级信息交换
一次深入的探索里,很多有价值的观察(某个报错、某段响应、某个隐藏参数)出现在一个 worker 的**执行过程**中,却未必被写成正式 fact。为避免重复劳动、让链路上的 worker 能站在彼此的肩膀上,worker 具备**跨 work 检索过程**的能力:
- `search_all_worker_traces(q)`:在**本任务其他 work 的执行过程**里按关键字检索(自动排除自己这条意图的步骤),命中项带 `intent_id`;
- `list_worker_traces` / `get_worker_trace(intent_id, step_ids=[…])`:先看有哪些 work 跑过,再取某个 work 具体几步的完整内容做细节交换。
这样即便探索图上还没有对应的 fact,后续 worker 也能复用他人过程中的观察——**信息在 worker 之间以“执行过程”为粒度流动**,而边界不变(每个 worker 仍只做自己领到的那条意图)。
```mermaid
flowchart LR
WA["worker A(意图 #12)"] -->|"每步 activity"| ACT[("探索图 · activity 过程库")]
WB["worker B(意图 #34)"] -->|"每步 activity"| ACT
WC["worker C(意图 #56)"] ==>|"1) search_all_worker_traces(q)"| ACT
ACT ==>|"2) 命中 A/B 的步骤(排除自己)"| WC
WC ==>|"3) get_worker_trace(id, step_ids)"| ACT
ACT ==>|"4) 返回完整过程内容"| WC
```
### planner 多轮共享 todolist → 稳定的攻击链路
真实攻击链往往是**有前后依赖的多步序列**(如:发现注入点 → 拿到凭据 → 横向 → 提权),一次性把这些并行派下去只会乱套。planner 因此持有一份**按任务保留、跨唤醒共享的规划待办(todolist)**:
- planner 是事件驱动的——图一变就被唤醒,但**每次唤醒是全新会话**;共享的 todolist 让它把一条串行利用链**记录一次**、然后在后续多轮里**按依赖逐步派意图**,而不是把整条链在一轮里全部前置展开;
- 每轮只对「前置步骤已完成、其依赖的 fact 已存在」的下一步派意图,并随进展更新清单(把已被 fact 满足的步骤标完成)。
```mermaid
flowchart TB
subgraph TODO["共享 todolist(按任务保留 · 跨唤醒常驻)"]
direction LR
T1["1 注入点 [已完成]"]
T2["2 取凭据 [进行中]"]
T3["3 横向 [待前置]"]
T4["4 提权 [待前置]"]
T1 -.前置满足.-> T2 -.-> T3 -.-> T4
end
R1["第 1 轮唤醒 派意图①"] --> T1
R2["第 2 轮(①产出 fact) 派意图②"] --> T2
R3["第 3 轮(②产出 fact) 派意图③"] --> T3
```
于是攻击链在“事件驱动 + 无状态会话”的环境下依然**稳定推进、不重复、不错序**——这是 ARTEX 能自主走完多步利用链的关键。
---
## 参考
任务的核心理念来源于:https://github.com/oritera/Cairn
https://github.com/oritera/Cairn
## 许可