先用 OAuth App 跑通,是很多团队的第一直觉:第一版登录、拉取仓库、提交译文全部按 OAuth App 搭好,AI 编程工具当时给出的理由是“实现简单、文档齐全”。OAuth 流程成熟,token 即拿即用,对个人项目确实够用。可项目要进企业试用后,我实测发现三个硬约束:权限边界、可观测性、组织授权,OAuth App 一个都满足不了。最后我把 OAuth 方案推倒重来,登录保留 OAuth 授权用户身份,仓库与提交全部迁到 GitHub App。这个决定让翻译任务在用户离职、权限变更时不再中断,也让企业安全评审一次通过。下面把当时的取舍过程完整写出来。
一、AI 给出的 OAuth 方案
当时 AI 生成的方案描述得很清爽:登录和仓库访问共用一个 token,不用管 App 私钥,开发量小到 1 天就能接入。对一个”先跑通再说”的 MVP,这套说辞很有吸引力,我最初也照着做了,三天就把登录和仓库拉取串起来了。
但代码搭起来之后,我总觉得哪里不对。共用 token 意味着整个应用拿到的都是用户身份的完整能力,我翻 GitHub 接口文档核对权限时发现,OAuth App 只能声明 repo、user 这类粗粒度 scope,想表达”只读某几个仓库、只写 PR 评论”这种精确边界,OAuth 根本做不到。
- 登录 + 仓库访问共用一个 token;
- 不用管 App 私钥;
- 开发量小,1 天接入。
二、为什么不能简单接受
带着”先试试”的心态跑了两周,问题陆续冒出来。最直接的一次事故是,一个测试用户被管理员移出仓库后,正在跑的批量翻译任务立刻 403 失败,用户的 OAuth token 跟着失效,整个任务队列卡死。这让我意识到 OAuth 方案的四个问题不是理论风险,而是每天都在发生的事:
| 问题 | 影响 |
|---|---|
| 权限继承用户 | 用户失去仓库访问权后,App 立即失效,翻译任务中断 |
| 速率限制共享 | 5000/h 全应用共享,大仓库扫描会撞限 |
| 提交记录为用户身份 | 难以审计,commit 列表里看是哪个 App 写的 |
| 跨组织不可扩展 | 用户属于多个组织时无法独立授权 |
速率限制那条尤其隐蔽。OAuth token 占用的是用户的主速率限制,每小时 5000 次请求,几个大仓库的元数据扫描叠加起来就撞限了,我还得在代码里加 retry 退避,问题没解决,代码倒复杂了。这类问题对”个人玩具项目”也许不致命,但本项目要进入企业试用,必须能稳定支撑生产。
三、GitHub App 的关键优势
对比之后我转向 GitHub App,它把上面四个问题挨个解决了。安装访问令牌按安装范围授予权限,App 只动授权过的仓库,用户被移出组织时应用照常工作;速率限制按安装独立计算,基础额度每小时 5000 次,组织安装还会随仓库数和用户数扩容;提交统一带 app[bot] 标识;token 默认 1 小时过期。
- 权限按安装范围授予,App 只动授权的仓库;
- 速率独立:5000/h × 安装数;
- commit 标
app[bot],审计清晰; - 短生命周期 token(默认 1 小时),泄露影响小;
- 跨组织:用户可在多个组织分别安装,按 installation_id 区分。
短生命周期 token 是我非常看重的一点。OAuth token 长期有效,一旦泄露就是长期后门;安装令牌一小时就过期,就算被偷,攻击者能用的窗口也很窄。私钥虽然要自己保管,但可以交给密钥管理系统托管,运维成本在可接受范围内。
四、增加的复杂度是值得的
迁移不是零成本,注册、私钥、安装引导、Webhook 校验都要补,当时也犹豫过要不要为这点收益折腾。做完一轮对比后我确定值得,因为每一项成本都换回了明确的安全或运维收益:
| 增加的成本 | 收益 |
|---|---|
| 注册 GitHub App | 权限更精细 |
| 私钥管理 | token 更安全 |
| 安装引导 | 用户授权边界清晰 |
| Webhook 校验 | 事件可信 |
Webhook 校验是我一开始想省掉的部分,后来被现实教育了:GitHub App 的事件推送必须验签,否则任何能往回调地址发请求的人都能伪造事件。用 HMAC-SHA256 验签后,整个事件链路才真正可信,这条成本花得值。
五、AI 建议偏差的根因
回过头看,AI 建议 OAuth 不是错,而是它的判断依据和我的约束不匹配。AI 的训练语料里 OAuth 教程占多数,它见过太多”个人项目用 OAuth 就够了”的案例;它没有真实运行环境,看不到撞限流、权限失效这些运行期痛点;它默认优化”开发量小”,没把长期运维成本算进去;它更不知道这个项目有企业落地的强约束。
- 训练语料以 OAuth App 教程居多;
- 没有真实运行环境,看不到”撞限流”的痛点;
- 默认追求”开发量小”,没考虑长期运维成本;
- 不掌握本项目”企业落地”的强约束。
六、修正 AI 建议的方法
既然摸清了偏差来源,我调整了和 AI 协作的方式。不再问”怎么做”,而是先把约束写在提示词里,再让它对比方案,最后自己拍板。
- 提示词明确给出强约束:”必须按安装粒度授权,commit 标识为 bot,速率独立”;
- 让 AI 列出每个方案的优缺点;
- 把非功能性需求(权限、审计、速率)作为强制项;
- 关键决策不交给 AI。
这样改完,AI 给的方案明显贴合实际了,它甚至能主动指出某些权限组合会有冲突。人机协作的关键是把”语境”喂给模型,而不是让它猜。
七、最终架构
最终架构里,两类身份各司其职:OAuth 只负责确认”你是谁”,GitHub App 负责”以应用身份干活”。下面这段是当时的架构备忘:
登录 ← NextAuth.js v5 + GitHub OAuth (User Access Token)
仓库 ← GitHub App + Installation Access Token
Webhook ← GitHub App
提交 ← GitHub App
权限 ← installation_id 与 user_id 双重校验
这里有个细节值得注意:登录依然用 OAuth,因为需要用户身份做界面展示和操作归属;而仓库读写、提交、事件回调全部走 GitHub App。两层身份分开后,业务代码里每次请求都要校验 installationid 和 userid 的绑定关系,防止用户越权访问别的组织的仓库。
八、给同类项目的建议
这套取舍不一定适用于所有项目,但方法论可以复用。给要做 GitHub 集成的项目几条建议:
- AI 的建议要看”前提条件”,不要照搬;
- 把项目的强约束列成 checklist,逐项过;
- 让 AI 解释”为什么”,不只是”怎么做”;
- 关键架构决策要人主导。
尤其第一条,我后来养成了习惯:收到 AI 方案先问它”这个方案成立的假设是什么”,再决定要不要采纳。
九、回归与监控
迁移上线只是开始,长期运行还要盯几个信号,防止架构漂移:
- 监控:installationid 与 userid 绑定失败率;
- 告警:单一用户安装数量异常增长;
- 复盘:定期 review 架构决策是否符合当初约束。
绑定失败率这个指标帮我抓过一次真实 bug:某次发布后大量请求 403,排查发现是安装令牌缓存逻辑写错了,缓存里的令牌过期后没有及时换新。监控到位,问题半小时内就定位了。
常见问题(FAQ)
Q1:是不是所有项目都要选 GitHub App?
不是。如果只是个人玩具,OAuth 更快。
Q2:AI 的建议什么时候值得听?
通用知识、样板代码、明确需求时可靠;架构选型要看上下文。
Q3:怎样让 AI 输出更准?
把强约束写在提示词里,并要求 AI 列前提条件。