开源项目 Bus Factor 不能只看贡献者数量。本文用四域条件证据矩阵,拆解代码知识、评审合并、制品发布与授权控制,帮助团队判断接受、补充内审、缓解或替代。
那天,续用评审会突然安静了。
一间假设中的评审会议室里,技术负责人把仓库页面投到屏幕上:贡献者不少,stars也很醒目,最近还有提交。采购同事问了一句:“如果关键维护者明天不再参与,谁能改核心目录、批准变更,再把可安装的包发出去?”
没人能从页面上直接回答。
先讲个场景:验证开源项目 Bus Factor,重点不是数页面上的人头,而是逐域确认代码知识、评审合并、版本与制品发布、授权控制分别由谁掌握;公开事实、合理推断与内部未知必须分开记录。
依赖续用时,先把“人多”翻译成“谁能完成关键动作”
这个场景不是某个真实客户事故,而是一种常见的续用冲突:仓库看起来热闹,真正影响连续性的动作却没有被拆开。
项目外部可以出现许多贡献者,但关键目录的知识可能仍集中在少数身份;多人可以提交PR或MR,却未必有人拥有合并资格;仓库里可以看到Release页面,也未必看得到registry的owner、发布凭证或备用发布者。源码控制面与制品控制面一旦分离,单看仓库人数就容易得出过于乐观的结论。
第一步不是计算分数,而是锁定核验对象:
圈定关键资产。按组件用途识别核心目录、构建文件、发布工作流、签名或制品入口,不把文档改动与关键逻辑改动混在一起。
设定项目自己的观察时间窗。维护节奏快慢不同,窗口应覆盖该项目有代表性的开发、合并与发布活动,而不是套用统一周期。
完成身份归一。同一个人可能使用多个邮箱、平台账号或组织身份;bot和共享账号也不能直接当作独立维护者。
记录证据层级。页面可见内容记为事实;由多条信号形成的解释记为推断;管理员、bypass、密钥和registry权限等不可见内容记为未知。
真实情况是——热闹度是项目表象,控制权才是续用问题。
核完单个组件后,团队往往还会追问:这些结果怎样进入整体依赖治理?可以继续看:
四控制域条件证据表:先判证据能走到哪一步
Bus Factor原本想回答的是:关键人员减少后,项目还能否持续运转。难点在于,“运转”不是一个动作。代码有人懂、变更有人批、版本有人发、权限有人接,缺少任何一环,连续性都可能断在不同位置。
下面这张表同时供外部评估和内部权限核查使用。它不是跨平台评分卡,而是一张证据边界表。平台机制、治理章程和仓库配置不同,判断路径也会变化;业界存在多种做法。
| 控制域 | 公开信号 | 判断依据 | 可证明 | 不可外推 | 内部补证 | 升级条件与处置动作 |
|---|---|---|---|---|---|---|
| 代码知识 | 关键目录提交历史、文件作者分布、维护活动、交接说明 | 关键资产是否持续由多个归一身份理解;人员变化前后是否出现可追踪交接 | 谁曾在选定窗口内修改特定资产;知识集中趋势是否值得关注 | 不能由commit量推出合并权、发布权或管理员权限;历史作者也不等于当前维护者 | 关键模块负责人、交接材料、接替者可独立处理的范围 | 核心知识长期落在单一身份且无交接迹象时,升级内部确认;补文档、结对维护或替代预案 |
| 评审合并 | CODEOWNERS、分支或合并保护说明、PR/MR记录、治理文件 | 评审请求、批准条件与执行合并是否由不同机制约束;公开规则能否与历史行为相互印证 | 在特定配置下,谁会收到评审请求;哪些账号公开执行过批准或合并 | CODEOWNERS不能单独证明合并权;保护规则页面不能列明所有管理员或绕过主体 | 实际合并角色、继承权限、管理员及bypass配置、紧急变更流程 | 公开角色与实际合并动作长期不一致,或关键配置不可见时,升级授权内核对;分离评审与执行职责 |
| 版本与制品发布 | Tag、Release、CI工作流、provenance、registry公开身份 | 源码版本动作、自动化执行身份和制品落库主体能否连成可解释链路 | 谁创建了可见Tag或Release;某次发布是否经过可见工作流;可见provenance关联了什么执行链 | Release作者、bot或provenance不能单独指向最终凭证持有人;源码权限不能推出registry权限 | registry owner、token或OIDC配置、手工发布入口、备用发布者、撤销与恢复流程 | 仓库发布链与registry主体无法对应,或只有单一路径时,升级内部确认;补备用发布者和恢复演练 |
| 授权控制 | 公开组织角色、治理章程、维护者名单、保护规则说明 | 治理身份与技术权限是否有明确映射;权限变更是否存在可追踪授权依据 | 公开声明的治理角色、部分规则和可见责任边界 | 公开名单无法展示未公开的继承权限、密钥持有关系或具体绕过者 | 管理员清单、团队继承关系、服务账号归属、权限变更记录、离任回收 | 同一身份横跨多个关键动作且缺少替补时,升级权限核对;拆分职责、回收遗留授权并建立继任安排 |
使用这张表时,每条结论都应带标签:事实、推断或未知。例如,“某账号创建了Release”是公开事实;“该账号大概掌握发布凭证”只能算推断;“还有谁能从registry手工发布”在缺少授权材料时就是未知。
未知不是空白备注。它会直接影响后续决策。
证据的价值,不在于看见多少,而在于知道它止步于哪里。
代码知识域:别把提交榜当成维护控制权榜
会议里的技术负责人继续往下翻。他发现,排行榜上靠前的账号并不都修改过核心目录;有人只更新文档,有人集中处理依赖升级,还有一个名字在关键代码里反复出现。
这时应把“项目有多少贡献者”改写为“关键资产由哪些归一身份持续理解”。

可执行动作可以这样排:
先画关键资产边界。将核心逻辑、构建配置、发布工作流和恢复相关文件单独列出。边界由组件在业务中的实际用途决定。
再按身份归一查看历史。合并同一维护者的邮箱、用户名和组织身份;将bot单列,避免把自动提交误算成人员冗余。
观察知识分布与交接。查看关键文件是否长期由同一身份主导,其他维护者是否做过实质修改、评审说明或接手记录。
核对人员变化前后的连续性。若主要作者减少活动,后续是否有人能够修改同类问题,提交说明中是否出现交接依据。
把代理信号写成条件句。文件覆盖法、主要作者法或半数文件覆盖法只能描述知识集中趋势,不能直接写成控制权结论。
“半数文件覆盖法”可以理解为一种地图着色:看少数人覆盖了多大范围。它能提示知识是否集中,却不会告诉你谁握着合并按钮,更不会告诉你谁能向npm或其他registry发布制品。
同样,提交活跃也有上下文。修复高频但边缘的问题,与理解低频却关键的发布脚本,不是同一种知识。一个维护者最近沉默,可能是角色变化,也可能是项目进入稳定期。公开历史只能支持当前窗口内的观察,长期连续性还要看交接材料和接替能力。
商业铁律就在于:当团队无法说清关键知识如何转移,贡献者名单再长,也不能替代继任安排。
因此,代码知识域的交付物不应是一串排名,而应是一张“关键资产—归一身份—交接证据—未知项”记录。它让下一步讨论从印象走向可追踪证据。
评审合并与授权控制:被请求评审,不等于能按下合并键
CODEOWNERS常被误读。
在GitHub的机制下,CODEOWNERS可用于对匹配文件的变更触发评审请求;是否要求代码所有者批准,要看仓库配置。换句话说,它更像“系统该叫谁来看”,不是公开授予某人最终处置权的任命书。
保护规则也要分层阅读。在具体配置允许时,管理员或指定主体可以绕过部分限制。但从平台机制存在这种能力,推不出某个仓库已经启用相同配置,更推不出具体绕过者是谁。
GitLab以及基金会、委员会治理下的项目,也应回到各自平台规则、项目章程与实际配置。治理角色描述的是组织责任,技术权限决定的是账号能做什么。二者可以重合,也可以分开。

动作上,建议沿着一条变更记录核对:
谁被请求评审;
谁实际给出批准;
谁执行合并;
合并是否受保护规则约束;
角色来自直接授权、团队继承还是治理安排;
哪些权限从公开页面无法观察。
最后一项应留在未知栏,并在组织有授权时转入内部权限核对。不要通过未授权探测去填补空白。
对比快答:CODEOWNERS能证明谁有合并权吗?
不能单独证明。一个新增判断维度是“批准是否为合并的必要条件”:如果仓库配置要求代码所有者批准,它能说明评审门槛;实际执行合并的主体仍要从规则配置和变更记录中另行确认。
反例是,某人持续收到评审请求,也经常留下意见,但最终合并始终由另一角色执行。此时“代码所有者”与“合并执行者”显然是两张名单。
对比快答:公开维护者名单和管理员名单有什么差别?
前者偏向责任声明,后者对应技术授权。还要额外观察权限来源:直接授予、团队继承和组织级角色,会形成不同的回收路径。
例如,一名维护者退出治理委员会后,公开名单已经更新,但继承权限是否同步变化,页面未必给出答案。该项应进入授权范围内的权限确认,而不是从头衔变化直接下结论。
源码仓库与制品发布:真正的单点,常藏在仓库之外
真的是仓库能合并的人多,发布就不会中断吗?未必。
如果按“谁提交、谁评审、谁创建Release”这套逻辑一直推下去,就会撞上一处断层:用户最终安装的通常是registry、镜像或其他分发通道里的制品。源码版本与可安装制品之间,还隔着Tag、Release、CI身份、发布工作流、凭证及registry授权。
仓库有人接班,不等于制品有人能发。
在GitLab中,Release可经作业、页面或API产生,也会受到protected tag等条件影响。因此,页面上的作者或bot说明的是可见执行记录,不能由此锁定凭证归属。
npm的特定OIDC可信发布流程,可让工作流基于身份联合完成发布。OIDC可以通俗理解为“工作流临时证明自己是谁”,不必把长期token直接塞进流程。但可信发布可以与npm token及手工发布并存。provenance则像制品附带的来源说明,帮助追踪构建关联;它呈现的链路不覆盖所有发布主体。
对于PyPI、Maven和镜像仓库,本安全包没有提供具体owner、token、签名或provenance可见范围。因此这里只保留核验框架,不套用npm机制:
分开记录源码仓库、版本标记和registry;
对照Release作者、CI执行身份与制品发布主体;
询问是否存在token、OIDC或手工发布入口;
登记owner、备用发布者与恢复路径;
将公开不可见的凭证持有人保持为未知。
这里的“registry”不必神秘化,它就是制品真正上架和被用户获取的分发控制面。若团队只检查仓库权限,却没有检查分发通道,Bus Factor评估就只完成了前半段。
反共识落在这里:贡献者稀少未必就是最危险的状态;更棘手的是表面参与者众多,而源码、Tag和制品发布实际汇聚到同一身份。
外部评估与内部审计:什么时候该升级
外部评估先解决“公开证据能支持什么”。内部审计再解决“公开页面看不到什么”。两者不能混为一层,更不能用未授权方式跨过边界。
外部路径可按以下顺序推进:
收集合法可见的提交、PR或MR、Tag、Release、工作流与治理资料;
完成身份归一,并按四域标注事实、推断和未知;
用组件关键性、暴露面及替代难度解释未知项的影响;
公开链路能够互相印证时,形成条件化接受意见。
出现以下情形,则应转入组织授权范围内的内部审计:关键目录长期缺少接替证据;公开合并动作与角色声明不一致;源码Release无法和registry主体对应;管理员、bypass、服务账号或备用发布者决定了连续性,却在外部不可见。
内部动作包括团队成员说明与权限导出交叉确认、检查角色继承、确认凭证归属和离任回收、验证备用维护者能否按既定流程接手。涉及平台配置时,以当前规则为准;不得尝试绕过权限或枚举凭证。
对比快答:怎么判断谁能发布npm包?
先区分“谁触发了工作流”和“谁拥有发布资格”。新增的判断条件是手工入口是否仍然开放:即使某次制品带有provenance,也要确认token、可信发布配置和registry owner之间的关系。
反例是,CI页面显示bot完成发布,但bot背后的OIDC配置由团队管理,同时另有人工token。此时可见执行者不是发布主体的完整答案。
对比快答:什么情况下应该升级内部权限核查?
当未知项正好卡住关键动作时。还应加入“撤销后能否恢复”这个视角:现有发布者即使仍在岗,若权限丢失后没有授权恢复路径,连续性风险依旧存在。
若组件只用于边缘工具,替代路径清楚,团队可以先缓解;若它处在充值结算、身份校验或代理数据核对链路,未知项的业务后果就更重。阈值应随组件位置变化,而不是套统一分数。
要把开源核验与商业第三方责任分开,接下来需要回答另一个问题:
开源控制权核验完成后,如何与商业第三方接入安全责任边界分开治理
尤其在出海游戏这类高频交互、资金敏感场景,开源依赖的续用决定会同时碰到发布连续性、结算稳定和用户数据链路。假设一个关键组件由单一身份同时掌握合并、Tag与registry发布,人员离开或凭证异常后,团队面对的不只是“版本暂时发不出”,充值结算与代理数据核对也可能一起进入无法验证来源、无法确认修复版本的状态。
从证据走向四类决策
会议回到最初的问题。技术负责人不再尝试报出一个Bus Factor分数,而是把四域证据铺开:哪些已经证实,哪些只是推断,哪些必须由内部材料补齐。
最终可以形成四类决定:
接受。四域关键动作存在可追踪证据,未知项不落在当前组件的关键控制面,并有可说明的继任与恢复路径。
升级内审。公开证据无法确认管理员、bypass、registry owner、凭证归属或备用发布者,而这些项目直接影响续用判断。
缓解。暂不替换组件,但补交接文档、备用维护者、权限拆分、制品留存和恢复安排。
替代。关键控制长期集中,补证渠道不足,且组件暴露面与替代难度使剩余未知无法被当前团队接受。
判断不会在一次检查后永久有效。维护者、平台规则、发布工作流和registry授权都会变化,结果需要跟随组件状态复核。
尤其是出海游戏业务,开源组件一旦进入充值、结算、用户数据或代理运营链路,技术依赖就不再只是研发侧的问题。WG可以从方向性风险梳理入手,协助团队把开源依赖风险评估、开源治理审计与软件供应链风险评估拆成可核对的控制域,而不是给出一个脱离配置背景的总分。
联系WG.com,可先完成一次开源维护控制权诊断,重点核查:
关键代码知识与交接证据;
评审、合并及授权边界;
源码版本与制品发布链路;
未知项对应的内审、缓解或替代动作。
真正值得挑战的,不是“这个项目有多少维护者”,而是:关键身份退出后,剩下的人是否还握有一条可验证、可接手、可恢复的完整路径。