威胁画像模块 · Actor Portrait Module¶
Status: shipped (Phase 7, Steps 1–10) Frontend route:
/actorsBackend prefix:/api/v1/actors
10-step iterative upgrade. The flagship "who is this seller?" workspace. Step 3 (Identity Resolution Engine) is the hard core — every other step either feeds into it or surfaces what it builds. Design imperative quoted from the user kicking off Phase 7:
威胁画像一定要专业,切入到点子上,如何通过抓取的信息精准的定位威胁, 这个点非常重要。不能磨棱两可。
1. Module purpose¶
For each canonical adversary (one row in portal_actors), surface
everything we know — and infer everything we can — so the analyst /
律师 / 鉴定中心 can answer:
- Who? — name + aliases + canonical contact registry (微信 / QQ / TG / Discord / 电话 / 邮箱 / 钱包 / 域名 / 用户名)
- What do they do? — 报价图谱、URL 命中、平台分布、地域、活动节律
- How dangerous? — multi-factor 0–100 risk score + radar chart
- Who do they work with? — depth-1 ego graph + 4 桥的 edge evidence
- What lifecycle stage? — active / dormant / closed, auto-inferred
- What changed? — full activity timeline + AI 简报
The output is courtroom-ready evidence packets, not opinion. Every number / claim must be reproducible from the raw rows in the DB.
2. Step ledger¶
| Step | Scope | Deliverable |
|---|---|---|
| 1 | 总览仪表盘 + KPI | GET /actors/stats + 5-tile Hero KPI (高危 / 活跃 / 蛰伏 / 已结案 / 本周新增) + TopRiskActors + PlatformDistribution panels |
| 2 | 详情页全身画像 | GET /actors/:id/related(5 collection bundle)+ 5-tile 跨源 KPI strip + 资产清单 + 社群足迹 |
| 3 | Identity Resolution Engine | portal_actor_identifiers + _merge_candidates + _audit 三张表 + 7 endpoints + 合并审核工作台 |
| 4 | 多源信号融合 | GET /actors/:id/sources 一遍 pass 聚合:联系方式注册表 / 报价图谱 / URL / 地域 / 平台 / 活动节律 |
| 5 | 量化风险评分引擎 | GET /actors/:id/risk-score 六因素加权 0–100 + 雷达图 + 每因素 reason 痕迹 |
| 6 | 关系网络图 | GET /actors/:id/network 四桥 (指纹 / 私服 / 社群 / 共同目标) + 纯 SVG force-directed 图 |
| 7 | 富化 + 生命周期推断 | POST /actors/:id/enrich 派生 primary_* + 自动 active→dormant→closed |
| 8 | 活动流 + AI 简报 | GET /actors/:id/activity(5 源 union)+ GET /actors/:id/ai-summary(actor-fusion/v1 templated) |
| 9 | 批量动作 + 观察名单 | portal_actor_watchlists 表 + watch toggle + watchlist page + bulk-enrich / bulk-status / CSV export |
| 10 | 文档 + e2e + 部署 | 本文档 + portal routes test + 部署 ai-astraweb + 同步 docs.astraeye.ai |
3. Identity Resolution Engine(Step 3 核心)¶
3.1 数据模型¶
portal_actor_identifiers
UNIQUE (tenant_id, kind, value) ← 闸门
kind ∈ {wechat, qq, telegram, discord, phone, email,
wallet_btc, wallet_eth, wallet_trc20, wallet_generic,
domain, domain_registrant_email, username}
occurrences int — 同一标识符在多个来源里出现次数
confidence int — per-row 0-100
portal_actor_merge_candidates
(a, b) lex-normalised; status ∈ {pending, merged, rejected, dismissed}
score int 0-100; reasons jsonb
portal_actor_audit
action ∈ {merge, split, ingest, enrich}
payload jsonb — 完整 pre-state,可作回滚依据
3.2 Kind weight 表(用于评分 + 合并候选)¶
wallet_* 1.00 ← 加密钱包 = 近确定性
phone 0.95
email 0.85
wechat / qq 0.85
discord 0.85
domain_registrant_email 0.80
telegram 0.70
domain 0.40 ← 故意低:CloudFlare / NS 共享常见
username 0.30
3.3 自动合并候选检测¶
当 UpsertActorIdentifier(in) 接到一个 (kind, value) 已落在不同 actor 上时:
- 绝不静默重指 actor_id
- 写 / 更新
portal_actor_merge_candidates一行 - 重算 pair score = max(weight × confidence) across shared identifiers
- score ≥ 85 → 建议自动合并(UI 标红 + 强匹配 chip)
- 60 ≤ score < 85 → 候选队列
- < 60 → 不入候选(避免噪声)
3.4 合并语义¶
MergeActors(target, source, byUser, notes) 单事务做:
- snapshot source actor + 标识符 → audit payload
- 移动 identifiers(UNIQUE 冲突时 bump target 行的 occurrences + 删 source 行)
- 重指 metadata 指针:threats / private_servers / social_intel / publications
- 重指 FK:evidence_chains / legal_docs
- source.status = 'merged'(软删,保留 audit 完整性)
- 关闭涉及 pair 的 pending 候选
- 写 audit
SplitActor 是反向:peel 子集 identifiers 到新 actor,不移动 SI/PS 链接(人工再连)。
4. API endpoints(全列表)¶
4.1 列表 / 统计 / 关联¶
| Method | Path | 用途 |
|---|---|---|
| GET | /actors |
列表(search / page / page_size) |
| GET | /actors/stats |
5 KPI tile + top_risk_actors + by_platform |
| GET | /actors/:id |
单画像详情 |
| GET | /actors/:id/related |
5 collection bundle (threats / ps / si / legal / evidence) |
| GET | /actors/:id/threats |
该画像名下的威胁分页列表 |
4.2 Identity Resolution(Step 3)¶
| Method | Path | 用途 |
|---|---|---|
| GET | /actors/:id/identifiers |
列该 actor 的所有标识符(confidence DESC) |
| POST | /actors/:id/identifiers |
手动加一个标识符(命中已存在 → 合并候选) |
| POST | /actors/:id/ingest-identifiers |
一键从关联 SI/PS 抽出标识符聚合 |
| GET | /actors/merge-candidates |
待审合并候选(按 score DESC) |
| POST | /actors/merge |
执行合并 |
| POST | /actors/merge-candidates/:id/decision |
拒绝 / dismiss 候选 |
| POST | /actors/:id/split |
拆出新 actor |
4.3 多源融合 + 评分 + 网络(Step 4-6)¶
| Method | Path | 用途 |
|---|---|---|
| GET | /actors/:id/sources |
canonical 多源融合(contacts / pricing / urls / geo / platforms / activity) |
| GET | /actors/:id/risk-score |
六因素 0–100 加权 + 因素明细 |
| GET | /actors/:id/network |
depth-1 ego graph + 4 类边 + per-edge evidence |
4.4 富化 + 生命周期(Step 7)¶
| Method | Path | 用途 |
|---|---|---|
| GET | /actors/:id/enrichment |
读 metadata.enrichment 块(不重算) |
| POST | /actors/:id/enrich |
重算 + 写 metadata + 可能更新 actor.status + audit |
4.5 活动 + AI 简报(Step 8)¶
| Method | Path | 用途 |
|---|---|---|
| GET | /actors/:id/activity?limit=N |
5 路 union 时间线 |
| GET | /actors/:id/ai-summary |
确定性 templated 简报(actor-fusion/v1) |
4.6 观察名单 + 批量(Step 9)¶
| Method | Path | 用途 |
|---|---|---|
| GET | /actors/watchlist |
当前用户的观察名单 + score_delta / status_changed 计算字段 |
| POST | /actors/:id/watch |
加入观察 |
| DELETE | /actors/:id/watch |
取消观察 |
| POST | /actors/bulk-enrich |
批量富化 |
| POST | /actors/bulk-watch |
批量加观察 |
| POST | /actors/bulk-status |
批量改 status |
5. Risk score 因素权重表(Step 5)¶
| Factor | Weight | Scoring 规则 |
|---|---|---|
| 威胁强度 | 30% | weighted (critical×10 + high×5 + medium×2 + low×1),50 饱和到 100 |
| 身份强度 | 20% | sum(kind_weight × 10),1 个钱包 ≈ 10 分 |
| 活跃近度 | 18% | 阶梯:今天=100 / 周内=90 / 月内=70 / 季内=40 / 半年=20 / 年内=10 |
| 平台广度 | 12% | unique platforms × 20,5 个平台饱和 |
| 报价频次 | 10% | 任何报价基线 20 + count×4 饱和 100 |
| 资产规模 | 10% | linked PS × 12 |
Band 阈值:≥80 critical / ≥60 high / ≥35 medium / 其它 low
6. Network graph 四桥(Step 6)¶
| Kind | Weight 上限 | 信号强度 |
|---|---|---|
identifier |
kind_weight × confidence | 强 — 共享强标识符(钱包 / 微信) |
private_server |
35 | 中 — 两位都连同一 PS |
social_channel |
25 | 中 — 同 (platform, group_id) 内交叉发帖 |
threat_target |
10 | 弱 — 共同目标游戏(convergent interest,非合谋) |
绝不做 depth ≥ 2 — well-connected hub 在 2-跳就爆图。点击邻居跳进去再展。
7. Lifecycle 阈值(Step 7)¶
硬约束:
- merged 永不被自动回滚
- 分析师手动 closed / archived 不被自动覆盖
每次富化写 portal_actor_audit 一行(action=enrich, payload 含 inferred_status + reason)—— "系统在 5/17 把这位推到 dormant"完全可追溯。
8. Frontend routes / components 索引¶
/actors — Hero + KPI + Top-N + Platform dist + 卡片列表
/actors/[id] — 全身画像页(10 panels)
/actors/merge-review — 合并审核工作台(Step 3)
/actors/watchlist — 观察名单 + bulk toolbar(Step 9)
components/actors/
IdentifiersPanel — 身份指纹(Step 3)
SourceFusionPanel — 多源融合(Step 4)
RiskScorePanel — 风险评分 + 雷达图(Step 5)
NetworkGraphPanel — 关系网络图(Step 6)
LifecyclePanel — 生命周期 + 主属性(Step 7)
WatchToggle — 观察按钮(Step 9)
components/viz/
ActorActivityFeed — 活动流(Step 8)
ActorAISummary — AI 简报(Step 8)
9. 已知不做 / Phase 7.5 备忘¶
- WHOIS / IP geo 实时拉取:当前 geo 推断只用 PS.geo_country(已在 sync 上游写入)。实时 WHOIS 查询是 Phase 7.5
- 真 langdetect:当前 primary_language 是 CJK vs Latin 比例的启发式。fastText / cld3 接入是 Phase 7.5
- 实际 Telegram / 邮件预警:当前 alert_on CSV 字段已落库,但 watcher 进程没跑(站内 score_delta + activity feed 是当前唯一 UI 反馈)
- LLM-backed AI summary:当前
actor-fusion/v1是确定性 templated(DGX vLLM 接入待 Phase 8) - 关系图 depth ≥ 2:故意不做(爆图)
- 跨 tenant 合并:super_admin 才能做;当前需要直连 DB;专门的"全局合并管理"页面是 Phase 7.5
10. Migrations¶
000009_actor_identity.up.sql — 标识符 / 合并候选 / 审计 三表(Step 3)
000010_actor_watchlist.up.sql — 观察名单(Step 9)
两个迁移都有对应 .down.sql,AutoMigrate 也已开启(dev 模式覆盖)。