 wuguanganandClaude Opus 5
|
a9363e43c9
|
feat: 共用密钥中心 + 项目账号密码库
两个功能来自同一个痛点,但威胁模型正好相反,这是整个设计的支点。
**共用密钥**:平台密钥(飞书、领星、OpenAI)在十几个项目里要各配一遍,
而最省事的做法——直接粘进聊天框告诉 AI——是最糟的那个。现在按平台建组、
勾给项目,物化成 ~/.vibe-foreman/env/by-project/<项目>-<哈希>.env
(目录 0700、文件 0600),复制路径给 AI。这份数据**故意是明文、故意给 AI 用**。
**账号密码**:本地/测试/线上分开记,只给人看。AES-GCM 加密,
查看和复制过 Touch ID。这份数据**绝不能被任何自动化读到**。
两者不共用存储、不共用目录、不共用界面,并用一条哨兵测试钉死
「密码的值不会出现在给 AI 的那个目录里」。
三个决定了做法的发现:
1. 「让 AI Read 那个文件」会把密钥写进两个明文文件——
~/.claude/projects/*.jsonl(0644、永久、每轮重发给 API),
以及 Hub 自己的验收清单(Evidence.ran 会存命令和输出尾巴,同样不过期)。
所以「复制给 AI」给的不是裸路径,是带 `set -a; source` 用法和
「不要用 Read/cat/grep」禁令的三句话。换成 source 之后,
transcript 里只剩路径和变量名,值一次都不出现。
2. 按项目分文件**是分装不是隔离**——同 uid 下 cat ../别的.env 照样拿得到。
README 和代码注释都按分装写,不吹成边界。
3. Keychain 的授权弹窗**就是那道防线**。SecItemAdd 不传 kSecAttrAccess 时,
默认 ACL 只允许创建它的 app 无提示读取,而在「攻击者 = 同 uid 的自动化」
这个模型下,能区分「Hub 在读」和「security 命令在读」的只有它——
文件权限做不到(同 uid),Touch ID 也做不到(LAContext 不参与取密钥)。
为了消弹窗放宽 ACL,等于一条 Bash 就能取走主密钥。
几个不写下来一定会再踩的坑(已进 NOTES.md):
- .atomic 写换 inode,chmod 必须每次都做,只在创建时设一次从第二次写起就是 0644
- GCM 的 AAD 必须用文件里存下来的那段字节,重新序列化会让历史文件永久打不开
- 「钥匙不对」和「文件坏了」处置完全相反,靠 header 里的 keyID 分辨;
EncryptedFile.save() 的 guard state.canWrite 是这套区分唯一的落地点
- LAContext 复用才有 reuse duration,每次新建等于每条密码按一次指纹
- 剪贴板定时清空必须比对 changeCount,否则用户复制的别的东西会被莫名清掉
- .env 的引号:shell / node dotenv / python-dotenv 三家的交集只有单引号;
多行值用字面换行不能用 \n;含单引号的值没有共同解,改写成 _B64 显式降级
617 个测试全过(原 530)。真 bash `set -a; source` 验过含空格、$、反引号、
#、多行 PEM 和含单引号的值。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
2026-08-17 12:45:20 +08:00 |
|
 wuguanganandClaude Opus 5
|
bfc4ebaecb
|
fix: 失效项目静默开到家目录;补上删除和"添加任意目录"
## 根因
tmux 对不存在的 `-c` 目录**返回 0 并悄悄用家目录**,`open /不存在` 则
静默什么都不做。实测:
tmux new-session -d -s t -c /不存在 ; echo $? → 0
pane_current_path → /Users/dev
projects.yaml 里 40 条有 6 条指向已删除的目录(agentx-agent 那一批),
于是表现成「Finder / VS Code 全没反应」+「Claude 开到 /Users/dev」——
看起来像刚加的右键菜单坏了,实际是数据坏了。
两个静默回落把数据问题伪装成了功能问题。我连猜三轮代码都没猜中,
最后靠"派发参数落盘 + tmux 实测"定位。
## 改动
- TerminalDispatch.open 派发前查 fileExists(isDirectory:),不通过就拒绝
- 派发日志写 launch.log(log show 对这个 app 是瞎的,ad-hoc 签名)
- hubprobe launch <项目名> [mode]:走完全相同那条路,把"界面传了哪个项目"
和"派发本身对不对"分开,这次就是没有它才只能猜
- ProjectStore.missingPaths:失效项目在两个界面上都标出来(岛上尤其必要,
那里根本不显示路径),菜单只留「从列表移除」——目录没了时每一个"打开"
类选项都是静默失败,给假的可点项等于把刚修好的问题再造一遍
- ProjectStore.remove / 工具栏「清理失效 N」:只动清单,不碰磁盘
- ProjectStore.addExisting + 「添加目录」:扫描只认 .git,monorepo 子目录和
没 git init 的目录永远进不来(实机 7 条),这是缺的那个入口
删除是文本手术,不是解析完重写 —— 保住手写的注释/别名/描述。
边界是删到下一个同级列表项或顶层键;只删 name 那行会让剩下的字段被挂到
前一条项目上,删一条弄坏两条且完全静默。11 个测试钉着。
518 个测试全过。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
2026-08-14 15:58:14 +08:00 |
|