Files
mnote/design/12-vault/process/12-2-vaultd-local-token-agent-read-path-v1.md
T
Agent Board 262e66b02e feat: purge legacy agent hosts and land vault Chrome extension path
Retire ACP/Hermes/OpenCode surfaces and rename hermes_tools to
mnote_agent_tools so Page AI stays on Pi Lab only. Add Chrome vault
extension + extension token route, pre-release purge design, and soft-retire
legacy smokes for the small-group production cut.
2026-07-25 14:25:37 +08:00

504 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 12-2 [process] 本地 vaultd + Agent Token 读密路径(不依赖 mnote-webv1
> 创建时间:2026-07-23
> 状态:`PROCESS`**P0 L-Access 已落地****P1aP1d 已落地**web AI list/get/resolve/login/session → core`mnote-vault serve` UDS + CLI sock→内嵌 fallback**login/session 不依赖 mnote-web**
> Owner`12-vault`
> 建议 repo 落点:`design/12-vault/process/12-2-vaultd-local-token-agent-read-path-v1.md`
>
> 上位依据:
> - `design/12-vault/process/12-1-password-vault-dedicated-crud-workbench-v1.md`vault 系统空间、AI 密码本策略、文件真源)
> - `/home/lix/.agent-infra/vault-policy.md`(多 agent 唯一策略 SSOT
> - `skills/mnote-vault` / `$mnote-vault`
> - `design/07-ai/process/7-18-local-first-agent-file-editing-control-plane-v1.md`(禁裸读敏感路径)
> - `ARCHITECTURE.md` local-first 原则
>
> 触发证据:
> - Paseo session `21242fc0-db03-454c-a1e5-723688351ee7`:取密依赖 mnote-web 存活 + `auth-e2e` cookie,步骤膨胀、失败面大。
> - 用户目标:**读库本质是本地文件**;解密/受控读取只需轻量常驻服务,**不**应绑庞大 mnote-webagent 内部保存 **token** 做授权取密。
---
## 1. Overview
### 1.1 一句话
> **文件是库;`mnote-vaultd` 是受控读密网关(及未来 master key 匣);agent 只持 capability token,不持 master key,也不依赖 mnote-web 进程。**
### 1.2 与 12-1 的关系
| 维度 | 12-1(已落地主线) | 12-2(本文) |
|------|-------------------|--------------|
| 真源 | `{workspaceRoot}/.mnote/vault/**` 结构化文件 | **不变** |
| 人用 UI | `/vault` + mnote-web `/api/vault/*` | **保留**;不作为 agent 读密必经 |
| AI 策略 | 单 AI 本 + 单 resolve 通道 + 禁扫 vault 文件 | **策略不变****transport 换** |
| Agent 通道 | HTTP → mnote-web(需 cookie / auth-e2e | UDS/loopback → **vaultd**Bearer token |
| 常驻进程 | 整站 mnote-web | 可选 **极小 vaultd** |
12-1 P1「多 agent 唯一策略」中的语义(只读 AI 本、`resolve` 唯一取密、禁通用 file)**冻结保留**。
本文只改 **谁持进程、用什么凭证、是否依赖 3000**
### 1.3 现状诚实声明(实现前必读)
当前实现(2026-07):
- 条目为 workspace 下 **结构化 Markdown + frontmatter**`mnote.kind: credential`)。
- `cipher-book.json`**片段占位符展开**(如 `[A]` → 共享串),**不是** 磁盘 AES 整库加密。
- 尚无「用户 master password → 内存 master key → 密文 at rest」完整链路。
- 「解密」在产品语言上 = **load 文件 + cipher 展开 + nested secret 解析 + 策略门闩**
因此 12-2 分两层能力,**禁止混称**:
| 层 | 名称 | P0 是否必须 | 说明 |
|----|------|-------------|------|
| **L-Access** | 受控读密网关 | **是** | token 鉴权、只暴露 list/get/resolve、审计、不依赖 mnote-web |
| **L-Crypto** | 真·at-rest 加密 | **P2 可选** | master key 仅驻 vaultd 内存;token **永不**等于 master key |
P0 交付 **L-Access** 即可消除「3000 挂了就不能取密」。
L-Crypto 在文件格式与迁移就绪后再做,不阻塞 agent 读路径瘦身。
---
## 2. Goals / Non-Goals
### 2.1 Goals
1. Agent 读密(list / get / resolve / login 所需密钥字段)**不依赖 mnote-web 运行**。
2. 常驻面缩小为 **`mnote-vaultd`**(或等价 one-shot CLI 内嵌同一 core,见 §5.4),不跑 SSR/Sidebar/文档编辑。
3. Agent **内部保存 vault_token**;每次调用带 token**禁止**把 master password / master key 写入 agent 配置。
4. 保持 12-1 策略:仅 AI 密码本 actor;禁通用工具扫 `.mnote/vault/**`;resolve 审计不落明文到日志。
5. CLI / Pi 工具 / skill 语义对齐:稳态 **1~2 次调用**完成取密(已知 id 时仅 `resolve`)。
6. mnote-web UI 与 human CRUD **可继续用现网路径**;演进期可与 vaultd 并行,终态共享 `mnote-vault-core`
### 2.2 Non-Goals(本设计不承诺)
- 不重做 `/vault` 工作台 UI。
- 不把 vault 变成 graph / `tree.*` 节点。
- 不要求远程多机共享 vaultd(本机 local-first;跨机另案)。
- 不在 P0 强制引入 at-rest 加密迁移(L-Crypto = P2)。
- 不取消「禁扫 vault 文件」策略(即便未来密文 at rest,仍禁止 agent 把 vault 目录当通用笔记读)。
- 不把 Cloudflare 过人机验证自动化为无人值守(仍 human → `session` 回写)。
---
## 3. 问题根因(为何要拆)
```text
今天 Agent 取密关键路径:
skill/policy
→ mnote-vault-cli auth-e2e # 需要 mnote-web + 用户 auth API
→ list / resolve HTTP # 需要 3000 存活 + cookie
→ (可选)login / session
失败面:
- web 未启动 / 崩溃 / 端口占用
- cookie eval / FORCE_COLOR / 环境变量污染
- agent 探索路径、读 policy、猜 URL → 工具次数爆炸
```
根因归类:
| 误绑定 | 正确归属 |
|--------|----------|
| 读本地文件 → 需要 Web 服务器 | 读文件 → 本地 IO + 可选小网关 |
| Agent 身份 → mnote-web session cookie | Agent 身份 → vault capability token |
| 解密权 → 与 SSR 同进程 | 解密/受控 resolve → vaultd(或 CLI 内嵌 core |
---
## 4. 目标架构
### 4.1 分层图
```text
┌──────────────────────────────────────────────────────────────┐
│ Agent runtimeGrok / Codex / Hermes / Pi / Paseo
│ - 持有 vault_tokenenv / 0600 文件 / 可选 keyring
│ - 薄客户端:CLI 或 Pi tool → 只打 vaultd │
│ - 禁止:通用 file 扫 .mnote/vault/** │
└────────────────────────────┬─────────────────────────────────┘
│ Authorization: Bearer <token>
│ 优先 Unix Domain Socket
┌──────────────────────────────────────────────────────────────┐
│ mnote-vaultd(常驻 · 小 · 本机) │
│ - 校验 tokeniss/aud/exp/scope/actor
│ - 解析 vault rootworkspace / AI actor root
│ - load index / credential md + cipher expand + nested secret │
│ - L-Crypto 时:内存持 master keylock 清空 │
│ - 审计 jsonl(无 plaintext value
│ - 不托管:SSR、树、Page AI、control-plane 全站逻辑 │
└────────────────────────────┬─────────────────────────────────┘
│ 受控读写 FS
┌──────────────────────────────────────────────────────────────┐
│ 本地文件真源(SSOT,与 12-1 相同) │
│ {workspaceRoot}/.mnote/vault/ │
│ vault-index.json │
│ credentials|*.md(条目) │
│ cipher-book.json │
│ audit.jsonl │
│ AI 本:MNOTE_AI_VAULT_ACTOR 对应 root(实现沿用 12-1
└──────────────────────────────────────────────────────────────┘
旁路(可选,非读密阻塞路径):
mnote-web /vault UI、human CRUD、共享到 AI 本
Chrome 扩展保存到 vault(人用 human token,见 12-3**禁止**复用本设计 agent token
登录态落盘:sessions/{credId}/{accountId}.json12-3 §5.6);login/session CLI 读该路径,fallback frontmatter loginSession
vault-login-helper resolve 后外站登录 / session 回写
```
### 4.2 两类密钥(禁止混用)
| 名称 | 持有者 | 用途 | 落盘? |
|------|--------|------|--------|
| **Master key**L-Crypto | 仅 vaultd 内存 | 解密 at-rest 密文包 | 否(仅 unlock 后内存) |
| **Vault token**capability | Agent 配置 / runtime | 向 vaultd 证明「谁、何 scope、何 actor」 | 可:`~/.config/mnote/vault-tokens/*.token``0600` |
**硬规则:**
1. Token **不能**派生或编码 master key。
2. 泄露 token ⇒ 在 vaultd 存活且已 unlock 时可 resolve**不能**离线解密磁盘(L-Crypto 后更强)。
3. 泄露 master password ⇒ 可 unlock 整库;**不得**写入任何 agent skill / env 默认模板。
### 4.3 Token 声明(逻辑 schema
```json
{
"v": 1,
"iss": "mnote-vaultd",
"aud": "local-vaultd",
"sub": "agent:paseo",
"actor": "mnote-e2e",
"scope": ["list", "get", "resolve", "login", "session"],
"workspace": "optional-stable-id-or-path-hash",
"iat": 0,
"exp": 0,
"jti": "uuid"
}
```
- 序列化:紧凑 JSON + **HMAC-SHA256**(本机 secret)或 ed25519(若未来多签发方)。
- 传输:`Authorization: Bearer <base64url(payload).base64url(sig)>`(类 JWT 即可,不必上完整 OIDC)。
- P0 默认 scope`list` + `get` + `resolve``login`/`session` 可同 token 或分 token。
- `actor` **必须**等于 AI 密码本 actor(默认 `mnote-e2e`env `MNOTE_AI_VAULT_ACTOR` 可覆盖签发时固化进 token)。
### 4.4 Bootstraptoken 从哪来)
```text
一次(人或安装脚本):
1. 启动 vaultd(或 CLI doctor
2. L-Crypto)用户 unlock → master key 入内存
3. vaultd issue-token \
--agent paseo \
--actor mnote-e2e \
--scope list,get,resolve,login,session \
--ttl 90d
4. 写入 ~/.config/mnote/vault-tokens/default.token0600
5. 各 agent skill / envMNOTE_VAULT_TOKEN_FILE 或 MNOTE_VAULT_TOKEN
日常 agent
读 token → 调 resolve → 用完 value(不写聊天、不写无关日志)
```
轮换:`revoke jti` + 重新 issuevaultd 维护 deny jti 集合(内存 + 可选小文件)。
---
## 5. `mnote-vaultd` 规格
### 5.1 进程与监听
| 项 | P0 决定 |
|----|---------|
| 二进制名 | `mnote-vaultd`(或 `mnote vault-daemon` 子命令) |
| 默认传输 | **Unix Domain Socket**`$XDG_RUNTIME_DIR/mnote-vaultd.sock`(回退 `/tmp/mnote-vaultd-$UID.sock` |
| TCP 备选 | `127.0.0.1:17300`**默认关**;仅显式 `--listen-tcp` |
| 权限 | sock `0600`、属主当前用户;拒绝非本 uid(若 OS 支持 peer cred |
| 启动 | user systemd / 登录脚本 / 首次 CLI 自动拉起(见 §5.4) |
| 资源 | 目标:常驻 RSS 远小于 mnote-web;无浏览器、无 leptos SSR |
### 5.2 API 表面(JSON over HTTP/1.1 on UDS,或 length-prefixed JSON
与现 Pi / CLI 语义对齐,路径前缀建议 `/v1/`
| 方法 | 路径 | scope | 解密/展开 | 说明 |
|------|------|-------|-----------|------|
| GET | `/v1/health` | 无 token 也可 | 否 | `ok`, `unlocked`, `version`, `actorDefault` |
| GET | `/v1/items` | `list` | 否* | L0 列表;同现 `list_ai` |
| GET | `/v1/items/{id}` | `get` | 否* | 元数据 + 掩码;无 password 明文 |
| POST | `/v1/items/{id}/resolve` | `resolve` | **是** | body: `field`, `accountId?`, `secretId?` |
| POST | `/v1/items/{id}/login` | `login` | 内部 resolve | 可 P1 仍代理或旁路 helper |
| POST | `/v1/items/{id}/session` | `session` | 写 session | 人机回写 |
| POST | `/v1/lock` | admin | — | 清 master keyL-Crypto |
| POST | `/v1/unlock` | admin | — | 本机交互/钥匙环;**不**给 agent 默认 scope |
| POST | `/v1/tokens/issue` | admin | — | 签发 agent token |
| POST | `/v1/tokens/revoke` | admin | — | 吊销 jti |
\* list/get:若未来元数据也加密,仅解密标题等非 secret 字段;password 永不出现在 list/get。
**错误码(稳定字符串,CLI/skill 可分支):**
| code | HTTP | 含义 | Agent 动作 |
|------|------|------|------------|
| `vaultd_unavailable` | — | sock 连不上 | 尝试 autostart 或提示用户起服务 |
| `vault_token_missing` | 401 | 无 Bearer | 检查 token 文件 / env |
| `vault_token_invalid` | 401 | 签名/格式错 | 重新 issue |
| `vault_token_expired` | 401 | exp | 轮换 token |
| `vault_scope_denied` | 403 | scope 不足 | 重新签发含所需 scope |
| `vault_actor_mismatch` | 403 | token.actor ≠ AI 本 | 用正确 actor token |
| `vault_locked` | 423 | L-Crypto 未 unlock | 提示用户 `unlock`**不是**启动 mnote-web |
| `vault_item_not_found` | 404 | id 不存在 / 非 AI 本 | list 再选 |
| `vault_resolve_field_invalid` | 400 | 字段不合法 | 对齐 schema |
| `vault_resolve_ai_only` | 403 | 试图 resolve 用户本 | 策略拒绝(与 12-1 一致) |
### 5.3 与文件布局(概念,兼容 12-1)
```text
{workspaceRoot}/.mnote/vault/ # SSOTvaultd 与 mnote-web 共享读
vault-index.json
… credential markdown …
cipher-book.json
audit.jsonl # 可继续追加;vaultd 写 agent 通道审计
~/.config/mnote/
vaultd.toml # 可选:root 覆盖、ttl 默认、tcp 开关
vault-tokens/
default.token # agent 用,0600
vaultd-hmac.key # 签发 secret0600;仅 vaultd/admin CLI 读
$XDG_RUNTIME_DIR/mnote-vaultd.sock
```
**Workspace root 解析顺序(P0):**
1. 请求头 / CLI 显式 `--workspace`
2. env `MNOTE_VAULT_WORKSPACE`
3. `vaultd.toml` 默认
4. 与现 mnote-web 一致的「当前 dev workspace」约定(实现时对齐 `vault.rs` AI root 解析,避免双根)
AI actor root:继续 `MNOTE_AI_VAULT_ACTOR`token 内 `actor` 必须匹配。
### 5.4 无常驻时的退化(仍不依赖 mnote-web)
若用户不愿常驻 daemon
```text
mnote-vault-cli resolve --id X
→ 若 sock 可达:走 vaultd
→ 若不可达:CLI 内嵌 mnote-vault-core(同代码)+ 本机 token 校验
校验密钥来自 ~/.config/mnote/vaultd-hmac.key(用户可读则等同本机信任)
```
**注意:** 内嵌模式仍 **禁止** 无 token 裸读;仍 **禁止** agent 用通用 Read 打开 vault 文件。
AutostartCLI 可 `spawn` 一次 vaultduser 级),避免每个 agent 拉起全站 3000。
### 5.5 login / session 边界
| 能力 | 建议 owner | 依赖 |
|------|------------|------|
| resolve 密码字段 | **vaultd 必含** | 仅本地文件 |
| list/get | **vaultd 必含** | 仅本地文件 |
| 外站 login playbook | vaultd 插件 **或** `vault-login-helper` | 网络 + 可选浏览器 |
| Cloudflare session 回写 | 同 login helper | 人 + chrome-bridge |
P0 最小闭环:**health + list + get + resolve**。
login/session 可 P0.5 从现 mnote-web 逻辑迁出或短期仍调 web(但 **resolve 不得回退依赖 web**)。
---
## 6. Agent 侧合同
### 6.1 环境变量
| 变量 | 含义 |
|------|------|
| `MNOTE_VAULT_TOKEN` | 直接 token 字符串(会话级优先) |
| `MNOTE_VAULT_TOKEN_FILE` | 默认 `~/.config/mnote/vault-tokens/default.token` |
| `MNOTE_VAULT_SOCK` | 覆盖 UDS 路径 |
| `MNOTE_VAULT_WORKSPACE` | workspace root |
| `MNOTE_AI_VAULT_ACTOR` | 与签发 token 一致(文档提示;以 token.actor 为准) |
| ~~`MNOTE_BASE_URL` + `MNOTE_COOKIE`~~ | **读密路径废弃**;仅 human/web 调试保留 |
### 6.2 CLI 稳态(目标)
```bash
# 一次安装(人)
mnote-vault doctor # sock / token / unlock 状态
mnote-vault unlock # 仅 L-Crypto
mnote-vault issue-token … # 写入 token 文件
# Agent 每次取密(已知 id
mnote-vault resolve --id <id> --field password [--account-id …] [--raw]
# 未知 id
mnote-vault list
mnote-vault resolve --id <id> --field password
```
**删除读密对 `auth-e2e` 的依赖。**
`auth-e2e` 可留作「测 mnote-web UI」工具,**不得**再出现在 `$mnote-vault` skill 稳态步骤。
### 6.3 Skill / policy 修订点(实现阶段同步,本文先钉文案)
`/home/lix/.agent-infra/vault-policy.md``$mnote-vault` 将改为:
1. 读密:**token + vaultd/CLI**,不经 mnote-web。
2. 仍禁扫 `.mnote/vault/**`
3. 登录仍优先 `login`CF 仍 human + `session`
4. 故障树:`vault_locked` → 用户 unlock`vaultd_unavailable` → 起 vaultd / CLI 内嵌;**不要**默认 `desktop:hot`
### 6.4 Pi tools
| 现名 | 后端切换 |
|------|----------|
| `mnote.vault.list\|get\|resolve\|login\|session` | 默认连 vaultd;失败策略见 §5.4 |
| 鉴权 | Bearer token,不再注入 web cookie |
### 6.5 安全行为(agent
- 聊天 / transcript:只写 `transcriptHint`,不写 password / cookieHeader。
- resolve value 仅用于当前工具链下一步(登录、填表),不回显用户除非用户明确要求。
- 禁止把 token 贴进公开 issue / 截图。
---
## 7. mnote-web 关系与迁移阶段
### 7.1 阶段
| 阶段 | 内容 | 退出标准 |
|------|------|----------|
| **A 现状** | Agent → mnote-web cookie → 文件 | — |
| **B 并行(P0** | 抽出 `mnote-vault-core``vaultd` + CLI token 路径;web 仍可直读文件 | **不启 3000 可 resolve** smoke 绿 |
| **C 收口(P1** | web `/api/vault/ai/*` 改为调 core 或代理 vaultdskill 去 auth-e2e | 双路径一致;旧 cookie AI 路径标 deprecated |
| **D 可选(P2** | L-Crypto at-restweb unlock UI 只负责把 key 交给 vaultd | 磁盘密文;无 key 不可读 |
### 7.2 代码落点(建议)
| crate / 路径 | 职责 |
|--------------|------|
| `rust/crates/mnote-vault-core`(新) | index/load/parse、cipher expand、nested secret resolve、audit append、(P2encrypt |
| `rust/crates/mnote-vaultd`(新)或 `mnote-vault` bin | UDS 服务、token 校验、issue/revoke |
| `mnote-web` `vault_store` | 逐步 thin wrapper → coreUI 路由保留 |
| `scripts/mnote-vault-cli.js` | 默认 sock+token;保留 `--via-web` 仅调试 |
**禁止:** 在 vaultd 内重新实现第二套 frontmatter schema。
### 7.3 兼容
- 文件 schema`mnote.vault.credential.v1` 等)**不**为 12-2 破坏性变更。
- 现有 AI 本条目无需迁移即可被 vaultd list/resolveL-Access)。
- L-Crypto 若上:单独 migration 设计 + 双读窗口,不在本文展开实现细节,只保留扩展点。
---
## 8. 威胁模型(摘要)
| 威胁 | 缓解 |
|------|------|
| Agent prompt 注入要求 dump 全库 | 按条 resolvelist 无密;rate limit;审计 |
| Token 文件被同机其他用户读 | `0600` + UDS peer cred |
| Token 被复制到另一台机器 | `aud=local-vaultd` + 可选绑定 machine-id;无 hmac key 则签失败 |
| 磁盘被盗 | P0:OS 磁盘加密依赖;P2vault at-rest |
| 恶意进程连 sock | 无有效 token 拒绝;sock 权限 |
| 日志泄漏 | audit 不写 valueCLI 默认 JSON 管道、skill 禁回显 |
| mnote-web RCE | 读密不依赖 web 后,攻击面与 key 分离(P2 更明显) |
| 用户把 vault 目录加进 agent 工作区 | 策略 + Pi allowlist deny;文档披露(12-1 已有) |
---
## 9. 验收标准(设计完成 → 实现门闩)
### 9.1 P0 必须
- [x] **mnote-web 未运行**时,持有效 token 可 `list` + `resolve` 成功(AI 本已有条目)。
- [x] 无 token / 坏 token → 明确错误码,不回退匿名读文件。
- [x] resolve 响应含 valueaudit 无 value(沿用 store audit)。
- [x] CLI 稳态文档与 skill**无** `auth-e2e` 作为读密前置。
- [ ] 通用 file 工具读 vault 路径仍 deny(web 与 Pi 侧回归,既有策略)。
- [x] 单元测试:token 校验、scopestore 原有 20 测。
- [x] 集成 smoke`cargo run -p mnote-vault -- …` 不启 30002026-07-23 本机绿)。
### 9.2 P1
- [x] login/session 不依赖 webcore + CLI + UDS;外站 HTTP 仅 api_first 出站,resolve 仍本地)。
- [x] mnote-web AI list/get/resolve/login/session thin-wrap 同一 core2026-07-23)。
- [ ] policy / skill / Paseo appendSystemPrompt 全文切换(skill 已更新 login/session 本地路径;Paseo 段可再对齐)。
### 9.3 P2L-Crypto
- [ ] unlock 前 resolve → `vault_locked`
- [ ] master key 仅内存;lock 后不可 resolve。
- [ ] token 无法离线解密 credential 文件。
---
## 10. 实现 Checklist(批准设计后执行;本文件阶段只列不写代码)
### PR-1 — core 抽出
- [x] 新建 `mnote-vault-core`,从 `vault_store` 搬迁:load index、load credential、cipher expand、`resolve_record_secret_field`、AI actor root 解析。
- [x] mnote-web AI 路径 thin-wrap corelist/get/resolve/login/session);CRUD/workbench 仍可双路径。
### PR-2 — vaultd + token
- [x] token issue/verifyHMAC + 文件格式 `mnv1.*`)。
- [x] UDS serverhealth/list/get/resolve/**login/session**`mnote-vault serve`)。
- [x] audit 写入(resolve/login/session 经 store)。
- [x] CLI 默认 local-core + token`mnote-vault` binsock 优先 fallback 内嵌)。
### PR-3 — agent 面
- [x] 更新 `vault-policy.md``$mnote-vault`(读密去 auth-e2elogin/session 本地 CLI)。
- [ ] Pi tool 仍进程内 thin-wrap core(不强制走 sock;可后置切 UDS)。
- [x] smoke:不启 3000 → resolve / session+login reuse。
- [x] TESTING_REFERENCE 增补 vault-local 段落(含 session/login)。
### PR-4 — login 迁出
- [x] login/session 进 core + CLI + UDSapi_first 出站 HTTP 在 corehuman_required 仍人 + session 回写)。
- [x] skill 表述:login/session 可本地、不依赖 mnote-web。
### PR-5 — L-Crypto(另设计修订)
- [ ] 密文格式、unlock UI、迁移工具。
---
## 11. 待决问题(实现前钉死;默认推荐已标)
| # | 问题 | 推荐默认 |
|---|------|----------|
| D1 | UDS vs TCP | **UDS 默认**TCP 显式开 |
| D2 | Token 算法 | **HMAC-SHA256** 本机 secret |
| D3 | 无 daemon 时 CLI 内嵌 | **允许**,同 token 校验 |
| D4 | login 是否进 P0 vaultd | **P0 不含**P0 只 resolve 闭环 |
| D5 | web 是否立刻代理 vaultd | **P1**P0 双路径并行 |
| D6 | AI root 与多 workspace | P0 单默认 workspace + env 覆盖 |
| D7 | L-Crypto 时间表 | **不进 P0**;扩展点保留 |
| D8 | token TTL | 默认 90d;可 issue 无 exp 仅 dev |
若用户否定推荐,在本文修订表追加一行后再开 PR-1。
---
## 12. 修订记录
| 日期 | 说明 |
|------|------|
| 2026-07-23 | v1 初稿:本地文件 SSOT + vaultd + agent token;与 12-1 AI 策略对齐;L-Access P0 / L-Crypto P2;验收与 PR 切片 |
| 2026-07-23 | P0 落地:`mnote-vault-core` + `mnote-vault` CLIissue-token/list/get/resolve);无 web smoke 绿;UDS vaultd / web 共 core 留 P1 |
| 2026-07-23 | P1dlogin/session → core + CLI/UDSweb thin-wrapsession 回写 + login reuse 不依赖 mnote-web |
| 2026-07-24 | 交叉 12-3:登录态演进为 `sessions/{credId}/{accountId}.json`;CLI 语义不变,读序优先 session 文件 |
---
## 13. 批准栏(实现启动条件)
- [x] 用户确认 §2 Goals / Non-Goals2026-07-23「先按12-2实现」)
- [x] 用户确认 §11 默认决策(含 D3 内嵌 CLI)
- [x] P0**core + CLI 内嵌 resolve**login / UDS / web thin-wrap 后置
P0 交付物:`rust/crates/mnote-vault-core``rust/crates/mnote-vault`bin `mnote-vault`)。