mirror of
https://github.com/yaklang/yaklang-chrome-extension.git
synced 2026-09-22 03:10:43 +08:00
590 lines
26 KiB
Markdown
590 lines
26 KiB
Markdown
# Browser Profile 自动推断与 AI 协作架构
|
||
|
||
## 1. 产品决定
|
||
|
||
自动推断 Profile 不是明文网关的辅助功能,而是浏览器现场的默认完成路径。
|
||
|
||
用户不应先理解混淆变量、复制密钥、编写包装函数,再手工配置参数路径和输出映射。正常流程必须从一次真实业务操作开始:
|
||
|
||
```text
|
||
用户执行登录 / 查询 / 提交
|
||
-> Recorder 生成有界业务 Trace
|
||
-> 确定性推断器关联明文点、页面调用和请求字段
|
||
-> 已知模式直接生成候选
|
||
-> 未知模式请求 AI 解释业务帧和参数语义
|
||
-> 必要时引导用户再执行一次操作以捕获业务闭包
|
||
-> 编译为文档绑定的 Profile
|
||
-> 使用录制样本做页面内回放校验
|
||
```
|
||
|
||
手写 JavaScript 保留为高级模式,不再作为主流程或文档中的首选方案。
|
||
|
||
本设计不包含“发送真实 HTTP 请求验证”。真实请求仍由 Yak / Web Fuzzer 的既有数据面负责。本阶段只负责发现、推断、捕获、编译和页面内样本校验。
|
||
|
||
## 2. 用户结果
|
||
|
||
以一次 CryptoJS 调用为例,默认界面应展示:
|
||
|
||
```text
|
||
已识别请求转换
|
||
|
||
POST /api/login
|
||
JSON 明文 -> CryptoJS.AES.encrypt -> body.encryptedData
|
||
|
||
输入 argument 0 <- 请求明文 JSON
|
||
Key argument 1 <- 页面内 WordArray · 16 B
|
||
IV options.iv <- 页面内 WordArray · 16 B
|
||
模式 CBC / Pkcs7
|
||
输出 toString -> URL encode -> encryptedData
|
||
|
||
证据 4 项 · 高置信度
|
||
[生成 Profile]
|
||
```
|
||
|
||
`_0x67b862` 一类混淆名称只能出现在折叠的原始证据中。主界面使用 `Key`、`IV`、`明文输入`、`请求字段` 等语义角色。
|
||
|
||
用户应能回答三个问题:
|
||
|
||
1. 插件为什么认为这是加密链路;
|
||
2. 哪些结论是确定事实,哪些是推测;
|
||
3. 还需要用户执行什么操作才能完成 Profile。
|
||
|
||
## 3. 设计原则
|
||
|
||
### 3.1 证据先于 AI
|
||
|
||
指纹相等、请求字段解析、调用顺序、运行时对象类型和调用栈属于确定性证据。AI 不重复判断这些事实,只消费其结构化结果。
|
||
|
||
### 3.2 AI 不能成为执行边界
|
||
|
||
AI 可以:
|
||
|
||
- 给业务 frame 排序;
|
||
- 将参数标注为 payload、key、iv、nonce、timestamp 或 signature;
|
||
- 从有限源码片段中解释序列化和包装步骤;
|
||
- 在多个候选之间给出理由;
|
||
- 建议下一次捕获点。
|
||
|
||
AI 不可以:
|
||
|
||
- 直接提交任意 JavaScript 作为生产 Profile;
|
||
- 引用不存在的事件、frame、参数或页面函数;
|
||
- 读取或输出 key、Cookie、token、密码等原始值;
|
||
- 绕过 grant、document、origin 或人工接管状态;
|
||
- 将猜测标记为已经验证的事实。
|
||
|
||
### 3.3 页面是执行环境,不是密钥导出器
|
||
|
||
Key、IV、CryptoKey、key promise、WASM 实例和闭包变量继续保留在原页面。Profile 只保存页面内 opaque callable 引用和经过校验的参数映射。
|
||
|
||
### 3.4 已知模式不依赖 AI,未知模式不依赖库清单
|
||
|
||
WebCrypto、CryptoJS、JSEncrypt 以及后续 sm-crypto、node-forge 等已知模式,连同 URLSearchParams、JSON、FormData 和常见编码链,应优先由确定性规则推断。AI 只处理业务语义和未知代码,避免增加延迟、成本和不确定性。
|
||
|
||
录制协议只暴露统一的 `crypto` 事件,库差异进入结构化 `adapterId / providerKind / family / operation / algorithm / mode / padding / encoding / state / key metadata`。推断器、时间线、Deep Capture 和 Agent 不再分别判断 `webcrypto`、`cryptojs` 等事件类型。新增密码库时只扩展 MAIN-world adapter、扩展自带的 manifest 和受限元数据归一化器,不扩展整条产品协议。
|
||
|
||
已知 adapter 只负责提供更准确的参数角色、算法和状态语义,不是通用性的唯一来源。对于 ESM/Webpack 闭包、Worker、WASM 或完全未知的业务封装,系统必须从请求/消息边界和调用栈恢复上层业务 callable;算法尚未命名不能单独成为 `insufficient-evidence`。adapter 协议的开放化、Worker/MessagePort 边界、高价值库优先级与反靶场特化验收见 [`FRONTEND_CRYPTO_GENERALIZATION_ROADMAP.md`](FRONTEND_CRYPTO_GENERALIZATION_ROADMAP.md)。
|
||
|
||
### 3.5 无兼容负担
|
||
|
||
插件尚未正式投入使用。页面配方、运行时适配器和 Transform Profile 可以直接收敛到新模型,不保留旧数据迁移或双写逻辑。
|
||
|
||
## 4. 总体架构
|
||
|
||
```text
|
||
MAIN-world Recorder
|
||
| bounded events + opaque handles + semantic argument metadata
|
||
v
|
||
Evidence Normalizer
|
||
| request fields / call slots / encodings / exact & normalized links
|
||
v
|
||
Evidence Graph
|
||
| proven edges + supported edges + hypotheses
|
||
+-----------------------+
|
||
| |
|
||
v v
|
||
Deterministic Inference AI Analysis
|
||
| known patterns | frame ranking / semantic labels / unknown code
|
||
+-----------+-------------+
|
||
v
|
||
Candidate Merger
|
||
| schema validation + evidence reference validation
|
||
v
|
||
Pipeline Compiler v2
|
||
| page callable graph, no arbitrary generated code
|
||
v
|
||
Local Sample Replay
|
||
| deterministic compare or structural assertions
|
||
v
|
||
Document-bound Profile
|
||
```
|
||
|
||
推断计算在扩展后台完成。Yakit、Options 和 AI Agent 读取同一候选结构,不各自实现一套启发式规则。
|
||
|
||
## 5. Evidence Graph
|
||
|
||
### 5.1 节点
|
||
|
||
```ts
|
||
type EvidenceNode =
|
||
| RecordingEventNode
|
||
| RecordedValueNode
|
||
| RequestFieldNode
|
||
| CallableNode
|
||
| CallArgumentNode
|
||
| StackFrameNode
|
||
| SourceExcerptNode
|
||
```
|
||
|
||
节点只使用录制会话内稳定 ID。原始敏感值不是图节点属性。
|
||
|
||
### 5.2 边
|
||
|
||
```ts
|
||
type EvidenceStrength = "proven" | "supported" | "hypothesis"
|
||
|
||
type EvidenceEdgeKind =
|
||
| "exact-value"
|
||
| "normalized-value"
|
||
| "parent-call"
|
||
| "same-trace"
|
||
| "stack-frame"
|
||
| "argument-role"
|
||
| "request-destination"
|
||
```
|
||
|
||
- `exact-value`:同一录制盐下的指纹完全相同;
|
||
- `normalized-value`:经过有界白名单转换后相同,例如 URL decode、JSON field extraction 或 Base64 表示;
|
||
- `parent-call`:Recorder 的同步父调用关系;
|
||
- `same-trace`:弱证据,只证明时间和用户操作相关;
|
||
- `hypothesis`:只能由 AI 或启发式产生,必须列出依据。
|
||
|
||
### 5.3 请求边界归一化
|
||
|
||
网络事件在边界处解析,不全局 Hook `JSON.stringify` 或 `encodeURIComponent`:
|
||
|
||
- JSON:递归提取最多 64 层、100,000 节点;
|
||
- `application/x-www-form-urlencoded`:字段级 URL decode;
|
||
- `FormData`:字段名、字符串值和文件元数据;
|
||
- Headers:规范化名称但保留原始大小写用于展示;
|
||
- Query:字段级解析;
|
||
- 原始 body:保留整体指纹和类型。
|
||
|
||
归一化候选只允许白名单操作并设置总预算。不得对每个值进行无界编码组合爆炸。
|
||
|
||
### 5.4 参数语义
|
||
|
||
Recorder 对已知库记录参数角色而不是变量名:
|
||
|
||
```ts
|
||
interface CallArgumentEvidence {
|
||
index: number
|
||
role: "data" | "key" | "iv" | "algorithm" | "options" | "signature" |
|
||
"salt" | "nonce" | "aad" | "unknown"
|
||
dataType: string
|
||
byteLength?: number
|
||
replaceable: boolean
|
||
retained: boolean
|
||
summary?: string
|
||
}
|
||
```
|
||
|
||
例如 CryptoJS AES:
|
||
|
||
- `argument 0`:data,可替换;
|
||
- `argument 1`:key,不导出,页面内保留;
|
||
- `argument 2`:options,提取 mode、padding 和 IV 长度,不提取 IV 值。
|
||
|
||
例如 JSEncrypt RSA:
|
||
|
||
- `argument 0`:UTF-8 data,可替换;对象输入按稳定 JSON 序列化后再交给原函数;
|
||
- receiver:保留实际 JSEncrypt 实例,不重建、不导出;
|
||
- key:只记录 public/private、模数位数和本次录制随机加盐的指纹;
|
||
- padding:记录 `PKCS1-v1_5` 等可解释元数据;
|
||
- output:记录 Base64 形态并与 JSON/Form/Header/Query 请求字段做 exact link;
|
||
- 公私钥 PEM、模数、指数和页面实例永不进入候选或 AI 上下文。
|
||
|
||
如果一次 RSA 输出精确进入一个请求字段,且原函数、receiver 和参数模板仍在当前 document 中,候选可以直接进入 `ready`,不要求用户填写函数表达式或先进入 Deep Capture。
|
||
|
||
## 6. 统一 Page Callable
|
||
|
||
当前页面配方和深度捕获适配器表达的是同一概念:在当前文档中可重复调用的页面函数。两套注册表应合并为 `BrowserPageCallable`。
|
||
|
||
```ts
|
||
interface BrowserPageCallable {
|
||
id: string
|
||
kind: "recorded-call" | "business-closure" | "global-function"
|
||
name: string
|
||
target: BrowserTarget
|
||
lifecycle: "document"
|
||
inputSlots: CallableInputSlot[]
|
||
output: CallableOutputShape
|
||
provenance: {
|
||
recordingId?: string
|
||
traceId?: string
|
||
eventId?: string
|
||
frameId?: string
|
||
sourceUrl?: string
|
||
lineNumber?: number
|
||
}
|
||
}
|
||
```
|
||
|
||
`recorded-call` 保存原函数、receiver、固定参数模板和可替换槽位;`business-closure` 保存 CDP 暂停时捕获的业务函数与闭包;两者使用同一执行、授权、生命周期和审计接口。
|
||
|
||
Profile 不再引用 `recipeId` 或 `adapterId`,只引用 `callableId`。
|
||
|
||
## 7. Pipeline v2
|
||
|
||
手工 JavaScript 中常见的 JSON 序列化、编码、调用和封装应变成可审计的类型化节点:
|
||
|
||
```ts
|
||
type PipelineNode =
|
||
| { kind: "context.read"; path: string }
|
||
| { kind: "builtin"; operation: BuiltinOperation; inputs: NodeRef[]; options?: object }
|
||
| { kind: "page.call"; callableId: string; arguments: NodeRef[] }
|
||
| { kind: "output.write"; destination: string; source: NodeRef; encoding: ValueEncoding }
|
||
```
|
||
|
||
首批 `BuiltinOperation`:
|
||
|
||
```text
|
||
value.literal
|
||
json.stringify
|
||
json.parse
|
||
text.toString
|
||
url.encode
|
||
url.decode
|
||
base64.encode
|
||
base64.decode
|
||
hex.encode
|
||
hex.decode
|
||
object.pick
|
||
object.compose
|
||
form.compose
|
||
```
|
||
|
||
`value.literal` 只允许字符串、数字、布尔值或 `null`,用于编译器生成固定的协议元数据,例如表单
|
||
`Content-Type`。它不接受输入,也不能持有函数、对象或页面秘密。
|
||
|
||
每个节点有明确输入输出类型和大小预算。未知操作不能通过 AI 临时创造;用户确实需要自定义代码时,进入独立的高级节点,并沿用程序 Eval 的高风险授权。
|
||
|
||
## 8. 推断候选
|
||
|
||
候选不是立即生效的 Profile:
|
||
|
||
```ts
|
||
interface BrowserProfileInferenceCandidate {
|
||
id: string
|
||
recordingId: string
|
||
traceId: string
|
||
target: BrowserTarget
|
||
request: { eventId: string; method: string; url: string }
|
||
direction: "request" | "response"
|
||
status: "ready" | "capture-required" | "mapping-required" | "insufficient-evidence"
|
||
confidence: { score: number; level: "high" | "medium" | "low" }
|
||
summary: string
|
||
pipeline: PipelineNodeDraft[]
|
||
evidence: InferenceEvidenceRef[]
|
||
missing: InferenceMissingStep[]
|
||
aiContext: BrowserInferenceAIContext
|
||
}
|
||
```
|
||
|
||
置信度不是 AI 的主观百分比。分数由固定规则产生,并在 UI 中解释:
|
||
|
||
- 请求字段与加密输出 exact link:强加分;
|
||
- 可重复 callable 已保留:强加分;
|
||
- 同一用户 Trace 且顺序正确:中等加分;
|
||
- 仅时间接近:弱加分;
|
||
- 多个同分候选:降分;
|
||
- 缺少输入映射或输出封装:状态不能为 ready。
|
||
|
||
## 9. 自动业务函数捕获
|
||
|
||
低层 `CryptoJS.AES.encrypt` 或 `crypto.subtle.encrypt` 往往不足以构造完整线上报文。推断器应把它作为断点入口,然后寻找上层业务函数。
|
||
|
||
```text
|
||
候选指出需要业务 callable
|
||
-> 用户点击“自动捕获完整加密流程”
|
||
-> 插件在已知低层调用处 arm 一次性断点
|
||
-> 用户重复相同操作
|
||
-> 页面暂停并立即显示控制面
|
||
-> 后台排除 Hook/依赖帧,并使用多来源共同祖先提示排序页面帧
|
||
-> 纯函数用 selected-frame;负责 DOM 取值/组包/发送的函数用 request-transaction
|
||
-> 页面立即恢复
|
||
-> 新明文映射到参数或页面控件,仅返回被拦截的线上 envelope
|
||
```
|
||
|
||
录制器只从每个来源事件的有界同步栈提取页面帧提示,并对 `functionName + script URL` 求交集;支持来源更多、平均深度更浅的共同祖先优先。捕获入口选择最早已确认的密码来源,而不是已经离开上层异步函数后的 Fetch 边界。后台再结合真实 CDP `scriptId`、函数位置、来源分类和副作用检查做最终选择,因此前端不能通过提交 URL、行号或函数名把任意对象伪装成推荐帧。
|
||
|
||
当最高候选唯一、可解析且未发现副作用时,默认路径使用 `selected-frame`。如果多个密码来源的最近共同页面祖先本身包含网络、DOM 或条件导航,系统不会跳过它去选更外层的事件 handler,而是建立 `request-transaction`:保留真实函数、receiver 和固定参数,在页面内替换明文控件,拦截唯一的目标 Fetch/XHR/Beacon/Form,校验所有预期输出字段后回滚 DOM。
|
||
|
||
存储副作用、多个或未授权请求、无法唯一绑定函数、或共同祖先证据并列时,系统保持页面暂停并解释原因。函数引用表达式只存在于高级模式。页面暂停不等待远程 AI;AI 只能在页面恢复后基于同一份有界证据做解释和候选补丁。
|
||
|
||
函数捕获后,后台从 `Function.prototype.toString` 恢复包括默认参数在内的有序参数名。单参数业务函数默认读取整个逻辑 Body;多参数且名称可靠时,引导配置生成 `body.<parameter>` 读取节点;`arg0` 这类占位名不会被冒充为已确认字段。Options 同时从已授权暂停帧的 local/block/closure scope 取同名原始值,构造一次性的本地回放 Body。完整暂停作用域始终只存在于当前会话;只有用户明确生成并保存明文网关后,选中的短时样本才会复制到独立的本机回放草稿。该草稿按 `profileId + request/response` 隔离,不写入 Profile、Bridge、审计、Yak/AI、诊断或导出,并可由用户单独清空。
|
||
|
||
### 9.1 多密码调用按请求建图
|
||
|
||
一个请求可能同时包含 AES ciphertext、RSA-encrypted session key、HMAC signature、nonce 和 timestamp。即使每个低层输出都与请求字段精确匹配,也不能把这些调用分别保存后独立回放:它们可能共享同一随机 key、IV、nonce 或闭包状态。
|
||
|
||
推断器因此按请求边界合并多个来源,生成一个 request-level candidate:
|
||
|
||
```text
|
||
plaintext -----------------> AES.encrypt ----------> body.data
|
||
dynamic AES key -----------> JSEncrypt.encrypt ----> body.encryptedKey
|
||
canonical request fields --> HMAC.sign ------------> header.X-Sign
|
||
|
|
||
+-- 同一上层业务 callable 保证动态值一致
|
||
```
|
||
|
||
界面展示每个密码调用及其线上目标,但状态固定为 `capture-required`。用户点击“自动捕获完整加密流程”时,Deep Capture 优先在仍保留上层业务调用栈的密码来源处武装断点,并捕获一次上层业务封装;系统不会把多个看似 ready 的低层调用拆成多个可执行 Profile,也不会误导用户反复缩短已经足够短的录制操作。
|
||
|
||
### 9.2 请求事务的输入与输出契约
|
||
|
||
`request-transaction` 对明文只暴露一个 `body` 输入槽,对 Pipeline 返回被页面业务代码生成的整个请求 Body。因此 AES + RSA 之类多输出流程会直接编译为:
|
||
|
||
```text
|
||
context.read(body)
|
||
-> page.call(sendDataAesRsa 请求事务)
|
||
-> output.write(body)
|
||
```
|
||
|
||
事务保留暂停现场的 URL/event/receiver 等固定参数。逻辑 Body 是对象时,先按 input `name/id` 向页面控件做同名映射;参数名明确是 `payload/data/body/request/params/input` 时才直接替换参数。已混淆的单参数如果其保留值解析后等于目标 URL,必须继续保留,不得被明文对象覆盖。
|
||
|
||
## 10. AI Agent 集成
|
||
|
||
### 10.1 绑定资源
|
||
|
||
Yakit 从浏览器集成页启动 AI 分析时,附加一个类型化资源:
|
||
|
||
```text
|
||
AttachedResourceInfo.type = browser_session
|
||
AttachedResourceInfo.key = context
|
||
```
|
||
|
||
Value 只在 Yak 进程内解析,包含 device、grant、document、selected trace 和 candidate ID。渲染给模型的内容只包含安全摘要,不暴露 device token、grant secret 或录制值。
|
||
|
||
资源必须绑定:
|
||
|
||
```text
|
||
timeline session
|
||
AI task
|
||
deviceId
|
||
grantId
|
||
tabId + frameId + documentId + origin
|
||
expiresAt
|
||
```
|
||
|
||
### 10.2 Agent 工具
|
||
|
||
不要把几十个 Bridge RPC 原样暴露给模型,也不要提供通用 `method + params` 工具。首批提供三个领域工具:
|
||
|
||
```text
|
||
browser_observe
|
||
page summary / actionable nodes / trace / inference / status / diff
|
||
|
||
browser_inference
|
||
list candidates / inspect evidence / arm capture / choose callable /
|
||
propose mapping / compile candidate / local replay
|
||
|
||
browser_act
|
||
stable node action / tab activation / human handoff
|
||
```
|
||
|
||
工具回调从当前 AI task 的 `browser_session` 资源解析绑定,AI 参数中不存在 `deviceId`、`grantId` 或任意 Bridge method。
|
||
|
||
`browser_observe` 默认只读;`browser_inference` 的读取和推断无需额外确认,arm debugger、创建 callable 和发布 Profile 使用现有细分 scope;`browser_act` 遵循 Agent review policy 和人机接管状态。
|
||
|
||
### 10.3 AI 输出 Schema
|
||
|
||
AI 只能返回候选补丁:
|
||
|
||
```ts
|
||
interface AIInferencePatch {
|
||
candidateId: string
|
||
labels: Array<{ evidenceId: string; role: SemanticRole; reason: string }>
|
||
preferredFrameId?: string
|
||
argumentBindings?: Array<{ slotId: string; contextPath: string; reason: string }>
|
||
suggestedBuiltins?: Array<{ operation: BuiltinOperation; evidenceIds: string[] }>
|
||
unresolved: string[]
|
||
}
|
||
```
|
||
|
||
Candidate Merger 必须验证所有 ID 存在、document 未变化、操作在白名单内、映射路径合法。验证失败只产生新的待处理项,不能退化为执行 AI 代码。
|
||
|
||
## 11. UI / UX
|
||
|
||
录制是入口,自动推断是录制完成后的主结果。三列工作台保持不变:
|
||
|
||
```text
|
||
Trace 列 | 数据流与候选 | 推断证据 / 下一步
|
||
```
|
||
|
||
右侧主区域按状态显示:
|
||
|
||
- `ready`:一键生成 Profile;
|
||
- `capture-required`:解释原因并提供“自动捕获完整加密流程”;
|
||
- `mapping-required`:只让用户选择少量无法确定的明文字段;
|
||
- `insufficient-evidence`:建议重新录制,并明确缺少哪类证据。
|
||
|
||
证据采用三种强度:
|
||
|
||
- 已证实:实线和明确措辞;
|
||
- 有支持:普通文本并展示依据;
|
||
- 待确认:虚线或次级文本,不使用成功色。
|
||
|
||
AI 是候选的解释者,不单独占据一个聊天面板。主要入口是“让 AI 深入分析”,结果回填到同一证据区域。需要继续对话时再打开 Yakit AI 会话,并携带相同 `browser_session` 资源。
|
||
|
||
手工 Pipeline 编辑器移入“高级编辑”,默认只展示推断出的可读流程和少量可修改字段。
|
||
|
||
默认 Profile 编辑器不是节点画布,而是三个业务决定:
|
||
|
||
```text
|
||
1. 明文从哪里来
|
||
2. 交给哪个页面函数
|
||
3. 线上结果写到哪里
|
||
```
|
||
|
||
当第三步选择“写入表单字段”并填写 `encryptedData` 时,编译器自动生成
|
||
`form.compose(keys=["encryptedData"])`、固定 Content-Type、Header 输出和 Body 输出。用户不需要看到或填写
|
||
`keys`、节点 ID、输入引用和输出引用。已有非规范 DAG 不会被静默改写,只能继续在高级模式中编辑,或由用户明确替换为引导流程。
|
||
|
||
## 12. 性能预算
|
||
|
||
- 单次快照最多 500 事件、每事件 48 个 evidence;
|
||
- 图构建使用 fingerprint/path 索引,目标复杂度 `O(E + V)`;
|
||
- normalized link 每值最多生成 8 个白名单变体;
|
||
- 候选最多 16 个,发送给 AI 的候选最多 3 个;
|
||
- scope 每次最多 8 个 frame,源码片段按需读取并限制总字节;
|
||
- 推断结果按 `recordingId + event revision` 缓存,增量追加事件时只处理新增部分;
|
||
- 不在页面主线程执行全量源码搜索、AST 构建或全局 JSON/URL 编码 Hook;
|
||
- Pipeline 在目标 document 内一次执行完成,每次请求/响应只跨扩展到页面边界一次,不按节点往返;
|
||
- 页面暂停路径绝不等待网络或 AI。
|
||
|
||
## 13. 隐私与授权
|
||
|
||
- 默认推断只使用指纹、类型、长度、路径、算法摘要和源码位置;
|
||
- 敏感录制预览即使被用户开启,也不自动进入 AI context;
|
||
- Key、IV、CryptoKey 和闭包值只显示语义、类型与长度;
|
||
- 源码片段可能包含硬编码 secret,发送 AI 前先进行字面量脱敏并由用户授权;
|
||
- 推断读取使用 `browser.recording.read`;
|
||
- scope/source 深入读取使用 `browser.debugger.read`;
|
||
- arm/resume 与 callable 创建使用 `browser.debugger.control`;
|
||
- callable 创建、执行与本地回放使用 `browser.callable.execute`;从暂停 frame 捕获 callable 还需要 `browser.debugger.control`;
|
||
- Profile 发布使用 `browser.transform.manage`;
|
||
- document、origin 或 grant 变化后候选立即标记 stale,不静默重绑。
|
||
|
||
## 14. 生命周期与恢复
|
||
|
||
Profile 是 document-bound。刷新后不能继续调用旧闭包,但推断定义可以保留为恢复计划:
|
||
|
||
```text
|
||
页面刷新
|
||
-> callable stale
|
||
-> Profile disabled
|
||
-> 插件按原 operation / script / route 重新 arm
|
||
-> 用户正常执行一次业务操作
|
||
-> 重新捕获 callable
|
||
-> 本地样本校验
|
||
-> 用户确认后重新启用
|
||
```
|
||
|
||
恢复计划不保存 key 或源码计算结果,只保存捕获入口、业务 frame 特征、参数语义和映射结构。
|
||
|
||
## 15. 分阶段实现
|
||
|
||
### P0:证据与候选基线
|
||
|
||
- [已完成] 使用统一 `crypto` 事件记录 WebCrypto / CryptoJS / JSEncrypt / sm-crypto / node-forge 的 adapter、provider kind、family、调用、参数角色、类型、长度和 state/retained 状态;
|
||
- [已完成] MAIN-world 密码适配器注册表支持稳定 adapter 与运行时晚加载 adapter;
|
||
- [已完成] JSEncrypt RSA encrypt/decrypt/sign/verify 保留真实 receiver,并仅输出公私钥类型、位数和加盐指纹;
|
||
- [已完成] 为 CryptoJS 结果补充安全的字符串表示 evidence;
|
||
- [已完成] 从 exact link、请求字段和调用顺序生成只读候选;
|
||
- [已完成] Options / Yakit 展示置信度、证据和缺失步骤;
|
||
- [已完成] 候选结构可通过 `browser.recording.get` 提供给 Agent。
|
||
|
||
### P1:统一 Callable 与 Pipeline v2
|
||
|
||
- [已完成] 删除 recipe / adapter 双模型,不保留旧方法别名或迁移分支;
|
||
- [已完成] 页面 callable 使用统一注册表、来源信息、生命周期和命名 input slot schema;
|
||
- [已完成] Pipeline v2 使用有序 DAG,并加入类型化 context.read / builtin / page.call / output.write 节点;
|
||
- [已完成] builtin 限定为 JSON、文本、URL、Base64、Hex、对象和表单组合白名单;
|
||
- [已完成] 输出支持 body、字段级 body、header 和 query,并由 Yak 二次限制 URL 只能改变 query;
|
||
- [已完成] 单条 exact value link 且保留可执行调用句柄的 stateless/receiver 模式可直接编译候选;stateful/stream 模式必须捕获上层 callable;
|
||
- [已完成] 同一请求的多个密码来源合并为 request-level candidate,并强制捕获上层业务 callable 以保持动态值关系;
|
||
- [已完成] JSON 字段、表单字段、Header、Query 和完整 Body 会编译为对应的引导式输出,不要求用户理解 DAG;
|
||
- [已完成] 录制短时样本自动填入 Options/Yakit 明文网关本地回放,并允许编辑后恢复原样本;
|
||
- 为页面内回放生成确定性/结构性断言。
|
||
|
||
### P2:自动业务函数捕获
|
||
|
||
- [已完成] 候选一键 arm,并在已有捕获等待或页面暂停时拒绝覆盖;
|
||
- [已完成] 业务 frame 使用来源、边界距离、函数可解析性、副作用、命名和作用域信息做确定性排序;
|
||
- 参数槽位与 request context 自动映射;
|
||
- 文档刷新后的引导式重新捕获。
|
||
|
||
### P3:Yak AI Agent
|
||
|
||
- `browser_session` attached resource;
|
||
- task-bound 三个 Agent 工具;
|
||
- AIInferencePatch schema 与 Candidate Merger;
|
||
- Yakit 从候选直接启动带上下文的 AI 会话;
|
||
- Agent 操作写入现有 session timeline。
|
||
|
||
### P4:复杂应用
|
||
|
||
- Axios/interceptor、GraphQL、WebSocket frame、protobuf 与自定义 serializer;
|
||
- [已完成] 按通用化路线迁移 adapter host,加入 sm-crypto、node-forge 与 Beacon/Worker/MessagePort 边界,并通过随机 ESM + WASM holdout;
|
||
- jsrsasign、jose 与后续现代密码生态按真实样本继续推进;
|
||
- sourcemap 存在时的业务 frame 增强;
|
||
- 多候选对比和跨操作共用 callable 识别。
|
||
|
||
P4 的实现顺序、协议草案、性能门禁和随机化测试矩阵以 [`FRONTEND_CRYPTO_GENERALIZATION_ROADMAP.md`](FRONTEND_CRYPTO_GENERALIZATION_ROADMAP.md) 为准。
|
||
|
||
## 16. 验收夹具
|
||
|
||
至少覆盖:
|
||
|
||
1. 固定 CryptoJS AES,混淆变量名,JSON 字段输出;
|
||
2. 真实 JSEncrypt RSA + form-urlencoded `data` 字段,独立服务端用私钥解密验收;保留实例 receiver,停止录制后对象明文仍可回放;
|
||
3. RSA 候选和 AI 上下文只包含 key 类型、位数与加盐指纹,不包含 PEM 或模数;
|
||
4. WebCrypto AES-GCM + HMAC,闭包内不可导出 key 和动态 nonce/IV;
|
||
5. AES + RSA + HMAC 同请求多来源图,不允许拆分低层调用回放;
|
||
6. 动态 key promise,页面刷新后重新捕获;
|
||
7. Axios interceptor 中的请求签名;
|
||
8. Form URL encode 和 Header signature;
|
||
9. 自定义业务 wrapper,低层库调用不足以构造完整报文;
|
||
10. 未知函数与多个同分业务 frame,AI 只能补全候选,不能直接执行代码;
|
||
11. WASM 导出函数,只能观察输入输出和业务 wrapper;
|
||
12. 敏感预览开启时,AI payload、审计和诊断仍不含原始值;
|
||
13. 500 事件 / 24,000 evidence 的性能与内存预算。
|
||
|
||
## 17. 目标目录
|
||
|
||
```text
|
||
src/features/browser-recording/
|
||
evidence.ts
|
||
recorder.ts
|
||
|
||
src/features/browser-inference/
|
||
graph.ts
|
||
normalize.ts
|
||
rules/
|
||
candidates.ts
|
||
compiler.ts
|
||
ai-context.ts
|
||
|
||
src/features/browser-callable/
|
||
registry.ts
|
||
execute.ts
|
||
lifecycle.ts
|
||
|
||
src/features/browser-transform/
|
||
pipeline-v2.ts
|
||
profile.ts
|
||
replay.ts
|
||
```
|
||
|
||
Yak 侧将 `browser_session` 资源解析和 Agent 工具放在独立包中,依赖一个最小的 Bridge caller interface,避免 `common/ai` 直接依赖 gRPC Server。
|