# ADR-004: Token 不入文件,走 wincred 缓存 **状态**: ✅ 已采纳 **日期**: 2026-06-14 **决策者**: 宋献 + Claude 评审 **关联**: [[风险跟踪表]] 第十二节 12.6 / 推送约定 --- ## 1. 背景 之前 Gitea 推送 token 直接嵌入 `.git/config` 的 `origin.url`: ``` url = https://ae236991c3d5...@ds923plus.tail58d872.ts.net/... ``` **风险**: - ❌ token 明文落盘 - ❌ token 失效后难更新(URL 整体换) - ❌ 误 `git add .git/` 可能入仓(虽然 .git/config 本身不入仓,但 .git/ 目录其他文件可能) - ❌ auto-classifier 拒绝重写 URL(防误操作) **事故**: 2026-06-14 workbuddy-claude token 失效后,`origin.url` 残留死凭据。 ## 2. 决策 **`.git/config` 的 `origin.url` 只写用户名,token 走 git credential helper(wincred)缓存**。 ## 3. 实现 ### 3.1 配 remote URL(无 token) ```bash git remote add origin https://simon@ds923plus.tail58d872.ts.net/simon/wecom_it_smart_desk.git # 或修复现有: git remote set-url origin https://simon@ds923plus.tail58d872.ts.net/simon/wecom_it_smart_desk.git ``` ### 3.2 配 credential helper `.git/config`: ```ini [credential] helper = manager # Windows = wincred / Linux = git-credential-manager ``` ### 3.3 首次推(输一次 token) ```bash git push -u origin main # 弹窗 → username 留空,password = token # wincred 自动缓存 ``` ### 3.4 换 token(必走) ```bash # 清旧缓存 printf "protocol=https\nhost=ds923plus.tail58d872.ts.net\nusername=simon\n" | git credential reject # 存新缓存(一次性,token 在 heredoc 不入文件) printf "protocol=https\nhost=ds923plus.tail58d872.ts.net\nusername=simon\npassword=NEW_TOKEN\n" | git credential approve # 验证 git push origin main # 应不弹窗 ``` ## 4. workbuddy 推送同理 `.workbuddy/config.json` 是 workbuddy 自己的凭据存储(类比 .git/config),**入仓** ❌。 **正确做法**: - `.workbuddy/config.json` 写用户名/URL/其他配置,**不写 token** - workbuddy 启动时读 `gitea.token` 字段(从环境变量 / 启动参数传入) - 或者 workbuddy 自己也用 git credential helper **已加 .gitignore**: ```gitignore .workbuddy/config.json .workbuddy/config.local.json .workbuddy/*.token .workbuddy/credentials* .workbuddy/.env* ``` ## 5. 优势 - ✅ token 不入文件(只入 wincred 系统密钥环) - ✅ 换 token 简单(`credential reject` + `approve`) - ✅ 不会误入仓 - ✅ auto-classifier 不拒绝(无 token 写文件) ## 6. 风险与缓解 | 风险 | 缓解 | |---|---| | wincred 缓存被读(本机攻击) | 操作系统级防护 + 强密码 + BitLocker | | 跨设备不能用 wincred | Linux 用 `git-credential-manager`,Mac 用 `git-credential-osxkeychain` | | 换电脑忘缓存 | `git credential approve` 一次性配置 | | token 在环境变量 | 仍比文件安全 + CI 用 secret store |