Files
mnote/design/07-ai/process/7-76-ai-principal-web-pat-and-auth-hardening-v1.md
T

30 KiB
Raw Blame History

7-76 [process] AI 主体账号 · Web PAT · 生产级鉴权硬化 · 用户级密码箱 v1

创建时间:2026-07-26
状态:PROCESSP0P1b 已实现;§12 验收清单已勾选;P2 / 部分跨用户 e2e 残留见 §12.5)
执行看板:design/07-ai/process/7-76-execution-goal-v1.md
Owner07-ai / mnote-web control-plane auth / 12-vault(密码箱多用户与代签面)
建议 repo 落点:design/07-ai/process/7-76-ai-principal-web-pat-and-auth-hardening-v1.md

上位依据:

  • /mnt/Data1T/mnote/ARCHITECTURE.md
  • /mnt/Data1T/mnote/AGENTS.md(云首发 control-plane、libsql-local、Page AI = Pi Lab
  • design/07-ai/process/7-71-unified-ai-management-control-plane-and-pi-lab-integration-v1.md
  • design/07-ai/process/7-18-local-first-agent-file-editing-control-plane-v1.md
  • design/12-vault/process/12-1-password-vault-dedicated-crud-workbench-v1.md
  • design/12-vault/process/12-2-vaultd-local-token-agent-read-path-v1.md
  • /home/lix/.agent-infra/vault-policy.md + $mnote-vault

触发会话:

  • Paseo 28e19bd9-f091-4fa8-807b-e80b88d3aba7
    主题:生产/开发分流、屏蔽测试快速登录、让外部 AI 以正式身份访问自身记录与用户笔记;密码箱按用户隔离并支持分享给 AI。

用户已拍板(相对初稿的硬约束,不得回退):

  1. 开发态对标生产:撤下「测试账号快速登录」;开发只是在生产形态上调试,不靠 fixture 快捷入口。
  2. Web PAT 可复显:不做「创建后永远不可再看明文」;列表默认遮罩,需要时可 reveal;不是放弃安全,而是可审计的受控复显。
  3. mnote.e2e 定位改为系统 AI 主体账号(不是普通冒充测试人):拥有 AI 自己的知识库、笔记与记录;可查看别人分享给 AI 的密码;**仅持有该账号密码的人(一般是 admin)**可登录检查;普通用户不能访问该主体工作区。
  4. 外部 AI 主能力 = 用户笔记的增删读写(及必要元数据),作为再介入 Pi 内部对话的主路径。
  5. 密码箱跟随用户:一个用户只有一个密码箱(用户真源,而非「共享 workspace 一库混装」)。
  6. Admin 可代用户签发 vault token(须审计)。

1. 第一结论

本设计同时收口四件事,且它们共用同一套主体模型:

主题 结论
鉴权 UI 移除 /auth 测试快速登录与 HTML 内嵌测试密码;MNOTE_WEB_ALLOW_DEV_FIXTURES 只服务 seed/smoke 机机接口,再驱动登录页后门。
AI 主体 保留并正式化系统账号 mnote-e2e / mnote.e2e@example.comAI Principalprincipal_kind=ai_service,不是普通 e2e 人设;其工作区 / 知识库 / vault 为 AI 私有面。
机机访问 引入 control-plane Web PATmnpat1.*:外部 AI / 脚本用 Bearer 调用 JSON API;浏览器人用继续 cookie session。
密码箱 从「workspace 级单库」演进为 每用户一库;支持 share-to-AIvault capability tokenmnv1.*)与 Web PAT 职责分离admin 可代签 vault token。

一句话:
人用 cookie 登录自己的工作区;外部 AI 持 用户或 AI 主体的 PAT 做笔记 CRUD;读密另持 vault tokenAI 自己的家在 AI 主体账号 下,普通用户进不去。


2. 背景与现状

§2 保留设计前痛点快照;当前实现状态以 §10 / §12 勾选为准2026-07-26 核验)。

2.1 测试快速登录(设计前)

设计前 当前(已核验)
开关 ALLOW_DEV_FIXTURES 默认 false 不变;seed 仍 fail-closed
/auth 无开关渲染快速登录 + data-test-password 已移除按钮与测试密码 DOM
测试 断言 HTML 快速登录 断言 不含 快速登录 / data-test-password / 明文密码

2.2 AI 管理面(设计前 → 当前)

  • 7-71 /admin/ai/user/ai 主线仍在。
  • 已补Web PAT API + Bearer 中间件 + 管理 UI「API 访问令牌 / 密码箱 AI 访问」。
  • PAT 存储当前为部署侧 sealed JSON~/.config/mnote/api-access-tokens.json),非 control-plane 表;API 合同满足 7-76。
  • Page AI = Pi Lab;外部 AI 默认走 PAT + notes/tree/tools不含 Pi run scope。

2.3 密码箱(设计前 → 当前)

  • 真源仍为 workspace 下 .mnote/vault/**;用户默认落在 users/<id>/workspaces/my-space(一人一默认箱路径)。
  • share-to-AI / AI vault 路径:12-x 既有能力 + POST /api/vault/ai/token Web 签发(admin 可代签)。
  • 12-2 vaultd / mnv1 读密路径保留。

3. Goals / Non-Goals

3.1 Goals

  1. 开发 = 生产基线:登录页无快速登录、无测试密码 DOM;需要 seed 时用受控 API / CLI,不走人机后门。
  2. 正式 AI 主体mnote-e2e 升级为系统 AI 账号(可配置显示名);自有笔记/知识库/vault;可接收他人 vault 分享;人登录该账号需密码(admin 持有),普通用户无入口。
  3. Web PAT:用户与 admin 可签发/列表/撤销/复显(受控);scope 白名单;默认服务「外部 AI 笔记 CRUD」而非 Pi 会话劫持。
  4. 密码箱用户真源:每用户一个 vault 命名空间;share-to-AI 显式授权;admin 可代签 vault token 并全量审计。
  5. 凭证分职cookie / Web PAT / vault token / 扩展 token / 上游 provider key 互不冒充

3.2 Non-Goals

  • 不把外部 AI 做成第二套 Page AI 宿主;不替换 Pi Lab。
  • 不在本阶段做 OAuth2 完整 AS / 第三方 App 商店。
  • 不取消 12-2 本机 vaultd 路径;云端多用户在其之上叠加 owner 与 Web 签发。
  • 不做「admin 默认可明文浏览任意用户密码」;break-glass 若需要另开 P2 且强审计。
  • 不把 vault 挂进 graph/tree.* 为普通页面节点。

4. 主体与凭证模型

4.1 主体(Principal

principal_kind 示例 谁用 工作区 / 知识库 / vault
human 普通注册用户 浏览器人 自己的用户空间
ai_service mnote-e2e(系统 AI 主体) 外部 AI 以 PAT 操作;人仅 admin 用密码检查 AI 私有 空间
service(可选 P1 service:ops 运维脚本 极窄 health/overview,默认无用户笔记

AI 主体账号规则:

  • 账号标识稳定:username=mnote-e2e(或 system/ai,迁移期保留 e2e 兼容 id)。
  • control-plane 标记:principal_kind=ai_serviceis_system=truelogin_policy=password_holders_only
  • 禁止 对普通用户暴露「切换到 AI 账号」;禁止公开注册同名。
  • 禁止 把 AI 主体密码写进前端 HTML / 文档 / smoke 默认文案(smoke 用 env 或 vault,不进 SSR)。
  • 普通用户访问 AI 主体私有资源 → 403 principal_forbidden
  • Admin 检查:用密码登录该账号(或未来 break-glass 代登,P2);UI 上可在 /admin/ai 显示「AI 主体状态」,自动注入密码。
  • 禁止mnote-e2e 列入 MNOTE_ADMIN_USER_IDSaccess-policy.jsonadmins(历史 e2e 方便已废止)。

4.1.1 账户分离(方案 A · 2026-07-26 已落地)

账号 principal / role admin 能力 用途
mnote-admin human / admin ops/admin/*、access-policy、代签 PAT/vault、全局 AI policy
liaibo 等真人 human / user 个人笔记 / vault / 分享给 AI
mnote-e2e ai_service AI 私有工作区与知识库;外部 AI 以 PAT 操作

Admin 判定真源(保持兼容):users.role=admin access-policy.admins MNOTE_ADMIN_USER_IDS
云首发基线:admins=["mnote-admin"]MNOTE_ADMIN_USER_IDS=mnote-admin
本地 insecure 默认口令仅用于 dev(见 TESTING_REFERENCE);生产 init 必须显式 --password

4.2 五种凭证(禁止混用)

凭证 前缀 作用 持有方
Session cookie httpOnly cookie 人用浏览器全站 浏览器
Web PAT mnpat1. 机机调 mnote-web JSON API 外部 AI / 脚本 env 或 0600 文件
Vault token mnv1. 仅 vault list/get/resolve/login agent 本地 token 文件 / skill
Extension token mnext1. Chrome 扩展写 vault 扩展;禁止给 agent
Provider API Key 厂商格式 调 OpenAI 等 admin provider 配置;不是登录 MNote

原则:一种凭证一种职责。
Web PAT 不等于 登录 vaultvault token 不等于 登录 WebAI 主体密码 不等于 分发给所有用户的万能 key。


5. 生产级鉴权:撤快速登录

5.1 产品行为

环境 登录页 标准邮箱/用户名密码 /api/dev/seed AI 主体密码登录
生产 无快速登录 仅知密者(admin
开发(对标生产) 同样无快速登录 仅当 ALLOW_DEV_FIXTURES=1 的机机 seed 同生产;本地 admin 自持密码

开发调试方式:

  • 使用真实注册/登录流程,或本地已知 admin/测试人账号密码(存在密码箱或本地 secret,不进 HTML)。
  • 自动化:优先 PAT;次选 control-plane seed APIfixtures 开时);禁止依赖「快速登录」按钮选择器作为唯一 smoke。

5.2 实现落点(P0

  1. 删除 AuthPage 中测试快速登录按钮、TEST_ACCOUNT_* 常量注入 DOM、data-test-password 等。
  2. 清理 AUTH_SCRIPT 中 quick-login 分支;表单脚本不得依赖 quickLogin 节点(避免 if (!quickLogin) return 整页失效)。
  3. 更新 gateway.rs / 相关 SSR 测试:断言 不包含「测试账号快速登录」与测试密码属性。
  4. scripts/TESTING_REFERENCE.md、AGENTS smoke 文案:改为「开发用标准登录或 PAT;fixtures 仅 seed」。
  5. 可选 harden:对 principal_kind=ai_service 的密码登录增加审计日志 auth.ai_principal.loginrate limit 加强。

5.3 明确不做

  • 不把快速登录藏到「连点 logo 十次」之类隐藏手势。
  • 不在生产 HTML 注释里保留 e2e 密码。

6. Web PAT(外部 AI 访问合同)

6.1 产品 IA

/user/ai → 导航 「API 访问令牌」#ai-api-tokens

用户只管理 自己的 PAT

  • 创建:名称、过期、scope 勾选(白名单)。
  • 列表:前缀 mnpat_****abcd、创建/最后使用/过期、状态。
  • Reveal(可复显):默认遮罩;用户点击「显示」→ 二次确认(或短时 re-auth)→ 展示明文;操作写审计。
  • 撤销 / 改名 / 旋转(rotate = 废旧发新,旧 jti 立即失效)。
  • 文案:用于外部 AI、脚本访问 你的 笔记与授权 API不是 vault 读密 token不是 Pi 内部会话钥匙。

/admin/ai「API 访问令牌」

  1. 平台级 service PAT(可选,窄 scope)。
  2. 代签:选择主体(普通用户 或 AI 主体)→ 生成该 sub 的 PAT + 审计。
  3. 强制撤销任意 PAT、查看元数据与审计。
  4. AI 主体 预置/轮转「给外部 AI 用的主 PAT」的运营入口(仍走同一表结构)。

6.2 可复显的安全模型(相对「只显示一次」)

用户明确要求 可再显示,因此采用:

创建时:
  raw = 高熵随机 或 mnpat1.<payload>.<sig>
  token_hash = SHA-256(raw)          // 鉴权比对
  token_sealed = Seal(server_key, raw) // 可恢复密封(AEAD
  token_prefix = raw 前后缀展示位
  明文不进日志

Reveal
  校验 session 为 owner 或 admin 代操作权限
  解封 token_sealed → 返回明文一次响应
  写 audit: api_token.reveal

鉴权请求:
  只比对 token_hash,不走 sealed 热路径

约束:

  • server_key 来自部署密钥(env / 文件 0600),进库、不进前端。
  • Reveal 限流(按 user / token_id);列表默认永不自动展开。
  • 若部署选择更高安全档(PAT_REVEAL_MODE=create_only),可编译/配置为创建后清空 sealed —— 默认产品档为 reveal_allowed(符合本拍板)。
  • 泄露响应:revoke + 轮转;审计含 jti 不含 raw。

6.3 Token 形态与存储

mnpat1.<base64url(payload)>.<base64url(sig)>
# 或 mnpat1_ + 高熵 random(服务端只存 hash + sealed

Claims(逻辑字段,无论 JWT 形还是 opaque):

{
  "v": 1,
  "iss": "mnote-web",
  "aud": "mnote-api",
  "sub": "user:<user_id>",
  "principal_kind": "human | ai_service | service",
  "scope": ["notes.read", "notes.write", "tree.read", "tree.write"],
  "workspace_ids": ["*"],
  "jti": "...",
  "iat": 0,
  "exp": 0
}

control-plane 表 api_access_tokens

id, jti,
subject_user_id,              -- 权限主体
created_by_user_id,           -- 签发者(admin 代签可不同于 subject
name,
token_prefix,
token_hash,                   -- 鉴权
token_sealed,                 -- 可复显密封;create_only 模式可空
scopes_json,
workspace_ids_json,
expires_at, revoked_at,
last_used_at, last_reveal_at,
created_at, updated_at

6.4 Scope 白名单(对齐「外部 AI = 笔记 CRUD」)

P0 默认推荐(创建向导默认勾选):

Scope 含义 外部 AI 默认
notes.read 读页面/文件正文与元数据(授权工作区内)
notes.write 创建/更新/删除笔记正文(授权范围内)
tree.read 读树/目录投影
tree.write 新建/重命名/移动/归档(tree.* ✓(可默认关,产品可选)
ai.settings.read 读自己的 effective AI 设置 可选
ai.usage.read 读用量 可选

默认不开放(Non-Goals / 需显式高危勾选):

Scope 说明
ai.sessions.write / pi.run 作为外部 AI 主路径;避免外部 agent 驱动内部 Pi
ai.admin.* 仅 admin session 或 admin 级 service PAT
vault.resolve 塞进 Web PAT 默认;读密用 mnv1
provider.keys.read 禁止;上游 key 永不经 PAT 下发明文

映射实现:

  • 优先复用现有 /api/mnote/tools/* 与 local-folder / page / tree 路由的 统一鉴权中间件
  • 每个 handler 声明 required scopes;缺 scope → 403,不静默放大。
  • directory_grants / membership 仍然生效PAT 不能绕过文件夹授权。
  • 写入走既有版本/冲突/watcher 纪律(对齐 7-18);外部 AI 写文件 = 授权 roots 内 patch/write,不是第二套真相。

6.5 鉴权中间件规则

  1. 请求带 Authorization: Bearer mnpat1… → 走 PAT忽略 cookie 叠加(避免权限并集歧义)。
  2. 仅 cookie → 人用 session(现有行为)。
  3. 绑定 RequestContext.user_id = subject_user_idauth_method = pat,附带 scopes。
  4. AI 主体 PATsubject 为 AI 用户 id,只能访问 AI 私有空间 + 显式 share 给 AI 的资源
  5. 人用户 PAT:只能访问该用户被授权的 workspace 资源。
  6. HTML SSR 管理页:不以长期 PAT 当 cookie 渲染全站;机机走 JSON。P2 才考虑 exchange code → 短会话。

6.6 调用示例

# 外部 AI:以某用户 PAT 列树 / 读写笔记
curl -H "Authorization: Bearer mnpat1.…" \
  https://<host>/api/…   # 具体 path 以 tools/tree/page 现网为准

# 外部 AI:以 AI 主体 PAT 写 AI 自己的知识库笔记
curl -H "Authorization: Bearer mnpat1.…" \
  https://<host>/api/…

Agent 持有方式:环境变量或 0600 文件(对齐 vault token 习惯);禁止默认写入前端 localStorage。


7. AI 主体:自己的知识库、记录与「被分享的密码」

7.1 AI 私有面

AI 主体拥有与普通用户同构的能力边界,但 默认不对普通用户可见

能力 说明
笔记 / 树 AI 自己的 workspace(或 system workspace 绑定 AI 主体)
知识库 LightRAG 命名空间绑定 AI 主体;索引 AI 私有笔记与授权语料
设置 /user/aiAI 主体 session 下的 effective 配置;admin 可在 /admin/ai 看全局
Vault AI 自己的一箱 + 他人 share-to-AI 的只读投影

普通用户 不能

  • 打开 AI 主体的 FileTree / 笔记(无 membership)。
  • 列出 AI 主体 vault 私有条目。
  • 使用 AI 主体密码(除非 admin 运营持有)。

Admin 可以

  • 密码登录 AI 主体做检查(审计)。
  • 代签 / 撤销 AI 主体的 Web PAT 与 vault token。
  • 在管理面查看 AI 主体健康、用量、token 元数据(默认无 vault 明文)。

7.2 分享密码给 AIshare-to-AI

用户 U 的 vault 条目 C
  → 用户标记 share_to_ai = true
     或 创建 share grant: (item_id, grantee=ai_principal, perms=resolve|list)
  → AI 主体的 vault token / AI 读密路径可见 C
  → 用户 U 的其他条目默认不可见
  → 其他用户 V 不可见 C(除非另有 grant)

隔离验收:

  1. 用户 A token 不能 resolve 用户 B 私有条目。
  2. AI token 只能 resolveAI 自有条目 有效 share-to-AI 条目。
  3. 用户 A 的 Web PAT 默认 不能 resolve 密码;除非错误地签发了 vault scope(产品向导应拆分两步,默认不勾)。
  4. 撤销 share 或 revoke token 后立即失效。

7.3 与 Page AIPi)的边界

角色 职责
Pi Lab(内部) 浏览器内 Page AIcookie + directory_grants;不依赖外部 PAT
外部 AIPaseo/Codex/…) 持用户或 AI 主体 PAT,做 笔记/树 CRUD;可选另持 vault token 读密
禁止默认 外部 AI 用 PAT 驱动 /api/page-ai/pi/* 代聊、劫持内部 session

若未来需要「外部系统触发一次 Pi run」,单独立项高危 scope,不进 7-76 P0 默认。


8. 密码箱:一人一箱 + 代签

8.1 真源模型(升级 12-1

产品口径(冻结):密码箱跟随用户,一个用户只有一个密码箱。

推荐存储解析:

# 逻辑
VaultRoot(user_id) → 用户私有系统目录

# 物理(云 / 多用户服务器,推荐)
{control_or_data_root}/users/<user_id>/vault/**

# 物理(单机 local-first 兼容)
若部署仅有单用户绑定默认 workspace:
  可仍落在该用户默认 workspace 的 .mnote/vault/**
  但元数据必须带 owner_user_id,且 API 按 user_id 解析,禁止「同事共享 workspace 就共享密码箱」

禁止:

  • 多个 human 共用一个无 owner 的 workspace vault 当默认。
  • Agent 用通用 file 工具扫任意 vault 路径。
  • 默认 actor 写死所有人共用 mnote-e2e 而不校验 owner(开发本机单用户过渡期除外,须文档标明)。

条目 frontmatter / index 强制:

ownerUserId: <user_id>
shareToAi: bool | grant refs

旧数据迁移:

  • ownerUserId → 归属「当前 workspace 的 owner 用户」或部署配置的 MNOTE_VAULT_LEGACY_OWNER;迁移完成前,非 owner deny。

8.2 Vault token claims 升级

在 12-2 VaultTokenClaims 上强制:

{
  "v": 1,
  "iss": "mnote-vault",
  "aud": "mnote-vault",
  "sub": "user:<user_id>",
  "actor": "user:<user_id>",
  "principal_kind": "human | ai_service",
  "scope": ["vault.list", "vault.get", "vault.resolve"],
  "item_ids": [],
  "include_shared_to_ai": true,
  "workspace": null,
  "iat": 0,
  "exp": 0,
  "jti": "..."
}
  • item_ids 非空 = 白名单;空 = 该主体命名空间内策略允许的全部(仍受 share 与总闸)。
  • AI 主体 tokeninclude_shared_to_ai=true 时合并分享投影。
  • Admin 代签created_by 记 adminsub 仍是目标用户或 AI 主体;必须审计 vault_token.issue.delegated

8.3 签发入口(同一后端)

入口 能力
/vault →「AI 访问」 用户 管自己的条目可见性、签发/撤销自己的 vault token
/user/ai →「密码箱 AI 访问」 用户 总闸、复制 token、测 doctor;深链避免双真源
/admin/ai →「密码箱治理」 Admin 代签、强制撤销、元数据与审计;默认不 reveal 用户密码明文

总闸:

user.settings.vault_ai_access = off | resolve_only | resolve_and_login

总闸 off → 既有 token verify 失败或签发拒绝。

8.4 与 Web PAT 的关系(再强调)

需求 钥匙
外部 AI 增删读写用户笔记 Web PAT(用户 sub
外部 AI 写 AI 自己的笔记/知识库 Web PATAI 主体 sub
外部 AI / skill 读密 Vault token mnv1(对应用户或 AI 主体)
人打开 /vault 编辑 Session cookie
扩展保存密码 mnext1

创建向导默认 两步拆分:「笔记 API 令牌」与「密码箱令牌」,禁止一键「全能钥匙」无 scope 确认。


9. 信息架构汇总

/user/ai 侧栏

  1. Overview(已有)
  2. Models / Tools / Skillseffective
  3. 目录权限(directory_grants,唯一授权真源)
  4. API 访问令牌Web PAT,可复显)
  5. 密码箱 AI 访问vault token + 总闸 + share 摘要)
  6. Sessions / Usage(人用 Pi;外部 AI 不依赖此写路径)

/admin/ai 侧栏

  1. 全局 provider / model / policy7-71
  2. API 访问令牌(平台 + 代签 + AI 主体 PAT)
  3. 密码箱治理(代签 vault token / 强制撤销 / 审计)
  4. AI 主体(状态、是否可登录、最近登录审计、知识库/工作区绑定)
  5. 环境健康只读:快速登录已移除、fixtures 开关状态、PAT reveal 模式

/auth

  • 仅标准登录/注册。
  • 无测试快速登录、无测试密码 DOM。

/vault

  • 当前登录用户 的唯一密码箱工作。
  • 条目:允许 AI 使用 / 分享给 AI
  • AI 访问令牌入口深链到 /user/ai#vault-ai-access

10. 分阶段落地

阶段 内容 验收要点 状态(2026-07-26 核验)
P0 删除快速登录 + 修脚本/测试/文档;AI 主体字段标记最小落库 任意环境 HTML 无测试密码;标准登录可用 done
P0.5 PAT API + Bearer 中间件 + /user/ai·/admin/ai PAT UIsealed 复显) 外部 AI 用 PAT 完成 notes/tree 读写 done(代码+单测;端到端 smoke 建议补)
P1 用户级 vault 路径 + share-to-AI + vault 区 A 不能读 BAI 能读 share done(主路径):复用 users/<id>/… + 12-x share-to-AIWeb 签发 vault token
P1b Admin 代签 PAT/vault token、撤销、审计;AI 主体运营 代签有 created_by 审计 done
P2 PAT exchange 短会话、break-glass、service 细粒度、PAT_REVEAL_MODE=create_only 高级场景 deferred

实现顺序回顾: P0 → P0.5 → P1/P1b 已合入主工作区;P2 不阻塞产品主路径。


11. 安全边界清单

  1. 凭证分职,禁止用 vault token 调笔记 API 或用 PAT 当 master key。
  2. PAT 与 cookie 不同时并权。
  3. Scope 白名单 + handler 强制;默认不含 Pi 写入。
  4. directory_grants / membership 不可绕过。
  5. PAT reveal 可审计、限流;日志无 raw token。
  6. AI 主体私有资源对普通用户 403。
  7. share-to-AI 显式;撤销即时。
  8. Admin 代签全审计;默认不 reveal 他人 vault 明文。
  9. 扩展 token 禁止进 agent。
  10. 开发对标生产:无登录页后门。

12. 测试与验收

勾选口径:[x] = 代码已实现且本轮有单测/静态核验证据;未勾选 = 未做独立 e2e 或仅结构依赖、需后续补测。
核验日:2026-07-26。证据:auth.rs / api_access_token.rs / middleware/request_context.rs / ai_admin UI / cargo test -p mnote-web --lib 定向套件。

12.1 P0 鉴权

  • /auth HTML 不含「测试账号快速登录」、data-test-password、硬编码 e2e 密码属性。
  • 标准注册/登录仍可用(auth_api_* 单测通过)。
  • ALLOW_DEV_FIXTURES=0/api/dev/seed 403(既有 fail-closed 保留)。
  • 相关单元/SSR 测试已改断言(auth_entry_uses_mnote_web_login_ui_when_compat_enabled)。

12.2 Web PAT

  • 用户可创建/列表/撤销/复显自己的 PAT(/api/ai-tokens* + UI)。
  • Bearer 可 notes.read/write(及 tree scope):middleware + documents/tree/tools ensure_scope
  • 缺 scope 403ensure_scope_session_passes_pat_requires 单测)。
  • 用户 A 的 PAT 不能写用户 B 的私有笔记(结构上仍受 directory_grants/membership无独立 PAT 跨用户 e2e)。
  • AI 主体 PAT 不能读普通用户未授权笔记(同上,依赖 grants,无独立 e2e)。
  • 默认不能调用 Pi run APIPAT scope 白名单不含 Pi;无 pi.run)。
  • reveal 产生审计(api_token.reveal+ 30s 限流生效(代码路径)。

12.3 Vault 多用户

  • 每用户一箱路径解析:users/<id>/workspaces/my-space + AI vault 路径(12-x / vault-core)。
  • owner mismatch → denyshare 模型与路径隔离已有;全量 owner 字段强制校验未单独立项闭环)。
  • share-to-AI 后 AI resolve / 取消分享:12-x vault-core share/unshare 能力与单测保留。
  • Admin 代签 vault token 有审计(POST /api/vault/ai/token + vault_token.issue(.delegated))。
  • 通用 file/RAG 仍排除 vault(12-1 既有门闩,本轮未回退)。

12.4 AI 主体

  • mnote-e2e 注册标记 role=ai_service/api/ai-admin/users 返回 principalKind
  • 普通用户 session 无法打开 AI 主体工作区(依赖 membership/默认私有 workspace无专用 403 e2e)。
  • Admin 密码登录 AI 主体成功且有专用审计事件(通用登录可用;未单独埋 auth.ai_principal.login e2e)。
  • AI 知识库命名空间隔离冒烟(未做本轮专项 smoke)。

12.5 残留 / 下一步(不回退已勾选)

  1. 补 PAT 跨用户拒绝 e2eA token → B 笔记 403)。
  2. 补 AI 主体工作区拒绝 / 知识库隔离浏览器 smoke。
  3. 可选:PAT 迁 control-plane 表;AI 主体专用登录审计。
  4. P2 整包延后。
  5. 零散脚本:scripts/test-handle-qa.js 已改为标准登录(本轮核验时修正)。

13. 与现有设计的衔接 / 覆盖关系

文档 关系
7-71 在 effective AI 配置之上增加 Token / AI 主体运营区段;不另起第二套 provider 真相。
7-18 外部 AI 写笔记仍受 AiAccessScope / allowed roots / 冲突模型约束;本设计补 谁持何种凭证进入
12-1 工作台 UI 保留;存储归属从 workspace 单库升级为 用户一箱(本文 §8 为增量合同)。
12-2 vaultd + mnv1 路径保留;claims 强制 user/AI ownerWeb 代签与多用户 verify 为增量。
12-3 mnext1 仍仅扩展;不与 PAT/mnv1 合并。
AGENTS / TESTING_REFERENCE 删除「优先测试账号快速登录」作为生产或默认真路径的表述。

后续若 vault 用户根路径实现细节膨胀,可再拆 12-4-user-scoped-vault-and-share-to-ai-v1.md,但 产品口径以本文为 SSOT,避免双源。


14. 开放实现细节(不阻塞 P0

  1. AI 主体 username 是否长期保留 mnote-e2e 字符串,或迁移为 system-ai(兼容 id 映射)。
  2. VaultRoot 物理根:control-plane data dir vs 用户私有默认 workspace —— 实现选一种并写迁移脚本。
  3. Web PAT 用 opaque+hash 还是可验证 signed payload —— 两者均可,表结构已支持。
  4. 外部笔记 CRUD 优先挂现有 mnote_agent_tools 还是一组更窄的 REST 资源路由 —— 建议 先中间件 + 现有 tools/tree/page,少造表面。

15. 建议 PR 切片

PR 内容 风险
PR-A 删除快速登录 + 测试/文档 低;立刻降公网面
PR-B api_access_tokens schema + middleware + 单测
PR-C /user/ai PAT UI(创建/列表/撤销/reveal
PR-D notes/tree 路由 scope 接线 + 外部 AI smoke
PR-E 用户级 vault root + owner + share-to-AI 高(数据迁移)
PR-F admin 代签 + AI 主体运营 + 审计

16. 完成定义(Definition of Done

当下列全部成立时,本稿可迁 done/

# 条件 状态
1 登录页无快速登录后门,开发/生产行为一致 满足P0
2 外部 AI 可仅凭 Web PAT 在授权范围内笔记 CRUD,无需 cookie/Pi 代码满足;建议补浏览器/API smoke
3 AI 主体隔离笔记/知识库,仅密码持有者可人登检查 部分满足(角色标记+默认 workspace;缺专用 e2e
4 密码箱用户隔离 + share-to-AIvault token 与 PAT 分职 主路径满足
5 Admin 代签与 reveal/revoke 有审计;文档与 smoke 一致 满足(残留见 §12.5

结论: 不迁 done/ 直至 §12 未勾选项(跨用户 e2e / AI 主体工作区 / KB 隔离 smoke)补齐或明确降级为 follow-up。P0–P1b 产品主路径可按 PROCESS 继续使用。


17. 变更记录

日期 说明
2026-07-26 初版:吸收 Paseo 28e19bd9-… 讨论与用户六条拍板;落盘 7-76
2026-07-26 执行:P0P1b 落地(见 7-76-execution-goal-v1.md);P2 延后。
2026-07-26 核验并勾选 §10/§12 已完成项;修正 test-handle-qa.js 残留快速登录;§12.5 记录残留。