# 个人私密空间：记事本、密码库、2FA（1.9.61）

> 1.9.63 更新：[统一个人云](unified-personal-cloud.md)取代本篇 1.9.62 的部署和日常入口：统一在设置授权；记事本和普通书签使用自动访问数据区；独立验证器迁移入 Warden。原 AES-GCM 库保留作为迁移源。下文是原版本设计/加密边界，不能据此把记事本或书签重新锁在主密码后。


## 当前实现与边界

三个独立导航入口与邮箱同级，共用一套本机主密码。它是插件自有密码库，不是 Bitwarden 客户端，也未经过独立密码管理器安全审计。当前提供记事分类、搜索和自动保存；登录条目的账号、密码、网站、备注及密码生成；独立或关联登录条目的 TOTP。暂不提供网站自动填充、Bitwarden 协议兼容、HOTP 或密码库脚本 API。

三类内容先在本机加密，密文通过个人数据云实时同步到用户自己的 D1。个人数据云沿用 `sellerfeeds-data-<scope16>`，独立于个人 MCP 网关。官方账号系统、官方 D1/R2 不接收这些内容、主密码、恢复密钥和 TOTP 种子。邮箱邮件内容规则不变：仅本机或用户明确选择的网盘；邮箱凭据仍由该用户 Worker 的 Secret 加密保存，与私密空间的本机加密是两套密钥。

## 部署与使用

1. 重载 1.9.61 插件。
2. 在三个页面的“云端设置”（与邮箱共享）授权用户自己的 Cloudflare，选择原账号，部署／升级个人数据云。OAuth 需要可选 D1 读写范围；不能用开发者 CLI 账号替用户部署。
3. 部署执行幂等 `CREATE TABLE IF NOT EXISTS`，保留原邮箱表、D1 数据和邮箱加密 Secret。只增加 `private_library_meta` 与 `private_library_records`。
4. 首次创建必须在线核对云端是否已有私密空间。主密码至少 12 字符；随机恢复密钥仅显示一次，用户另行保管。
5. 同账号换电脑后重新连接同一 Cloudflare 账号和个人数据云，先同步，再用原主密码或恢复密钥解锁。不能在云端已有库时用新主密码覆盖它。
6. 已恢复并解锁的本机副本可离线使用。Service Worker 被终止、账号切换、退出或闲置五分钟后须重新解锁。管理页隐藏时主动锁定，切换导航清除编辑器的明文。

## 加密结构

`personal-library-crypto.mjs` 使用 WebCrypto。随机 256 位数据密钥以 AES-256-GCM 加密条目（每次新 96 位 nonce），AAD 为账号作用域、库 ID、记录 ID。标题、分类、正文、密码、用户名、网站、备注及 TOTP 种子均在密文内。

主密码通过随机 128 位 salt 与 PBKDF2-HMAC-SHA256 的 600000 次迭代生成包裹密钥，包裹数据密钥；独立随机 256 位恢复密钥包裹同一数据密钥。非可导出数据密钥只留在后台内存，本机 IndexedDB 仅保存包裹密钥和加密条目，并再套现有设备密钥加密。D1 根记录仅接受固定结构的包裹密钥元数据，条目接口仅接受密文或删除标记，不接受明文附加字段。

主密码和恢复密钥同时丢失无法恢复；Cloudflare 数据库被删除也不能承诺恢复。主密码修改、恢复密钥轮换与整库导入导出尚未开放，不得在界面或交接文档冒充已实现。

## 存储、同步与冲突

- `personal-library-store.mjs`：账号作用域内的加密快照和待同步队列。
- `personal-library-sync.mjs`：操作串行化、真实账号检查、内存锁定、每条记录的 revision 与删除墓碑。
- 本机保存成功后才发起同步；网络失败显示“待同步”，保留本机密文。页面打开、保存或手动同步时与用户 Worker 同步，后台不向官方上传。
- `/library/meta` GET／首次 PUT：根记录插入一次，禁止覆盖。
- `/library/records` GET：每页 10 条，包含墓碑；PUT／DELETE 均须 `baseRevision`，SQL CAS，旧版本不能复活删除记录。
- 同一条记录两边都改动时保留本机待同步值，显示冲突。用户可“保留两份”（将本机非删除版本另存新 ID，再保留云端原条目）或明确“采用云端”。删除冲突不自动覆盖新云端修改。
- 上限 1000 个记录 ID（含墓碑）；单条记事正文 100000 字符。请求和响应均有边界，超限或本机存储失败不伪称成功。

## 权限与 TOTP

所有 `PRIVATE_LIBRARY_*` 消息必须来自本扩展的 `/manager/index.html`。不接入 `GET_STATE`、UserScript、offscreen 任务、MAIN world、MCP Tool 清单或 AI Schema。脚本声明无法增加私密空间权限。

`totp.mjs` 实现 RFC 6238，支持 SHA1／SHA256／SHA512、6／8 位、15—120 秒周期。默认 SHA1、6 位、30 秒；校验电脑时间由用户负责。可输入 Base32、`otpauth://totp` 链接或用户选择的二维码图片，拒绝 HOTP。`vault-qr.mjs` 通过随包 jsQR 1.4.0 本机解析 PNG／JPEG／WebP，最大 10 MiB／1600 万像素，无远程脚本，无上传。构建生成本地 ESM 包装及 Apache-2.0 许可证；不得改为网络加载。

复制密码／验证码写入用户剪贴板，并明确提示；插件不保证系统剪贴板历史被清除。

## 验证状态

`tests/private-library.test.mjs` 覆盖主密码／恢复密钥、随机 nonce、AAD、非可导出密钥、错误密码、18 个 RFC 测试向量、真实生成二维码的解码、只向个人 Worker 请求、SQLite 模拟 D1 CAS、明文拒绝、离线保存、换设备快照恢复、冲突保留、删除墓碑、账号切换与五分钟锁定。

Chrome 本地页面用实际视图模块与虚构数据验证记事编辑和切换自动保存、密码库布局、TOTP 倒计时和锁定清空。该页面不是已安装插件与真实用户 D1 的端到端验收。真实账号尚未代部署，真实换机同步、用户二维码和恢复流程须在用户重载与升级自己的数据云后验证。

本次最终检查：全仓 958 项测试通过，pnpm run check 通过；本地构建 1.9.61。没有代替用户部署真实个人云、创建真实主密码，也没有发布官网或 GitHub。


## 1.9.62 Warden 密码库边界

密码库与常用网站改用用户自有 Warden Worker/D1，不是脚本 API，不能向脚本/MCP/AI 提供密码或 TOTP 种子。原记事本、独立验证器和旧库保留，旧库可复制迁移但不删除。当前入口和真实验收状态以 `docs/development/warden-vault.md` 为准；本文旧版“暂无自动填充”只描述原库。
