MTR104前驱本地闭合与发布入口(2026-10-25T15:06:18.333018+00:00): DIAG最终own R2/本地1a9cd767、组合AF1十阶段192唯一PASS、FIX13最终own R6/本地cca52ccd及FIX12最终own R5 8c66b333四PASS/本地4b763c5均已实际核验;三笔精确signed/DCO提交和独立GPG通过,origin仍b7df/0.42.72,未push。当前执行前沿MTR104自身ER05→另审具体C1→唯一patch完整C/D→102→103→11→40→13→39→92→12/H1→LTR10→11→12→LTR01/H2,另有95/93→102。两child仍locally-accepted并等待104覆盖,正式17/118、0/26、17/144及外部资格1/4不变。Libra FIX04 A1全量10761/21原ignored/2原生flake、源B/ownPASS已核,C/D待;两flake根因未证,资格完成前真实基线及FIX/DEFER条件保持。原REL-MTR-FIX-01退出、FIX3耗尽预算/所有FAIL-STOP、唯一publisher/no-push及H0~H6其它依赖不变。
FIX13实际本地提交与FIX12开工前沿(2026-10-25T14:49:01.072868+00:00): DIAG-MTR-01最终own R2 PASS及signed/DCO本地1a9cd767、组合AF1十阶段/192唯一PASS/root资源后检均已核。FIX-MTR-13实际自己的R4源ER05 PASS/H0 FAIL保留;R5 fd398e89与最终R6 c0ce5ca0四PASS,精确七路径signed/DCO本地提交cca52ccd,实际GPG416E…E0C及完整tree已核。FIX13仍locally-accepted、C/D待MTR104,未push;当前执行前沿为FIX-MTR-12最终增量ER05/精确九路径localcommit→MTR104自身审查/完整C/D→102→103→11→40→13→39→92→12/H1→LTR10→11→12→LTR01/H2,另有95/93→102。正式17/118、0/26、17/144不变;外部资格1/4。Libra FIX04 A1/full10761/21原ignored/2原生flake、源B与own e76e3d02 PASS已核,C/D待;两flake根因未证、资格完成前真实基线及FIX/DEFER条件保持。原REL-MTR-FIX-01退出、FIX3耗尽预算/全部旧STOP、唯一publisher/no-push与H0~H6其它边不变。
AF1实际终态与子卡提交前沿(2026-10-25T14:33:05.791314+00:00): DIAG-MTR-01最终自身Claude R2 a3f7bd2d PASS及signed/DCO本地提交1a9cd767已核,未推送。REL-MTR-ENV-01 R7已采纳;组合AF1十阶段exit0、五完整模块101+73+11+4+3=192唯一PASS,root于14:24:46Z核实际新编译产物、原107库名称owner及资源终态,未手工清理。FIX-MTR-13/12各自最终增量ER05与精确localcommit待;MTR-104完整C/D尚未准入。现行链99→DIAG→FIX13→FIX12→104→102→103→11→40→13→39→92→12/H1→LTR10→11→12→LTR01/H2,另有95/93→102;其余H0~H6不变。正式17/118、0/26、17/144不变,外部资格1/4。Libra FIX04 A1全量10761/21原ignored/2原生flake、源B与本地Claude e76e3d02 PASS已核,仅locally-accepted,C/D待;两flake根因未证,资格完成前按具名P2补FIX/DEFER及真实基线证据。FIX02旧C1 STOP/stash与FIX03后继保持;原REL-MTR-FIX-01退出、FIX3耗尽预算及全部旧STOP不复位。
REL-MTR-ENV-01实际采纳与组合源准备(2026-10-25T13:23:46.846168+00:00): DIAG-MTR-01 D1实际GO,七阶段exit0、root资源/来源后检与ownClaude06c202a4 PASS已核;仅证明受控Request机制,不证明历史Interrupted/交错/C2。REL-MTR-ENV-01切换R1/R2/R3/R4/R5/R6失败原件保留;实际R7 ed5d6a31-7828-40e2-bc13-2442d0932b57 于2026-10-25T13:21:47.060495+00:00 五项PASS,root已采纳;2026-10-25T13:23:18.332588+00:00 在独立legacy clone精确形成四测试文件组合树并同步21份治理。没有新AF1/C claim或提交/push;最终采纳文本自身审查及DIAG精确本地签名提交仍待。现行完整执行链:MTR-99→DIAG-MTR-01→FIX-MTR-13→FIX-MTR-12→MTR-104→MTR-102→MTR-103→MTR-11→MTR-40→MTR-13→MTR-39→MTR-92→MTR-12/H1→LTR-10→LTR-11→LTR-12→LTR-01/H2。另有MTR-95/MTR-93→MTR-102;H0~H6其余原边不变。正式17/118、0/26、17/144不变。Libra外部资格1/4;FIX04恢复R2 session15ccf47d于12:26:41Z四PASS,root采纳及精确恢复12:28:09Z已完成;执行审c8ad29bf于12:37:57Z四PASS,A1于12:38:25.742703Z已claim,终态/自身ER05/C/D尚未取得。FIX02旧C1 STOP及stash988ded20保留;FIX01→FIX04→FIX02→FIX03不替代H1。
历史R7候选快照(采纳前): 环境修复聚合资格切换R7候选(2026-10-25T13:18:15.748263+00:00,仓外待审): DIAG-MTR-01 D1实际GO,七阶段exit0、root资源/来源后检与ownClaude06c202a4 PASS已核;仅证明受控Request机制,不证明历史Interrupted/交错/C2。REL-MTR-ENV-01切换R1/R2/R3/R4/R5/R6实质G13 PASS但ER03/文档/H0总FAIL,原件保留;本R7将MTR01的H0~H6映射、SSOT §1 H0单审、两正文依赖登记与五索引对齐,并补Libra修订记录及显式历史来源说明;旧资格计划文件仍具名保留待FIX03受控整合,仍仓外待审、未正式合源/claim AF1或C。候选完整执行链:MTR-99→DIAG-MTR-01→FIX-MTR-13→FIX-MTR-12→MTR-104→MTR-102→MTR-103→MTR-11→MTR-40→MTR-13→MTR-39→MTR-92→MTR-12/H1→LTR-10→LTR-11→LTR-12→LTR-01/H2。另有MTR-95/MTR-93→MTR-102;H0~H6其余原边不变。正式17/118、0/26、17/144不变。Libra外部资格1/4;FIX04恢复R2 session15ccf47d于12:26:41Z四PASS,root采纳及精确恢复12:28:09Z已完成;执行审c8ad29bf于12:37:57Z四PASS,A1于12:38:25.742703Z已claim,终态/自身ER05/C/D尚未取得。FIX02旧C1 STOP及stash988ded20保留;FIX01→FIX04→FIX02→FIX03不替代H1。
Libra profile警告恢复H0候选(2026-10-25T12:03:44.446299+00:00,仅仓外未采纳): FIX02 C1实际STOP:9阶段exit0、full10761/21原ignored/0retry/0flake保留,release一项项目dead_code涉及两构造器;native build数值退出未记录,安装/提交/发布未执行。root已确认0owned/孤儿/target与实际云16表0/R2空;source审ce6fb162 SOURCE PASS、RECOVERY FAIL两P1由新qualification FIX04候选修订。外部候选四实现卡1/4,顺序01(done)→04→02→03;各自G07全C/D,H1/LTR10/LTR01不豁免。正式17/118、0/26、17/144不变。Mega D1于11:39:55Z实际claim,本H0源仅在D1协调器实际退出、资源closed,且D1自身review(原工具句柄24409)已有实际终态并完成root采纳/收据之后,按当时before hash逐项匹配采纳;任何不匹配先重建overlay并重审;本候选不预判D1 GO或REL eligible、不授新窗口。
恢复R2实际PASS与R3静态设计订正(2026-10-25T10:39:09.077932+00:00): 本地Claude09357ed6四PASS、两P1已闭;root于10:38:02Z保存并精确退出FIX13自己失败的.73两Cargo为.72,其它来源及空index保持。R2五P2由root承接:默认10次退避保守70秒,因此在D1尚未claim前提议RED/502新实验进程90秒,其它30秒/ready10秒、总3600不变;不改产品重试/原单测超时/旧窗口。R3及具体执行器仍须实际PASS;DIAG未claim、REL-MTR-ENV-01仍pending、无新C/合树/发布准入。源码guard相对真实dirty前像,重试类型集合只允许Request/Interrupted;两blocked卡旧依赖标历史。
恢复方案R2修订候选(2026-10-25T10:33:30.462307+00:00): 已保留R1真实FAIL并修订正文依赖/发布/里程碑与严格GO/NO-GO;REL-MTR-ENV-01仍pending、无诊断claim/新C/合树资格。原单本地Claude审查指令继续有效。
FIX13 C1失败后的新恢复候选(2026-10-25T10:18:00.497984+00:00): FIX13 C1已FAIL/STOP(2796PASS/3FAIL/3原ignored,20targets/双build未跑),A174及ownR3仅保存;FIX12 C1 STOP同样保留。新DIAG-MTR-01诊断候选pending、MTR-104聚合候选blocked,REL-MTR-ENV-01仅pending不授合树/发布;source审54cf861e确认proxy缺陷但历史选路待证。当前前沿为DIAG具体准入→机制证据→另审恢复边界,102/103/H1不解锁。正式17/118、0/26、17/144(活动17/117、0/25、17/142);外部资格1/3。LibraFIX02 A2及自身R2 PASS,独立C1于10:09:46Z开始,.30.88本地待门,未提交/推送/发布。 原REL-MTR-FIX-01仍退出,旧FIX3的3/3、8/8与全部STOP不重置。单审依据用户原话“審查變爲單審,不要使用隔離的 Codex ,使用 Claude 進行審查”;该指令的原始UTC未提供,不虚构日期,本轮于上述UTC继承登记;只用本地Claude命令。下文旧时点原件保留。
FIX13 own最终审查R3与C准入候选(2026-10-25T09:38:18.648958+00:00): Claude session b32370dc-66f2-47e0-aad1-5a8e78ff6cfd ER03/ER05/H0/VERDICT全部PASS;source41c495与原174例资格不变,原A1 STOP保留。C尚未claim;新C执行审查R2须绑定本次最终pre-bump治理与严格被测树=提交树执行器。FIX13未提交/推送/发布,正式17/142不变。
FIX13 C前最终树一致性修订(2026-10-25T09:29:58.013813+00:00): own ER05/H0 R2 session92b5eb48已PASS,原A1计数STOP/零重跑恢复证据不变。root复核模板ER-04第③步“最终待提交树”后,不采纳C执行审查810a9a95的P2-5中C后再改治理再提交的建议;该原审PASS保留,但新的发布执行准入须重新审。C尚无entryclaim/claim、版本仍.72,没有消耗C1窗口。现明确C开始后全部tracked字节冻结直至本卡提交/推送/tag/D观察;被测树=提交树,任何tracked差异STOP,不设治理白名单。后置结果只在实际产生后先保留仓外原件,D终态后由root在既有治理路径本地如实回填,随已登记后继FIX12的治理写集/其最终C/D发布,不单独开证据版本,不改写FIX13被测commit。两仓正式17/116、0/26、17/142及依赖不变。
FIX13自身ER05/H0已PASS,C输入补齐(2026-10-25T09:08:05.161443+00:00): 本地Claude sessione7d022a7-2d91-45a4-8618-a2c318656942 ER05/H0/VERDICT PASS,P0/P1=0。root补真实未截断unified diff(3个hunk,仅局部runner及两负例;源hash不变),前滚两处治理旧状态/40计数为实际子字串73;6项P2逐名处置,完整最终输入仍须C执行准入。A1原计数STOP与恢复收据都保留,174实际例不重跑;.72未bump,无提交/push/tag/Release/C-D。LibraFIX02 A2全量进行中,Cargo发布门继续串行;17/116、0/26、17/142不变。
FIX13 A1原STOP保留、证据重新核定;自身审查待(2026-10-25T09:01:09.525409+00:00): 源码仅validate.rs cfg(test);nightlyfmt、严格Clippy、RED预期1PASS/1FAIL、GREEN2PASS、错名child零测试被父进程拒绝、两完整模块101+73=174PASS(原目标141与额外commands模块33),库2802及3原ignored身份不变。13命令预期退出、原计数STOP 917.614/3600秒,root后检1449.985秒;107个全部DB名称owner保存、零owned-live/新孤儿。自己的Claude ER05/H0及独立五门C/签名/发布D尚待,未bump/提交/push。FIX12/MTR102原C1 STOP不复位。Libra独立FIX02 A1因实测umask0002违既定0022已STOP:5994PASS/5FAIL/4762未跑,旧15focused/1live只是观察;环境恢复A2候选另审,不冒充通过。正式17/116、0/26、17/142及99→FIX13→FIX12→102→…→H1不变。以下旧时点快照保留。
恢复审查收据:本地Claude 076a6493-a599-474e-b968-13886b6d84e7 ER03/RECOVERY/H0/VERDICT PASS;原terminal FAIL不改,仅独立qualified-A收据认可原命令真实覆盖,没有重跑或新增窗口。
FIX13 A1计数守卫STOP与零重跑恢复候选(2026-10-25T08:55:00.165386+00:00): A1实际13命令均按预期退出,fmt/严格Clippy与RED/GREEN/错名负控符合预期,两完整模块分别101/73PASS;但执行器把原命令
config::tests::当prefix,仅预期40,实际Rust子字串另匹配commands::config::tests::33,因此末阶段计数守卫FAIL/STOP。917.614/3600秒,候选已还原,尚未接受A。root逐名核73恰等listing全部子字串匹配且含原40,107个DB名称owner不变、零owned-live/新孤儿;不重跑产品、不改测试过滤/断言、不重置A1。本轮只提证据核算更正与carry-forward、待真实Claude恢复/H0审核;ownER05/C-D未完成。LibraFIX02 A1环境STOP保留,A2恢复R2真实Claude四PASS并依独立资源收尾条件启动,不等于Libra验收通过。正式17/116、0/26、17/142及原依赖不变。
FIX13计划PASS、单文件实现候选(2026-10-25T08:17:31.965470+00:00): 本地Claude session0bf7b0d0-68ae-4170-b29a-d33ac362e3f6 ER03/H0/VERDICT PASS,root具名处置P2。旧FIX12失败.73两Cargo前像已保存并精确退出到.72,三测试候选/原C1 STOP与MTR102候选均保留。新独立clone仅validate.rs tests内两负例/局部runner候选,in-progress/空;未格式化/编译/新A/自己的ER05/C,未提交/push/tag/Release。A1控制实验及执行器待实审,Libra A进行期间不运行Mega Cargo。正式17/116、0/26、17/142不变;前沿99→FIX13→FIX12→102→…→H1。新clone签名key416E…是本次生成的新key,不倒记为既有发布key;C时核实际PGP/UID/DCO与tag冲突。以下历史原件保留。
FIX13独立G07恢复候选(2026-10-25T08:09:01.488404+00:00): FIX-MTR-13独立恢复计划待ER03/H0,pending/空;FIX12 A1/ownR2保存但C1 FAIL/STOP,blocked/locally-accepted;102 C1 STOP继续保留。新前沿99→FIX13→FIX12→102→103→11→…→12/H1→LTR10;正式17/116、0/26、17/142(活动17/115、0/25、17/140),外部资格1/3。 来源Claude5df82b11确认当前legacy OAuth测试env污染,时间交错快照缺口保留;不扩G13、不重置任何旧C窗口。新clone从实际published b7df/.72起步,只拟validate.rs测试模块内两负例/局部runner,不带FIX12或102候选。FIX12未发布.73须新计划PASS后保存前像并精确退出;FIX13完整自身C/D后再前滚FIX12、另审其A消费与新C窗口,102更后。Libra FIX02 A1已开始,完整15例及真实D1/R2一例PASS、唯一UUID16表零行/R2前缀空,全量仍待;第三方proc-macro-error2 futurewarning按用户排除。原Libra三治理仅本地LTR01承载,qualification分支不混入。以下日期快照保留。
FIX12独立C1失败/STOP、原候选保留(2026-10-25T07:57:20.283192+00:00): 机械0.42.73后的完整C1实际于2026-10-25T07:51:01.991381+00:00退出1,661.427/3600秒;fmt和严格Clippy通过,full-test退出101,仅库2798PASS/1FAIL/3原ignored,其余20targets与build/build-tests未执行。失败为
config::tests::server_identity_stability_credential_rotation_keeps_server_id在reload.validate读到已移除MEGA_OAUTH__CAMPSITE_API_DOMAIN,源码归属待真实审查,不先算根因已证。原件/tmp/fix-mtr12-C1-20261025/,terminal SHA256 25b3996925ef8873d0a0988e5d09b49485ef0faf22cbda71bd6b17cb1be12b72;未重试、未提交/push/tag/Release。FIX12 blocked/locally-accepted,仅保留A1与自身ER05/H0 R2 PASS,不等于C完成。root精确手工清理本次dead PID600133的28个新DB、全部原107库名称owner保留,无owned存活进程/新孤儿/spool,三服务稳定;失败收尾原件/tmp/fix-mtr12-C1-failure-20261025/。原MTR102 C1及更早STOP不变;独立Libra FIX02 A1已准入,待/按本机串行启动,不受本次Mega发布阻塞而暂停。正式17/115、0/26、联合17/141不变。下方既有PASS/FAIL按当时scope保留。
FIX12实际A1通过、自己的ER05待(2026-10-25T07:22:20.378613+00:00): 受审A1实际14阶段PASS:nightlyfmt、严格all-target/all-feature Clippy零warning/error;受控RED原network通过/环境探针按预期失败,修复GREEN同两例通过,错误exact的0-child成功被父测试按预期拒绝;最终未插桩三完整模块11/4/3共18例全部PASS,2802库listing及3原ignored逐名核定。root后检在原3600秒内1023.064秒完成,104原DB名称/owner保持、无owned存活进程、未手工清理;四变体fresh=false/产物hash及最终模块binary绑定核实,MTR102候选完整保留。FIX12 in-progress/locally-accepted,自己的本地Claude ER05和完整C/D待,版本仍.72、未提交/push/tag/Release;不是历史C1交错或C2数据库根因证明。Libra DOC PR636/main全部实际D成功,FIX02 helper实现候选但未验收;外部1/3、正式17/115与0/26、联合17/141不变。以下旧FAIL/STOP原样保留。
FIX12 A1执行审查R1 FAIL、未claim(2026-10-25T06:57:28.993059+00:00): 本地Claude session6748d1a5 EXECUTION FAIL/H0 PASS,唯一P1为环境指纹含易变工具调用ID且缺claim前验证;本轮排除具名会话传输字段,增加相同sourced-env preclaim验证。P2补ignored3逐名、实际候选binary绑定、退出后进程观察、中断先回收再恢复、恢复守卫决定PASS;保留内存输出/失败日志,proxy Drop避免双panic;尚未执行的实验barrier界限明确10秒,原2/5秒请求与20/30秒进程界限及A3600秒均不变。原R1输入/FAIL保留,执行R2待;新A尚未claim、未消耗验收尝试。FIX12与Libra FIX02均只有实现候选,未验收/提交/发布,17/115、0/26、17/141、外部1/3不变。
FIX12计划R3已采纳、实现候选与A1待审(2026-10-25T06:46:17.909186+00:00): 本地Claude sessiondd1fe5ec-53ef-4e79-86d3-4353bc4b6b72 ER03/H0/VERDICT PASS,R1/R2 FAIL完整保留;root逐项核60输入并具名处置P2。原102失败的本地.73机械bump已保存前像并精确退出到.72,三个候选源码/旧C1 STOP未变。独立clone FIX12三cfg(test)文件已实现候选、nightly格式化,尚未验收/自身ER05/C/提交/推送/发布;in-progress/空。A1一次3600秒的具体RED/GREEN/错误exact负控与三完整模块18例执行器待本地Claude,未claim。前沿99→FIX12→102→103→11→…→12/H1→LTR10;正式17/115、0/26、17/141、外部1/3不变。Libra main核心10761PASS/21原ignored/0retry/项目warning0;network D仍待,FIX02独立分支已取实际合并源,尚未实施。以下旧日期快照保留。
FIX12计划R2 FAIL后的R3候选(2026-10-25T06:36:23.586705+00:00): R2 session01150932实际ER03/H0 FAIL,唯一P1为里程碑M1/H1漏同步;本轮补齐FIX12完整C/D→102→103→11→…→H1并登记修订历史,R3待。R1其他P1已获R2确认修正。17/115、0/26、17/141、外部1/3不变;源码/版本退出/新验收/提交/推送均未执行,102 C1 STOP及旧失败保留。
FIX12计划R1 FAIL后的R2候选(2026-10-25T06:31:19.176954+00:00): 本地Claude session67966d1d实际ER03/H0 FAIL,阻断项为正文顺序/依赖/发布窗口与修订历史追溯未同步;本轮已前滚修订,R2待。新前沿99→FIX12→102→103→11→…→12/H1→LTR10,计数17/115、0/26、17/141,外部1/3不变。修复设计获R1认可不等于计划总PASS;尚未实现/验收/版本退出/提交/发布。102 C1 STOP与候选完整保留。以下历史不回改。
FIX-MTR-12独立恢复候选(2026-10-25T06:23:48.226590+00:00): FIX-MTR-12代理测试进程隔离为当前候选前沿,ER03/H0待本地Claude;未实施/验收/提交/发布。MTR102 blocked/locally-accepted:A2与自身R2保存,C1 FAIL/STOP,不授C2。 源审session a8cf92a6已确认两测试共享代理env污染缺陷,但C1历史交错仍未证明。拟从已发布b7df855d/0.42.72独立native clone修复,只以Command启动环境传代理、保留原断言/timeout;不带102候选代码。原102 .73仅本地未发布,受审后保存前像并只退出自己的机械bump。新DAG:99→FIX12→102→103→11→40→13→39→92→12/H1→LTR10→11→12→LTR01/H2。正式Mega17/115、Libra0/26、联合17/141(活动17/114、0/25、17/139),外部资格1/3;新增一张独立FIX不改旧失败/预算/STOP。Libra DOC PR636已合并b73e98a,main Clippy/Rustdoc实际项目warning=0,base其余D待;FIX02/03与原merge政策/H1仍待。Libra三治理只本地由LTR01覆盖。以下带日期内容为历史。
MTR102 C1真实STOP与只读归属(2026-10-25T06:09:53.994636+00:00): MTR102 C1实际FAIL/STOP,blocked/locally-accepted(仅保存A2及自身Claude结论);0.42.73仅本地bump,未提交/push/tag/Release。fmt/strict Clippy通过,full lib2807PASS/1FAIL/3原ignored,后续20targets及双build未执行。失败是raw-fetch测试fixture首次put_raw的GET运输出错,根因尚未证明;不自动重跑C、不增加超时或减覆盖。 原terminal SHA256 d4bd911237aed2d4390591895933f3802ba5c56cf90752456e22c0f20c61de0e;执行647.571/3600秒后失败。root核source/tool/review终态无漂移、无owned/新孤儿/spool,RustFS实例稳定且raw前缀0;26个本轮零连接DB逐名绑定已退出PID4078417后人工清理,原104个名称/owner保持,不宣称自动回收或历史C2根因。两处测试全局代理环境修改与默认HTTP client读取是待验证并发污染线索,不是已证历史因果。仅只读源码/原件审计及恢复设计可继续,受控实验或新C须先具名审定。自己的Claude最终R2 session4f679d9e-fe60-4e52-bff2-da736cd1cb97 ER05/H0/EXECUTION PASS不能覆盖本次失败。Mega17/114、Libra0/26、联合17/140、外部1/3不变;MTR103/11及H1仍待。Libra PR636合入b73e98a、main D仍待,原三治理仍只本地LTR01承载。以下旧日期快照保留。
MTR102自身Claude R1通过、最终治理与C合同R2待(2026-10-25T05:43:17.171586+00:00): A2实际37例/资源后检通过;自身R1 session8a6087eb-543a-4a5a-8f1a-5bd6d37d64c3 ER05/H0/VERDICT PASS,无P0/P1。root具名接受NoSubscriber每次构建Dispatch造成全局interest重建的P2性能风险:当前无公开transport;MTR11开工必须评估Dispatch::none(),任何修正先核合法I/粒度与真实验收,不提前声称修复;两项并发/created_at测试覆盖限制如实保留。源码/A2字节不变,本轮仅9治理记录,R2与C准入待;未bump/提交/push,102仍in-progress/locally-accepted。Libra DOC PR636已由gh合并b73e98a77ecc7c3db1ea905ab55478785d76c041,13PR检查全绿、10761selected PASS/21原skipped/零retry,Clippy/Rustdoc/core项目warning=0;main D及FIX03覆盖仍待,不增版本。FIX01 done/complete、外部1/3;正式17/114、0/26、17/140与前沿102→103→11→…→12/H1保持。以下日期快照保留。
MTR102实际A2通过与自身Review前沿(2026-10-25T05:36:56.619767+00:00): MTR99 done/complete(b7df855d/v0.42.72);MTR102 A2实际37例通过、in-progress/locally-accepted,自己的Claude ER05/H0及完整C/D待。原A1与A2 R1 FAIL/STOP保留。Mega17/114、Libra0/26、联合17/140(活动17/113、0/25、17/138);外部资格1/3:FIX-LTR01 main/release D实际全绿并done/complete;DOC PR636/main与FIX02/03仍待。前沿102→103→11→40→13→39→92→12/H1→LTR10→11→12→LTR01/H2;H1与原merge政策未闭合。 三完整模块4/18/15、fmt/strict Clippy/listing全部通过;root后检1337.390/1800秒,在原05:44:30.433733Z截止内,104原DB名称/owner保持、无owned/新孤儿、未手工清理;工具/config/source均核。源码3文件/7AC/3VER不变,0.42.72未bump/提交/push;本次治理字节尚待自身H0,非已通过的A输入。Libra三文档只本地、由LTR01覆盖。以下日期快照保留历史。
MTR102 A1实际FAIL/STOP与有界A2候选(2026-10-25T05:26:43.466526+00:00): 102三文件源码候选及新增8例已写;A1 fmt PASS、strict Clippy exit101(测试helper缺StorageConnector import),A1时36例尚未执行;无残留worker、104原DB保持、未手工清理。A2 R1真实FAIL(时间戳/工具现核);R2补正确时间、claim/逐阶段工具与Cargo配置hash守卫及180秒后检余量。另源核SeaORM debug-print会展开首次认证token bind,本卡敏感查询以scoped NoSubscriber隔离,新增真实日志控制对照;3文件/7AC/3VER不变,37例待跑。原A1起点2026-10-25T05:14:30.433733Z、总1800秒/绝对截止05:44:30.433733Z不重置;提议一次A2重跑原6阶段,诊断/修文/Claude审查/后检全部扣原窗口,须真实本地Claude ER03/H0/执行合同PASS后才claim。原FAIL/STOP保留,本次不是自己的最终源码ER05、C或发布PASS;不提交/push/bump。正式17/114、0/26、17/140;103/11仍待逐卡开工,H1不提前。
MTR11开工发现与G09修订候选(2026-10-25T04:57:04.668267+00:00,真实本地Claude ER03/H0待): MTR99已done/complete(b7df855d/v0.42.72,完整C与main/tag D实际success)。源码审查session b3f3d07d的SOURCE_REVIEW PASS/总VERDICT FAIL及5项P1保留;拟拆MTR102可信Mono凭据→MTR103绑定管理→MTR11 HTTP。新总数Mega114/Libra26/联合140(活动113/25/138),正式完成仍17/0/17,外部资格0/3。102/103/11尚未实施或验收;本候选经本地Claude单审明确PASS前不启动实现。H1仍为12,后续11→40→13→39→92→12/H1→LTR10→11→12→LTR01/H2不变。Libra DOC-LTR-01已signed 5c449bba推分支/PR636,A/B及自身Claude PASS、PR Clippy/Rustdoc项目warning=0;PR/main门与FIX03覆盖仍待。FIX01合入f33be958/v0.30.87,main全量D尚未终态;原Libra三治理文件仅本地由LTR01覆盖。旧失败、STOP、缺失原件、取消项和原merge签名政策不改。
MTR99实际收口与当前执行前沿(2026-10-25 04:29:22 UTC): MTR99 done/complete:0.42.72源码/A1/自身Claude R2/五门C/签名提交b7df855/main/tag/人工Release及实际D全通过;MTR11待ER01/02/03,尚未实施。Mega17/112、Libra0/26、联合17/138、外部资格0/3;H1与Libra资格/原merge政策仍待。 MTR99五门C实际21 targets/3107 PASS/0 FAIL/3原ignored,local C含postchecks2582.007/3600秒;原资源观察器对并发拼接port行FAIL保留,受审保守superset只读恢复通过。25个本次owned测试DB经精确授权人工删除、原104DB保留,此为测试环境收尾,不是自动回收修复或历史C2根因证明。main Harbor40160748002及tag Docker40160777703的amd64/arm64/manifest四job全部success,D终态2026-10-25 04:26:13 UTC;实际head b7df855d2ca6fb945774b5dd397884ad82b46c31、annotated v0.42.72、人工Release均核。 Libra独立资格clone的DOC-LTR-01已通过A/B,自己的本地Claude审查进行中、尚未提交;FIX01 PR635已合并f33be958/v0.30.87,release与CodeQL成功、main base待。原Libra三治理文档仍只本地、由LTR01覆盖,不混入用户指定下一笔warning提交。以下日期快照保留历史。
MTR99自身R1源审PASS/H0 FAIL与前滚修订(2026-10-25T02:50:50.524869+00:00): MTR101 done/complete:v0.42.71完整C/D;MTR99 A1实际61例通过、自己的R1源码ER05/内存PASS,但H0四处索引P1导致总FAIL;索引已前滚、R2待审,未bump/提交/push/C-D。正式Mega16/112、Libra0/26、联合16/138、外部0/3;Libra资格/H1/原merge政策待。 原R1精确1016输入与FAIL完整保留;A1源码字节不变、不重跑已通过的61例。五项P2具名登记,原FAIL/STOP与缺失证据保持。
MTR99实际A1通过、自己的源码审查待(2026-10-25T02:39:53.809601+00:00): MTR99五文件实现已通过A1:nightlyfmt/严格Clippy、原selector4/3/4及七完整模块7/13/5/6/9/7/14,共61唯一用例0fail/0ignore;root后检496/1800秒,104个DB名称/owner保持、无owned进程/私有spool、RustFS raw前缀仍0,未手工清理。自己的Claude ER05/H0及完整C/D待,0.42.71不变,未提交/push/tag/Release。正式Mega16/112、Libra0/26、联合16/138、外部0/3保持;101已done/complete,Libra PR635 fontconfig及资格02/03、H1/原merge政策仍待。旧FAIL/STOP与缺失原件不改。
MTR99开工已准入、源码实施候选(2026-10-25T02:06:58.385961+00:00): 本地Claude R2实际五项PASS(session0b34282e,终态01:56:01 UTC),root重算54输入无漂移、保存原件并具名处置5项P2;R1 FAIL/STOP与缺失证据保持。MTR99已开始五文件I内实现及真实后端测试候选,尚未执行A/自己的源码ER05/C/D,不勾AC/VER、不bump/提交/push。MTR101 v0.42.71完整C/D已闭合。正式Mega16/112、Libra0/26、联合16/138、外部0/3保持;Libra PR635远端fontconfig阻塞与资格02/03、H1及原merge签名政策未关闭。
MTR101实际C/D闭合与MTR99 R2候选(2026-10-25 01:50:01 UTC): MTR101 done/complete:0.42.71源码/A4/自身Claude/五门C/签名提交6a63504/main/tag/人工Release及实际D全通过;MTR99 R1三P1 FAIL保留,R2候选待本地Claude,未实施。Mega16/112、Libra0/26、联合16/138、外部0/3;H1与Libra资格/原merge政策仍待。 main40150856672及tag40150892586全部四job success,终态01:43:34 UTC。Libra原三已审文档signed+DCO本地7541e9b已核,未push;PR635仍未合并/tag/Release,compat-clippy缺fontconfig。旧FAIL/STOP与缺失原件均保留;下方带日期旧前沿为历史。
MTR101已发布、MTR99开工修订候选(2026-10-25 01:36:27 UTC): MTR101自己的Claude R2 ER05/H0 PASS;0.42.71五门C实际21 targets/3096 passed/0 failed/3原ignored/0 filtered,root资源后检2596/2700秒。signed+DCO
6a635042a40bb4d013c56c8655d9a42558150c83、main、标注v0.42.71及人工Release实核;main40150856672/tag40150892586正在执行,in-progress/remote-pending。MTR99仅候选:解耦raw读取/parser控制与push时钟,拟5生产文件/3落点/M,8AC/3VER与independent patch/self保持,须本地Claude ER03/H0及101 D成功后实施。Libra PR635未合并/tag/Release,compat-clippy缺fontconfig.pc,资格02/03与H1/原merge政策待。正式Mega15/112、Libra0/26、联合15/138、外部0/3不变;历史FAIL/STOP与缺失原件保留。
MTR101 A4验收与最终源码审查前沿(2026-10-25T00:34:41.026023+00:00): MTR101 A4实际PASS:fmt/严格Clippy、selector6/4/1及四完整模块7/9/16/10全通过,42唯一用例、0failed/0ignored;212.117/900秒,root后检确认输入/工具/104个DB名称与owner不变、无新孤儿、未手工清理。新覆盖已兑现,最终候选自身Claude ER05 R2待;0.42.70不变,未bump/提交/push/C-D。Libra PR635已推但CI缺fontconfig未闭合,未合并/tag/Release;资格02/03与H1前驱不变。 原A1/A2 FAIL/STOP、A3/R1限定输入PASS保留;正式Mega15/112、Libra0/26、联合15/138、外部0/3不变。
MTR101 覆盖方案采纳与实现候选(2026-10-25 00:20:32 UTC): 本地Claude ER03/H0实际PASS,无P0/P1;仅两现有cfg(test)模块补齐候选,生产字节不变。新增storage第二页缺失/异tree拒绝及全匹配正对照,保留At并补Absent/首发无副作用、原checkpoint同一行的真实增量发布,原断言与空tree stale-binding覆盖保持。A4预期42例、一次900秒执行准入待,尚未编译/测试;自己的新ER05与C/D仍待。A3/R1 PASS和旧FAIL/STOP均保留;Libra PR635 CI缺件未闭合,正式计数不变。
MTR101 自身审查与覆盖补齐候选(2026-10-25 00:12:22 UTC): MTR101当前源码自身Claude ER05/H0已PASS、A3实际41例通过;root决定在C前关闭P2-1/2覆盖缺口与P2-6正文滞后。仅两个现有cfg(test)模块拟补断言/一个case,生产源码不改;A4一次900秒方案待ER03/H0审查,尚未实施/claim。0.42.70不变,未提交/push/C-D。Libra PR635 clippy缺fontconfig失败,未合并/tag/Release;其余资格和H1前驱不变。 原A3 PASS、A1/A2 FAIL/STOP及预算全部保留;正式15/112、0/26、联合15/138、外部0/3不变。
MTR101 实际A3与自身代码审查前沿(2026-10-24 23:59:09 UTC): 2026-10-24 23:59:09 UTC:MTR101 A3实际PASS,完整模块7/9/15/10共41例、0fail/0ignore;fmt/严格Clippy通过,32.954/900秒。root核输入/工具/DB/进程无漂移或残留,原A1/A2 FAIL/STOP不改;源码及A/B完成候选,自己的本地Claude代码ER05待,未bump/提交/push/C-D。Libra FIX-LTR01已signed2852497推功能分支PR635,远端clippy缺fontconfig.pc失败,未合并/tag/Release;资格02/03与H1仍待。 正式Mega15/112、Libra0/26、联合15/138、外部0/3不变;以下旧时点均为历史。
当前恢复与跨仓前沿(2026-10-24 23:51:00 UTC): 2026-10-24 23:51:00 UTC:MTR101 A2实际FAIL/STOP;三组selector6/3/1已PASS,外部阶段名校验在首个完整模块Cargo启动前失败,四完整模块均未执行。A3恢复候选一次900秒、ER03/H0/执行准入待本地Claude;源码不变,8AC/4VER未勾。Libra FIX-LTR-01本地C受限接受、自己的Claude PASS,signed/DCO提交2852497已推功能分支并建PR635;远端clippy缺fontconfig.pc失败,未合并/tag/Release。 原A1/A2预算与FAIL/STOP全部保留;旧时点为历史。正式Mega15/112、Libra0/26、联合15/138、外部0/3不变。
MTR101 A2准入修订(2026-10-24 22:10:09 UTC): R1实际EXECUTION FAIL/H0 PASS;执行器串行前置P1已修成R2候选,待本地Claude复审,尚未claim/测试。原A1 FAIL/STOP、源码恢复ER03/H0 PASS与一行夹具修复保留。Libra FIX-LTR-01已bump0.30.87并运行独立C,尚未提交/推送/发布;不与A2并跑测试。下方旧时点保留。
MTR101恢复方案实际通过(2026-10-24 22:01:36 UTC): 本地Claude ER03/H0 PASS,P0/P1无;root采纳受审的一行cfg(test)键隔离修复,8AC/4VER未勾,in-progress/空。A1 FAIL/STOP保留;A2一次1800秒最终执行准入待,尚未运行。原功能链/计数与C/D边界不变;下方候选及旧状态为历史。
MTR101恢复候选与Libra并行前沿(2026-10-24 21:56:54 UTC): 2026-10-24 21:56:54 UTC:MTR101 A1实际FAIL/STOP,chain6/6、publication0/3,resources及四完整模块未运行;原8AC/4VER未勾。仅测试fixture冪等键隔离的ER03/H0恢复候选待本地Claude,A2一次1800秒未准入/未执行,旧A1不重置。FIX-LTR-01源码/A/自身Claude ER05已PASS,C准入待、无提交/push/发布;外部0/3。FIX11已done/complete;Mega15/112、Libra0/26、联合15/138。 当前功能链仍101→99→11→40→13→39→92→12/H1→LTR10→11→12→LTR01;LTR10仍需H0/H1/WRITERS/LIVE及DEP-TR-QUAL-REPAIRS,原merge签名政策未关闭。以下旧时点事实保留。
FIX10代码审查R1事实与文档订正(2026-10-24,最终输入R2待): 本地Claude session
235da2d1-f225-4c03-a85c-e84971911a44,exit0,ER05/H0/最终VERDICT均PASS,无P0/P1;输出SHA256a5380d528ff218fe57c31644581059fd5ad0c172611ad65ce5426610ba1ede2a。root选择在发布前关闭P2-A~C:订正陈旧RED/GREEN待执行文字,恢复误插FIX10的历史快照原文并保留当前依赖边,对齐Granularity写集措辞;上述变更另行R2审查,源码及A1输入不变,不冒用R1覆盖改后文档。root具名接受P2-D:头长度解析允许前导+但最终原解析器拒绝,至多回原EOF路径;P2-E:缺权限由未改exec入口先拒绝,现有完整SSH进程目标在最终C实跑,早处理不绕过此入口。无新scope/waiver。C/版本/提交/推送/D均未执行。
FIX10本地A/B结果(2026-10-24,代码ER05待): 独立clone单生产文件SSH修复候选完成;旧源handler RED1PASS/4FAIL、真实Docker Git RED0PASS/2FAIL(原90秒期限)已保存。相同新测试GREEN5/5、真实Git2/2、完整SSH模块34/34,0failed/0ignored;nightly fmt、strict all-targets/all-features clippy、release build均exit0。原19项HTTP/SSH/PUSH/LFS smoke 19PASS/0FAIL/0skip,HTTP OpenAPI200/3.1.0/96paths、SSH就绪实测;自有服务exit0、DB/Redis键/容器/目录均清理,无source/runner漂移。A1 terminal SHA256
bdfd4f90cb34791337ab0dbb84d9eaeae9c70c19db6fa050b304f2ec97b6f330,原件/tmp/fix-mtr10-A1-20261024/;smoke log SHA256addaaa247a9809959889bd54deb08267e79c48c195f0e0372afd5a166624a59b,原件/tmp/fix-mtr10-entry-20261024/。原始A/B不替代最终C:本卡尚无代码ER05、版本bump、签名提交、推送、tag/Release或D。原FIX07候选仍冻结/blocked,未随本卡发布。两仓当前完成数仍11/0/11,Libra不push。
FIX10实现候选(验收进行中,尚未发布): SSH receive-pack按pkt-line边界保存命令扫描进度;完整非空命令段以flush结束且无PACK、既有解析器确认全部为删除时,立即进入原receive-pack处理并发送report-status、exit-status、EOF/close。完成标记阻止重复data/EOF再次执行事务或产生missing-flush错误;非删除、混合、畸形或不完整请求仍沿原EOF路径处理,PACK数据不被反复扫描/复制。所有exec鉴权、只读/禁用守卫及main/tags/CAS规则沿用原路径。旧源真实handler RED为1PASS/4FAIL、真实Docker Git RED为0PASS/2FAIL(原90秒期限),根因链已受控复现;GREEN5/5、真实Git2/2、完整SSH34/34及19smoke已过;代码ER05与最终C/D尚待,不能据此记发布成功。
FIX10计划采纳事实(2026-10-24): 本地Claude R2 session
9057479b-c960-44fc-ad17-5f38715acd2f、exit0,ER03/H0及最终VERDICT: PASS;输出SHA2567caa7cc57c97dadf32a5dec7c1499ea80f33405841c209143b3743bf9a2fb6b5,manifest SHA25648fe01cd13f5f2d2545c9c637bdc36b8b7cfc09a67af4e197b67efcaf93f7fad,九文件SHA守卫应用成功,仅Mega独立发布clone六文件及Libra三文件。原Mega11个FIX07候选完全冻结。R1两个P1已关闭,R1真实FAIL原件/摘要保留于/tmp/fix-mtr10-entry-20261024/review-terminal.json;本PASS只准入计划,不是代码ER05/C-D。root负责R2 P2-1~4本批事实同步(待代码ER05核)、P2-5未来整合候选证明原生stash/ff-only行为、P2-6本登记。新测试先运行旧源RED;源码实现、全部A/Review/C-D/提交/推送仍待。
FIX-MTR-10 计划已采纳(R2 PASS;测试先行,源码修复待): 现有普通Git SSH receive-pack只在EOF分派,真实delete-only客户端可能先等待report-status而不发EOF。拟在完整合法且无需PACK的命令flush后执行原鉴权/引用处理并回报,防止重复执行;普通PACK及Traces禁用/只读边界保持。来源和验收见当前计划,不把候选写成已发布行为。
本文档记录 mega2 当前 Git SSH/HTTP 协议实现的现状分析、主要兼容性问题、风险点和分阶段改进计划,用于提升与标准 Git 客户端的兼容性。
治理规范:本文档遵循
../general.md中定义的统一结构、共同约束和执行标准。在审阅或执行本计划前,请先查阅 general.md 了解共同需求。
与其他模块的依赖:Git Protocol 改进与 config/vault 的认证统一相关。当 config.md 阶段 2(CLI LoadMode)完成后,可统一 HTTP/SSH 的认证上下文设计。集成测试参见
integration.md。
用户可见规则:Monorepo 仅公开
main,Git 客户端不能推送 Tag;路径例外和推送行为见使用指南。本文负责记录 Git 协议行为与 smoke 矩阵。
本文档中的代码引用已对照当前
src/重新核对。当前 Git protocol 实现处于基础阶段,具有完整的功能框架但多处缺乏错误处理和兼容性完善:2026-06-23 更新:已完成首批 malformed input panic 止血:
- HTTP
info/refs的 query 反序列化错误以及service参数缺失或非法时,不再unwrap()panic,而是返回ProtocolError::InvalidInput。- smart protocol pkt-line 读取新增
try_read_pkt_line,对非十六进制 header、短 header、长度小于 header、payload 不完整等输入返回ProtocolError::InvalidInput,并补单元测试;upload-pack 与 receive-pack 命令解析已改用该可失败 parser。- upload-pack 的
want/haveobject id 长度和 UTF-8 解析已改为协议错误;receive-pack 命令解析会传播 pkt-line/capability 解析错误。SSH receive-pack 遇到非法 command pkt-line 时记录告警并返回 error 文本,不再在该点 panic。2026-06-23 更新 2:已完成 SSH exec parser 止血:
exec_request不再用split(' ')和command[1]直接索引;新增独立 parser,支持单引号、双引号、反斜杠转义和包含空格的 repo path。- 只允许
git-upload-pack、git-receive-pack、git-lfs-authenticate、git-lfs-transfer;未知命令、缺 path、引号未闭合或参数数目错误会返回 channel failure 和可读错误,不再默认降级为 upload-pack。- repo path 只去除末尾
.git,不再删除路径中间的.git。2026-06-23 更新 3:已完成 receive-pack
PACKmagic 分界止血:
- HTTP / SSH receive-pack 不再搜索
PACK字节序列,而是复用SmartSession::split_receive_pack_request按 pkt-line command list 的 flush-pkt 分割 commands 与 pack bytes。- 新增单元测试覆盖 capability 中出现
PACK不误切分,以及缺少 flush-pkt 返回ProtocolError::InvalidInput。- 当前实现仍是完整 body / channel 数据缓冲后再 split;更完整的 streaming pkt-line reader 仍为后续,delete-only push 语义与空命令列表校验已加固。
- 2026-06-28 更新:SSH per-channel state 已实现。
SshServer不再维护连接级smart_protocol/data_combined,而是按ChannelId维护独立的GitSshChannelState,每个 channel 拥有独立的SmartSession与 receive-pack 缓冲区。capability advertise已完成首批保守收敛,后续仍需完整 truth table 覆盖。2026-06-23 更新 4:SSH upload-pack 初始响应已删除
String::from_utf8(...).unwrap(),改为直接按 bytes 写回 channel;Git 协议 payload 不再在该路径上被 UTF-8 假设约束。2026-06-23 更新 5:HTTP upload-pack request body 聚合不再对 body stream 错误
unwrap(),已与 receive-pack 统一经ProtocolError::InvalidInput返回。2026-06-23 更新 6:HTTP
info/refsquery 已按 smart HTTP 规范收紧为 exactly oneservice=...参数,额外参数和重复service均返回ProtocolError::InvalidInput。2026-06-24 更新:SSH
git-lfs-transferpure SSH 路径已从普通占位文本not implemented yet改为通过 SSH stderr extended-data 返回明确 unsupported 错误,并继续返回 channel failure,明确声明不支持 pure SSH LFS transfer、引导客户端使用git-lfs-authenticate的 HTTP fallback。2026-06-24 更新 2:SSH LFS exec parser 已收紧
git-lfs-authenticate/git-lfs-transfer参数语义,operation 从 optional 改为必填且仅允许upload/download;缺失或未知 operation 返回 channel failure,不再接受模糊请求。2026-06-24 更新 3:SSH
git-lfs-authenticate响应序列化已移除serde_json::to_vec(...).unwrap(),改为错误传播;成功写回 hybrid LFS JSON response 后显式发送 channel success。2026-06-24 更新 4:capability truth table 阶段 3 收尾——为
side-band-64k补充build_side_band_format专用单测(含启用/未启用两条路径);为ofs-delta补充 advertise/parse 单测并明确其 OFS_DELTA pack 编解码由git-internalcrate 实现(internal/pack/decode.rs处理 offset delta),mega2 侧仅覆盖 advertise/parse;对 SHA-1 object format 落地显式策略——协议允许 SHA-1 默认时省略object-format,mega2 策略是对 SHA-1-only repo 不 advertiseobject-format,由advertised_capabilities_keep_sha1_default_and_do_not_advertise_object_format锁定。2026-06-24 更新 5:阶段 4 认证上下文统一收口(工作项 1/2/3/6)。新增
SmartSession::set_authenticated_user;SSHauth_publickey成功后将 key owner username 存入SshServer.authenticated_user,exec 阶段注入SmartSession.auth;HTTP receive-pack 改用同一 helper。SSH push 的 commit binding 不再匿名。残余:upload-pack 匿名策略、receive-pack repo/path 级 push 权限(工作项 4/5)。2026-06-24 更新 6:阶段 2 delete-only push 落地(工作项 4)。新增
SmartSession::is_delete_only_push;git_receive_pack_stream检测到全 delete command list 时跳过unpack_stream/receiver_handler,unpack_result视为 Ok,直接处理 ref 删除并返回 report-status。由is_delete_only_push_detects_pure_delete_vs_mixed锁定。2026-06-30 更新:LFS lock / metadata storage 路径完成 panic 止血。
LfsDbStorage的 object/lock CRUD 不再 unwrap SeaORM 结果,而是返回MegaError;ceres::lfs::handler的 lock list/create/delete 路径不再 unwrap lock JSON、limit parse 或 DB 结果,统一映射为GitLFSError。Link::new的 86400 秒过期时间也改为 infallible chrono 构造。2026-06-30 更新 2:LFS router response/body 路径完成 panic 止血。
api::router::lfs_router不再通过Response::builder().body(...).unwrap()构造静态 LFS JSON/stream responses,改为Response::new+ 静态 header;upload object request body 聚合错误也从unwrap()改为 400 错误返回。2026-06-30 更新 3:pack traversal count helper 完成首批 panic 止血。
RepoHandler::traverse_for_count与traverse_trees_only_for_count不再 unwrap tree lookup 结果,改为返回Result<(), MegaError>并由 monorepo/import pack 生成路径向上传播错误。2026-06-30 更新 4:pack traversal entry send 完成首批 panic 止血。
RepoHandler::traverse与traverse_trees_only不再 unwrap pack encoder channel send 结果,blob/tree entry send failure 会作为 storage/protocol error 向上传播。2026-06-30 更新 5:monorepo pack generation 的 encoder startup 与 commit entry send 完成 panic 止血。
Monorepo::{shallow_pack, filtered_pack, incremental_pack}不再 unwrapPackEncoder::encode_async或 commit entry channel send failure,统一映射为MegaError/GitError向上传播。2026-07-01 更新 2:
try_read_pkt_line的 pkt-line parser 错误模型继续收敛。新增回归测试覆盖 reserved length0003、length 小于 header(如0002want)的精确错误诊断与不消费输入行为,以及非十六进制 header、短 header、payload 不完整的既有测试;由try_read_pkt_line_rejects_reserved_length_3、try_read_pkt_line_rejects_length_smaller_than_header、try_read_pkt_line_rejects_non_hex_header、try_read_pkt_line_rejects_incomplete_header_without_consuming、try_read_pkt_line_rejects_incomplete_payload共同锁定。2026-07-01 更新 3:真实 Git CLI CI 矩阵确认覆盖 HTTP 只读路径(ls-remote、clone、fetch、protocol v2 fetch/ls-remote、shallow clone、blob:none partial clone)。2026-07-01 更新 4:HTTP CL push(客户端
HEAD:refs/heads/<name>→ 服务端refs/cl/*,不新增公开分支)已进入 CI 必跑 gate;workflow 在 smoke DB 中生成并 mask 一次性access_token,通过 Basic Auth URL 运行scripts/git_protocol_smoke.sh的MEGA2_GIT_SMOKE_PUSH=1分支。为支持该路径,monorepo receive-pack 会在 old-id 为零但新提交带 parent 时以首个 parent 作为 CL base;孤儿提交初始化仍拒绝。2026-08-03 更新:Monorepo 公开分支仅
main;Monorepo::update_refs拒绝 Git 客户端创建、更新和删除 Tag(Tag 通过 HTTP API 管理)。smoke 将原「push and delete tag」改为 reject Git-client tag push,并将 branch smoke 改名为 CL push,断言refs/heads/*集合不变。2026-08-29 更新:Monorepo receive-pack 放开多 commit 链式 push(plan-20260827 MC-06,唯一用户可见行为变化):单次 push 允许 2..=250 个 commit 的线性链(上限为 CL 累计范围口径,ADR-MC-07),新分支 push 的 CL base 按 pack 成员关系沿首父链反走到 fork point(取代单 commit 时代的「取 tip 首个 parent」近似);含 merge commit 的链、断链/环、tip 与 ref 更新目标不符、累计超限,一律在 finalize 写 ref/CL 之前 fail-closed(MC-03 校验器正式接通主路径);单次 receive-pack 多于一条非删除 branch 命令时整体拒绝并引导分次 push(ADR-MC-04 收紧生效,删除命令不受影响)。unpack 不再拒绝第二个 commit entry,也不再要求 pack commit 等于
new_id(改由 finalize 的「pack 必须携带 ref 更新目标」检查等价兜底)。端到端由tests/integration_git_cli.rs的multicommit用例族锁定;trunk merge 语义不变(ADR-MC-01)。2026-08-29 更新 2(MC-06 评审硬化):fork point 反走只沿「本 push 新引入」的 commit 前进(unpack 时已存在于服务端的祖先即便被 pack 冗余携带也不构成链),反走与校验共享 250 上界;校验器增量段改为内存校验(复用 resolve 的反走结果,不再重复读库),历史段仍仅计数;commit 绑定从 unpack 阶段后移到 finalize 成功之后且仅覆盖已接受链——被拒 push 不再 upsert
commit_auths;混合「删除 + 单条更新」的 receive-pack 明确放行(ADR-MC-04 的删除豁免由 e2e 锁定)。2026-09-12 更新(plan-20260901 FC-08):receive-pack 对齐 Mega 的 per-command report-status:pack-less 非删除命令校验已存 object;monorepo tag 与
refs/heads/main删除在持久化前ng;多余非删除 branch 标ng而第一条仍可 finalize(不再整包拒绝);tag-only 不finalize_receive_pack。CL delete-only 保持允许。2026-09-12 更新(plan-20260901 FC-09):ref 删除按客户端 advertised
old_id做 compare-and-swap;不匹配时不删除已被并发更新的 ref,report-status 为moved since advertisement。默认分支删除仍由 FC-08 前置规则拒绝。2026-09-12 更新(plan-20260901 FC-10):import/monorepo filepath 写入改为收集
(blob_id, path)后按 repo/domain 一次 CASE UPDATE(empty 为 no-op,duplicate 保留最后一次 path)。成功导入的路径语义不变。2026-08-29 更新 3(MC-06 R2 粘性收口):拒绝规则改为只基于 pack 内容(presence 集)——resolve 沿 tip 首父路径做 presence 界定的走查(新引入成员走 250 语义上界,冗余携带的已知祖先走独立卫生上界),凡不在路径上的 pack commit 一律判 junk 拒绝,与瞬时 newness 无关;无新引入的 push 不再退化为
[tip]链,而是把整段内容链交给校验器重验。净效果:同一被拒 pack 原样重试必被同样拒绝(junk / 链中 merge / 超长 / 累计超限全部粘性),且 ref/CL/commit_auths零变化;已接受 push 的幂等重试在真实客户端下天然走空 pack no-op 分支不受影响。绑定消费收窄为ordered ∩ 新引入。
2026-07-01 更新 5:LFS opt-in smoke 已对齐 monorepo push 语义。
lfs_smoke_http不再从孤儿仓库初始化并推送不可接受的 root commit,而是先 clone 远端默认分支、创建普通子提交、用 non-delta pack 推送,再通过refs/cl/*差异定位 mega2 实际创建的 CL ref;clone/fetch/LFS pull 与清理都针对该 CL ref 执行。2026-07-01 更新 6:CI workflow 现在安装git-lfs并默认启用MEGA2_GIT_SMOKE_LFS=1,LFS push/clone/pull/locks-list round-trip 进入Git Protocol Smoke必跑 gate。2026-07-01 更新 7:首轮 LFS CI gate 暴露 Git LFS 对 monorepo 根路径 remote
http://host/的默认 discovery 派生问题:客户端会拼出http://host.git/info/lfs并导致端口解析失败。lfs_smoke_http现在对源仓库和验证 clone 显式配置lfs.url=<remote>/info/lfs,并关闭 locks verify 探测,避免根路径 URL 被 Git LFS 自动追加.git。2026-07-01 更新 8:第二轮 LFS CI gate 暴露普通
git clone在临时 LFS push 后会先拉取 remote 全量 refs,并可在 upload-pack 阶段因临时 CL ref 状态返回 HTTP 400。lfs_smoke_http的验证端现在改为空仓库git init,只 fetch 本次创建的refs/cl/*到本地lfs-smoke分支,再执行 checkout、git lfs pull和 locks-list;CI 验证聚焦在目标 CL ref 的 LFS round-trip,不再依赖全量 clone。
2026-09-09 更新(TP-17 / ADR-TP-18):monorepo
finalize_receive_pack按[monorepo].push_policy条件化。review仍走persist_mono_branch_cl_mega_refs_transaction+ CL post-push 管线(写refs/cl/*)。trunk跳过 CL 落地,以kind=push入队并执行 B3:N=1 客户端 commit 原样落main@P,N>1 squash(sideband 返回合成 id 与对齐命令git fetch && git reset --hard origin/main);删除类 branch 命令在 finalize 以 B0 正文拒绝。trunk 形态refs_with_head_hash过滤is_cl行(档案 CL refs 不 advertise)。push_queue.requester取协议身份(token 名 /none为 NULL),不用 commit author。
2026-09-10 更新(plan-20260908 SP-01): storage-only SSH 读与 HTTP 共用
anonymous_access:仅push_auth.is_some() && anonymous_access=true时auth_noneAccept。review 即使匿名开也不 Acceptauth_none(保护公钥推送)。storage-onlyauth_publickey早拒。进程 IT:integration_git_ssh_trunk_none_anon_on_clone、integration_git_ssh_trunk_none_anon_off_clone_fail、integration_git_ssh_trunk_token_anon_on_clone。2026-09-16 更新(plan-20260912 / WH-05):storage-only LFS basic 上传在本次请求实际
put_stream成功后发一次lfs.object.uploaded出站事件(仅 oid/size/transfer="basic"元数据,scope 三个值全 null,只发给include_unscoped_lfs=true的静态 target;契约见storage-events.md)。明确不发的路径:batch 建行、exists 命中 no-op、hash/size 校验失败、presigned 直传(对象存储signed_url绕过本机 upload handler,无完成回调,覆盖缺口登记为 DEFER-WH-01)。exists→put 非原子,并发上传可重复通知,不承诺首次写 exactly-once。进程 IT:integration_git_lfs_storage_events_basic_upload(basic 一发)/integration_git_lfs_storage_events_presigned_gap(RustFS 直传零事件)。2026-09-12 更新(plan-20260907 B3-04):
monorepo.object_format为sha256/blake3时,normal Git service 会 advertiseobject-format={kind},pack 编解码走*_with_hash_kind。这是 git-internal / Libra extension,不是 标准 Git BLAKE3 互通(永久非目标,DEFER-B3-01)。跨 kind / 错宽度 ID 与 pack trailer 错配 fail-closed。
2026-09-10 更新(plan-20260908 SP-02):
push_auth=token时 SSHauth_password复用lookup_push_token(username 不参与判定,身份为 tokenname)。客户端用SSH_ASKPASS(password 不进 tracing、不进GIT_SSH_COMMAND)。push_auth=none与 review(省略)均 Reject password。进程 IT:integration_git_ssh_trunk_token_anon_off_clone_fail、integration_git_ssh_trunk_token_anon_off_password_clone/_fetch/_pull、integration_git_ssh_trunk_token_push_receive_pack_disabled、integration_git_ssh_review_pubkey_anon_off_clone、integration_git_ssh_review_pubkey_anon_on_push。
2026-09-11 更新(plan-20260906 SO-19..SO-25 / SO-04): storage-only SSH 黑盒为
scripts/git_protocol_smoke_storage_only.sh:只读矩阵(SSH ls-remote…SSH protocol v2 blob:none clone)+SSH reject receive-pack(断言稳定子串SSH receive-pack is disabled;未设MEGA2_SSH_REPO_URL时 SKIP)。默认GIT_SSH_COMMAND使用StrictHostKeyChecking=accept-new+ workdir known_hosts;anonymous_access=true下auth_none。对照 review smoke 与 plan-20260908。
-
HTTP 和 SSH 双协议支持已就位。
contract::git_protocol/http.rs和contract::git_protocol/ssh.rs分别实现两个协议入口,共用SmartSession和src/ceres/protocol/smart.rs的 smart protocol 实现。 -
基础 fetch/push/clone 可工作。当前能支持标准 Git 客户端的基本 clone、fetch、push 操作,但多处使用
unwrap()和缺乏边界检查。 -
pkt-line 解析与 receive-pack 分流已完成首批止血。
read_pkt_line的可失败版本已落地,HTTP/SSH receive-pack 已按 flush-pkt 分割 commands 与 pack bytes,不再搜索PACKmagic;delete-only push(全 delete)已支持(跳过 unpack);残余风险是当前实现仍缓冲完整 body / channel 数据,尚未实现真正 streaming pkt-line reader。 -
认证上下文已统一(HTTP/SSH)。 HTTP receive-pack 需要 Bearer/Basic token,upload-pack 无认证;SSH publickey 认证成功后保存 username 并传入
SmartSession,commit binding 绑定到 authenticated actor。receive-pack 尚未做 repo/path 级 push 权限校验。 -
Capability advertise 已完成保守收敛与 truth table 覆盖。receive-pack 重新 advertise 已由 HTTP CL delete smoke 覆盖的
delete-refs,但不再 advertise 未验证的 atomic、report-status-v2、quiet、no-thin;upload-pack 不再 advertise 未实现的 include-tag;v2 不再 advertise 未 act-on 的server-option。side-band-64k/ofs-delta已补 advertise/parse 单测(ofs-delta pack decode 委托git-internal),object-format落地 SHA-1 默认策略;(2026-06-30)真实 Git CLI 兼容性矩阵已通过.github/workflows/git-protocol-smoke.yml在 CI 中自动化执行。用户可见的分支与 Tag 规则见../user-guide.zh.md。 -
SSH 多 channel 状态已隔离,并已支持 protocol v2。
SshServer按ChannelId保存独立GitSshChannelState;SSH client 通过GIT_PROTOCOL=version=2请求 v2 时,server 返回 v2 capability advertisement,并在 upload-pack data 阶段分发ls-refs/fetchcommand。
| 能力 / 组件 | 实现状态 | 关键事实与风险 |
|---|---|---|
| HTTP GET /info/refs | 已实现(含 protocol v2 advertisement) | query 已要求 exactly one service=...;缺失、重复、非法或额外参数均返回 ProtocolError::InvalidInput;Git-Protocol: version=2 会返回 v2 capabilities;真实 Git CLI 兼容性矩阵已通过 CI smoke gate 覆盖(2026-06-30)。 |
| HTTP POST upload-pack | 已实现(含 shallow / v2 fetch / blob:none) | 一次性读取 request body 到内存;pkt-line 与 want/have malformed input 已返回协议错误;protocol v1 支持 deepen/deepen-relative,v2 支持 ls-refs、fetch、deepen、filter blob:none;仍不支持 streaming request parser。 |
| HTTP POST receive-pack | 已实现(CL push + delete-only / pack-less 与 HTTP smoke 已纳入 CI) | command pkt-line malformed input、空命令列表与无效 PACK magic 已返回协议错误;flush 后空 payload 为 pack-less(不再要求非删除必须带 pack);commands / pack 已按 flush-pkt 分割;delete-only 与 pack-less create/update 跳过 unpack;HTTP CL push 与 Git-client tag 拒绝 已进入 Git CLI smoke CI gate;多 commit 线性链 push 已放开(2..=250 累计口径);FC-08 起单次多条非删除 branch 为 mixed report-status(多余 ng,第一条可 finalize),而不是整包拒绝;仍需 streaming parser。 |
| SSH git-upload-pack | 已实现(per-channel state + protocol v2) | exec command 已走独立 parser,支持基础 shell quoting、包含空格的路径和严格命令白名单;upload-pack 初始响应已按 bytes 发送;SshServer 已按 ChannelId 隔离 SmartSession 与 receive-pack 缓冲区;GIT_PROTOCOL=version=2 可启用 v2 ls-refs / fetch。 |
| SSH git-receive-pack | 已实现(per-channel state) | 与 HTTP 共用 flush-pkt 分割逻辑,不再搜索 PACK;每个 SSH channel 拥有独立的 receive-pack 缓冲区,多 channel 不再共享状态。 |
| SSH git-lfs-authenticate / transfer | 已实现 hybrid;pure SSH transfer 明确 unsupported | git-lfs-authenticate 支持 hybrid 模式,返回 HTTP LFS URL;git-lfs-authenticate / git-lfs-transfer 均要求 operation 为 upload 或 download;git-lfs-transfer 通过 stderr extended-data 返回明确 unsupported 错误 + channel failure,不再输出普通占位文本。 |
| 权限与认证 | 已统一(读写策略化) | HTTP receive-pack 有 Bearer/Basic token 认证;review SSH 走 publickey,storage-only push_auth=token 时 SSH auth_password 命中 lookup_push_token 后将 token name 写入 authenticated_user。HTTP/SSH commit binding 均绑定到 authenticated actor(set_authenticated_user)。upload-pack 匿名访问已策略化:check_upload_pack_access 按 git.anonymous_access(默认 true)放行匿名 clone/fetch,关闭时无 token 返回 Forbidden(3 个单测覆盖),HTTP(http.rs:53/217)与 SSH(ssh.rs:149)共用。receive-pack 通过 check_push_permission 走 Cedar pushRepo 授权:未认证 push 直接 Forbidden(不进入 unpack),已认证时按 state.entity_store 策略裁决(策略库为空则放行),HTTP(http.rs:64/355)与 SSH(ssh.rs:140)共用。更细粒度 repo/path ACL 与基于策略的 push-deny 协议层单测待后续。 |
| Capability advertise | 保守收敛 + truth table 已建立 | receive-pack 仅 advertise report-status + common 能力;upload-pack 移除 include-tag;v2 移除 server-option。side-band-64k/ofs-delta 已覆盖 advertise/parse(ofs-delta pack decode 委托 git-internal);object-format 落地 SHA-1 默认策略;RepoHandler::supports_shallow_fetch/supports_filtered_fetch 门控非 Monorepo handler。(2026-06-30)真实 Git CLI 兼容性矩阵已通过 CI smoke gate 覆盖。 |
| 错误处理 | 首批止血 | info/refs service 参数、smart pkt-line malformed input、HTTP upload/receive request body stream 错误、malformed SSH exec 与 import repo handler 的 repo path/DB lookup 已改为协议错误/channel failure;SSH data/handle_upload_pack/handle_receive_pack 中的 smart_protocol.unwrap()、protocol error .unwrap()、session.data().unwrap()、git-lfs-authenticate response serialization .unwrap() 和 auth_publickey DB 查询 .unwrap() 已改为可诊断错误/best-effort 发送(2026-06-23/24);2026-06-28 更新:Repo::new 的非 UTF-8 path/file_name unwrap() 已改为 ProtocolError::InvalidInput,SmartSession::git_upload_pack 中 full_pack/incremental_pack 的 unwrap() 已映射为协议错误;2026-06-28 更新 2:HTTP Git 路由已抽出 GitProtocolPath parser,移除内联 .git 替换与 404 unwrap();2026-06-28 更新 3:contract/git_protocol/http.rs 中 response builder、HeaderValue::from_str、upload-pack sideband read_buf 的 unwrap() 已收敛;2026-06-28 更新 4:contract/git_protocol/ssh.rs 中 LFS Duration::try_seconds(...).unwrap() 与 channel_eof 的 expect("state just found") 已移除。Protocol 当前范围内剩余 unwrap() 已基本收敛;vault/legacy 路径与数据迁移工具不在本次范围。 |
-
协议正确性优先:Git smart protocol 是二进制协议,所有 payload 必须按 bytes 处理,不能假设 UTF-8 或文本。
-
客户端不能导致崩溃:任何 malformed client input(非法 query、脆弱 exec、malformed pkt-line)都必须返回协议错误,不能 panic。
-
Capability 诚实:只 advertise 已实现且有测试的能力。未实现的能力如 atomic、report-status-v2 应先完齐或从 advertise 中移除。
-
权限强制:auth context 必须统一(HTTP Bearer/Basic + SSH key),并在 upload-pack/receive-pack 入口前完成。push 必须验证用户和权限。
-
pkt-line 协议边界:receive-pack 的 command 和 pack 分界必须由 flush-pkt 决定,不能依赖 magic bytes 搜索。
-
兼容性声明:已实现的现代能力(protocol v2、shallow clone、
filter blob:none)必须明确范围;未实现的功能(tree filters、完整 promisor remote、pure SSH LFS)必须明确文档化,而不是静默失败。
| 维度 | 当前状态 | 目标状态 | 关键差距 |
|---|---|---|---|
| 错误处理 | 多处 panic | 协议错误或断开,不能 panic | 需要 Result 化所有输入解析 |
| pkt-line 实现 | unwrap() panic 散落 |
定义 PktLine enum 和 streaming parser |
需重构 parser 返回 Result |
| receive-pack 分流 | 已按 flush-pkt 分割,仍缓冲完整 body/channel | streaming pkt-line reader + delete-only push 验证 | 中等 |
| SSH exec 解析 | 脆弱(空格、拼接错) | 严格 parser,支持引号和转义 | 需独立 parser 函数和单测 |
| SSH 多 channel | 全局 session 状态 | per-channel state dictionary | 已引入 GitSshChannelState(2026-06-28) |
| 认证统一 | ✅ HTTP/SSH 共用 check_upload_pack_access / check_push_permission |
统一入口鉴权 + 匿名策略 + push 授权 | upload-pack 匿名可配置、receive-pack Cedar pushRepo 授权已落地;更细 repo/path ACL 与 push-deny 协议层单测待后续 |
| Capability 诚实 | advertise 多于实现 | 仅 advertise 已实现能力 | 需 capability truth table |
| 测试矩阵 | 无 | 真实 Git CLI smoke test | 需建立兼容性测试脚本 |
本文档与其他改进计划的依赖关系:
| Git Protocol 的工作 | 对其他模块的依赖 | 依赖类型 | 关键同步点 |
|---|---|---|---|
| 阶段 0:兼容性基线 | general.md | 框架 | 必须遵守结构规范 |
| 阶段 1:panic 止血 | general.md | 框架 | 错误模型与 config 的 error.rs 对齐 |
| 阶段 2-3:pkt-line/capability | general.md | 框架 | 与整体错误处理框架一致 |
| 阶段 4:auth 统一 | config.md | 前置 | 需先完成 config 阶段 2 的 CLI LoadMode |
| 阶段 5-6:SSH/LFS 完善 | integration.md | 并行 | 集成测试可同步验证改进 |
注:阶段 1-3 相对独立,可先完成基础止血。阶段 4 需与 config 协同,推荐在 config 阶段 2 之后。
-
二进制协议处理:当前多处假设 UTF-8,需要完整的 bytes 化改造。如果改造不彻底,会在处理特殊 pack 数据或 binary diff 时出现隐蔽问题。
-
receive-pack 事务边界:当前 atomic 的声称不被测试覆盖,并发 push 的锁粒度不明确。如果不完整地实现事务,可能导致数据不一致。
-
SSH 多 channel 状态:state 在 handler 上全局保存,虽然 clone 降低共享风险,但一个 connection 内多个 channel 仍可能互相影响。
-
Capability 误导:advertise 未实现的 capability 会让 Git 客户端进入不支持的代码路径,产生隐蔽失败。必须建立 truth table 防止此类问题。
-
兼容性测试缺失:没有真实 Git CLI 的测试矩阵,无法防止 panic 或协议误差的回归。
| 维度 | 评估结论 |
|---|---|
| 合理性 | 高(8.5/10)。当前代码框架完整,兼容性问题识别准确。阶段划分合理,从基础止血到兼容性扩展的路线清晰。 |
| 可行性 | 中高(7.5/10)。基础 panic 止血相对容易(Result 化输入解析);pkt-line 和 receive-pack 分流需要较深的协议理解;SSH auth 统一需与 config 协同。 |
| 完整性 | 中高(7.5/10)。6 个阶段覆盖主要问题,且已补齐 shallow clone、protocol v2 ls-refs / fetch、filter blob:none 等现代 Git 基础能力。仍缺真实 Git CLI 矩阵、streaming pkt-line reader、tree filters 和完整 promisor remote 语义。 |
| 安全性 | 中(7/10)。panic 止血直接提升安全性;auth 统一防止权限泄露。但 per-channel state 和事务边界的改进是长期工作。 |
| 可维护性 | 中(7/10)。首批已移除 magic bytes 搜索和部分 scattered panic;SSH channel state 已改为 per-channel 字典。剩余 unwrap() 和 streaming parser 缺口仍是维护陷阱。改进后代码应更易维护,但短期工作量较大。 |
Git Protocol 是 mega2 的核心功能,但当前实现在错误处理、兼容性和细节上存在多个缺陷。建议优先完成阶段 0-1 的兼容性基线建立和 panic 止血,确保 malformed input 不导致崩溃。再依次完成阶段 2-3 的 pkt-line 和 receive-pack 改造,确保协议边界正确。阶段 4 的 auth 统一可与 config 模块协同完成,阶段 5-6 为长期改进。
- 崩溃修复:消除 panic 风险,malformed input 返回协议错误而非连接中断
- 兼容性提升:标准 Git 客户端在各场景下(clone、fetch、push、tags、delete)更稳定可靠
- 可观测性改进:清晰的错误模型和兼容性测试矩阵便于快速诊断和防止回归
- 维护成本降低:代码结构改进(streaming parser、per-channel state)降低后续改造成本
- 扩展性增强:shallow clone、protocol v2 和
filter blob:none已落地,为后续 tree filters、promisor remote 和 streaming parser 继续预留设计空间
本文覆盖:
- Git smart HTTP:
GET /info/refs?service=...、POST /git-upload-pack、POST /git-receive-pack。 - Git SSH:
git-upload-pack '<repo>'、git-receive-pack '<repo>'、git-lfs-authenticate。 - Git smart protocol 的 pkt-line、capability、side-band、upload-pack、receive-pack。
- Git LFS 与 SSH hybrid LFS discovery 的兼容性。
- 与标准
git clone、git fetch、git push、git lfs客户端交互相关的认证、错误处理和测试建议。
不覆盖普通 REST API、Web UI、内部 monorepo API 或对象存储协议。
HTTP 服务在 src/server/http_server.rs 中注册 Git 协议入口:
/{*path}
-> GET */info/refs
-> POST */git-upload-pack
-> POST */git-receive-pack
核心分发函数是 handle_smart_protocol:
GET .../info/refs调用contract::git_protocol::http::git_info_refs。POST .../git-upload-pack调用contract::git_protocol::http::git_upload_pack。POST .../git-receive-pack调用contract::git_protocol::http::git_receive_pack。- 其他路径返回 404
Operation not supported。
HTTP Git 协议处理代码位于 src/contract/git_protocol/http.rs。该模块负责:
- 解析
InfoRefsParams.service。 - 创建
SmartSession。 - 读取 request body。
- 调用共享 smart protocol 实现。
- 设置 Git smart HTTP 所需的
Content-Type和Cache-Control。 - 对 receive-pack 执行 Bearer token 或 Basic Auth token 认证。
SSH 服务入口位于 src/server/ssh_server.rs 和 src/contract/git_protocol/ssh.rs。
src/server/ssh_server.rs 负责:
- 加载或生成 SSH host key,并保存到 vault 的
ssh_server_key。 - 构造
russh::server::Config。 - 构造
ProtocolApiState。 - 运行
SshServer。
src/contract/git_protocol/ssh.rs 负责:
- 处理
exec_request。 - 支持
git-upload-pack和git-receive-pack。 - 支持
git-lfs-authenticatehybrid LFS discovery。 - 对
git-lfs-transfer返回明确 unsupported failure。 - SSH 认证:review(省略
push_auth)用 UserStorage publickey,不成功放行auth_none;storage-only 在anonymous_access=true时auth_noneAccept,auth_publickey早拒(不查 UserStorage)。ssh_receive_pack=false只关 receive-pack,不关 upload-pack。
SSH 和 HTTP 最终共用 SmartSession 与 src/ceres/protocol/smart.rs 中的 smart protocol 实现。
SmartSession 定义在 src/ceres/protocol/mod.rs,核心字段包括:
repo_pathservice_type:UploadPack或ReceivePacktransport_protocol:Http或Sshauthcapabilitiesview:Option<ResolvedView>,视图 URL 经第 3 层解析后为Some,其余会话为None;new/from_state签名不变。
repo_handler_with_commands 先看 view,再根据 repo path 选择 repo handler:
- 如果
view为Some,使用ViewRepo:用解析时取得的配置快照构造,在读取state.storage.config()前返回,不看 repo path。 - 如果 path 位于
config.monorepo.import_dir下,使用ImportRepo。 - 否则使用
Monorepo。
ImportRepo 和 Monorepo 都实现 RepoHandler,提供 pack 生成、pack 解码、ref 更新、receive-pack finalize 等能力。
核心实现位于 src/ceres/protocol/smart.rs:
git_info_refs:构造 ref advertisement。git_upload_pack:解析want、have、done,返回 ACK/NAK 与 pack stream。parse_receive_pack_commands:解析 receive-pack ref update commands。git_receive_pack_stream:解码 pack stream、保存对象、更新 refs、返回 report-status。build_side_band_format:按 side-band / side-band-64k 包装 pack 数据。read_pkt_line/add_pkt_line_string:pkt-line 编解码辅助。
当前 advertise 的 capability:
upload-pack:
multi_ack_detailed no-done side-band-64k ofs-delta shallow agent=mega/0.1.0
receive-pack:
report-status side-band-64k ofs-delta agent=mega/0.1.0
protocol v2 upload-pack:
agent=mega/0.1.0 ls-refs fetch=shallow filter object-format=sha1
Capability enum 当前只解析部分 capability:
multi_ack
multi_ack_detailed
no-done
side-band
side-band-64k
report-status
report-status-v2
ofs-delta
deepen-since
deepen-not
shallow
当前实现已经覆盖 smart HTTP 的三类核心请求:
- ref discovery:
GET /repo.git/info/refs?service=git-upload-pack。 - fetch/clone:
POST /repo.git/git-upload-pack。 - push:
POST /repo.git/git-receive-pack。
HTTP response 已设置:
Content-Type: application/x-git-upload-pack-advertisementContent-Type: application/x-git-receive-pack-advertisementContent-Type: application/x-git-upload-pack-resultContent-Type: application/x-git-receive-pack-resultCache-Control: no-cache, max-age=0, must-revalidate
当前 SSH 实现支持标准 Git SSH exec 命令:
git-upload-pack '<repo>.git'
git-receive-pack '<repo>.git'
认证采用 SSH public key fingerprint 匹配数据库中的用户 SSH key。认证成功后,git-upload-pack 和 git-receive-pack 复用 SmartSession。
fetch 侧:
- 支持
want、have、done。 - 支持无
have时 full pack。 - 支持有
have时 incremental pack。 - 支持
multi_ack_detailed下的ACK ... common和ACK ... ready。 - 支持 side-band-64k 包装 pack data。
- 支持
deepen/deepen-relativeshallow fetch,并 advertiseshallowcapability。 - 支持 protocol v2
ls-refs/fetch(HTTP 通过Git-Protocol: version=2,SSH 通过GIT_PROTOCOL=version=2)。 - 支持 protocol v2 partial clone
filter blob:none;tree filter 仍未承诺完整语义。
push 侧:
- 支持 receive-pack command 解析。
- 支持 pack stream 解码。
- 支持对象保存。
- 支持 refs 更新。
- 支持
report-status风格的unpack ok与 per-ref status。 - 支持 tag 和 branch 的基本更新路径。
LFS router 同时暴露:
/api/v1/lfs/.../info/lfs/...
HTTP server 还包含 rewrite_lfs_request_uri,用于把 repo path 下的 /info/lfs/... 重写到 LFS runtime router,并在改写前把仓库前缀写入 LfsRepoContext。SSH 下 git-lfs-authenticate 会返回 HTTP LFS URL,让 Git LFS 客户端走 hybrid 模式。
开启 fastcdc Cargo feature 时,同一 LFS mount 额外提供 Libra FastCDC Media API:<repo>.git/info/lfs/libra/media/v1/...(不是无 libra/ 前缀的 media/v1,也不是 Git LFS 扩展)。每条 Media 路由(含 capabilities)都要求 Bearer AccessTokenUser,不复用 objects 传输 URL 的「batch 后可不再认证」例外。关闭 feature 时这些路由不存在(404),既有 LFS batch/objects/locks 行为不变。协议细节见 fastcdc-media.md。
handle_smart_protocol 当前通过 parse_info_refs_params 解析并校验 query,反序列化失败、缺失/重复/非法 service 或存在额外 query 参数都返回 ProtocolError::InvalidInput;contract::git_protocol::http::git_info_refs 仍保留同类防御性校验。旧实现曾直接:
let service_name = params.service.unwrap();
let service_type = service_name.parse::<ServiceType>().unwrap();
let params: InfoRefsParams = serde_urlencoded::from_str(query_str).unwrap();已处理风险:
- query 反序列化错误会返回 400,不再 panic。
- 缺少
service会返回 400,不再 panic。 - 重复
service或额外 query 参数会返回 400。 - 非法 service 会返回 400,不再 panic。
仍待后续:
- 更完整 smart HTTP query 兼容性矩阵和真实 Git CLI 覆盖。
- 按真实 Git CLI 矩阵确认是否需要对非标准客户端提供兼容模式。
建议:
- 缺失、重复、额外参数或非法
service返回 400。 - 不支持的 service 返回 403 或 400,并输出 Git 客户端可读错误。
- 对额外 query 参数做显式策略:首版已选择拒绝;如未来需要兼容非标准客户端,应先补矩阵并记录偏离规范。
- 所有解析失败都返回
ProtocolError,不能 panic。
git_upload_pack 当前通过 try_fold(BytesMut::new()) 把整个 request body 读入内存。fetch 请求通常较小,但 protocol v0 negotiation 在复杂仓库和大量 have 场景下仍可能较大。body stream 读取错误已统一映射为 ProtocolError::InvalidInput,不再 panic。
建议:
- ✅ 已增加 body size 上限(
GIT_HTTP_MAX_BODY_BYTES = 512 MiB,collect_body_data拒绝超限 body,2026-06-28)。 - 中期将 upload-pack negotiation 改为 streaming pkt-line reader,而不是一次性聚合 body。
- 为
read_pkt_line增加可诊断错误,避免 malformed pkt-line panic。
早期 git_receive_pack 在 chunk 中搜索字节序列 PACK:
if let Some(pos) = search_subsequence(&chunk, b"PACK") {
chunk_buffer.extend_from_slice(&chunk[0..pos]);
let commands = pack_protocol.parse_receive_pack_commands(Bytes::copy_from_slice(&chunk_buffer));
let left_chunk_bytes = Bytes::copy_from_slice(&chunk[pos..]);
...
}这一路径已在 2026-06-23 的首批止血中替换为 SmartSession::split_receive_pack_request:
- HTTP receive-pack 先聚合 request body,再按 pkt-line command list 的 flush-pkt 分割 commands 与 pack bytes。
- SSH receive-pack 对已缓冲的 channel 数据使用同一 splitter。
- capability 或 command payload 中出现
PACK不再影响分割。 - 缺失 flush-pkt 会返回
ProtocolError::InvalidInput。 - 纯 delete refs 的无 pack receive-pack 请求已支持,splitter 会在 flush-pkt
后返回空 pack payload,并由
is_delete_only_push跳过 unpack。 - 非 delete receive-pack 请求在 flush-pkt 后缺失 pack payload 会返回
ProtocolError::InvalidInput。 - 非 delete receive-pack 请求的 pack payload 不以
PACKmagic 开头时会返回ProtocolError::InvalidInput。 - flush-pkt 前没有任何 command pkt-line(空命令列表)的 receive-pack 请求会返回
ProtocolError::InvalidInput,避免无命令请求进入 ref 处理。
仍待后续处理:
- 将当前完整 body / channel 数据缓冲改为 streaming pkt-line reader。
- HTTP branch/tag push+delete 与 LFS round-trip 已纳入真实 Git CLI CI 矩阵;SSH push/delete 仍为手动 opt-in。
exec_request 早期使用:
let command: Vec<_> = data.split(' ').collect();
let path = command[1];
let path = path.replace(".git", "").replace('\'', "");
let service_type = ServiceType::from_str(command[0]).unwrap_or(ServiceType::UploadPack);这一路径已在 2026-06-23 的首批止血中替换为独立 parser。当前 parser 已覆盖以下风险:
- 空命令或缺 path 会 panic。
- 路径包含空格会被错误切分。
.replace(".git", "")会删除路径中所有.git,而不是只去掉末尾.git。- 不支持单引号、双引号和反斜杠转义。
- 非法 command 默认变成
UploadPack,可能导致错误行为。
仍待后续处理:
- 更完整的 shell 兼容性(如
--、复杂转义规则)如果标准客户端需要,再按兼容性测试补充。 - ✅ 将已解析的 exec state 与 SSH channel 绑定,避免一个 connection 内多个 channel 共享
smart_protocol/data_combined(2026-06-28 已实现)。
SshServer 原在 handler 上保存连接级 smart_protocol: Option<SmartSession> 与 data_combined: BytesMut,一个 SSH connection 内多个 channel 会共享这些状态。2026-06-28 已改为:
SshServer维护channels: HashMap<ChannelId, GitSshChannelState>。GitSshChannelState每个 channel 单独保存SmartSession、receive-pack buffer、service type。data只读写当前ChannelId的状态。channel_eof只处理对应 channel 的状态,处理完后从 map 移除。- 关闭 channel 时清理状态。
GitSshChannelState记下视图错误的退出码;channel_eof按它发 exit-status,缺省为 0(HP-34)。
设计 §6.1 的错误契约规定 SSH 对视图不存在和只读分别发送 ERR view not found、ERR view URLs are read-only,退出码均为 1;暂不可用发送 ERR view <filter_id> unavailable: <reason>,退出码为 75;打包预检失败发送错误原文的 ERR,退出码为 1。每条消息都是一个 pkt-line。
exec 阶段由 reject_exec 依次发送 channel_success、ERR、exit-status、EOF 和 close,不登记通道状态,并移除该通道的 clients 句柄与 v2 标记。russh 在 close 之后不再回调 channel_eof 或 channel_close。HP-18 与 HP-20 的 exec 拒绝经 SshServer::send_exec_err 调用这条路径。
v0 upload-pack、v2 ls-refs 和 v2 fetch 的数据阶段都经 write_data_error 写出视图错误。写出 ERR 后,通道不再写 data 字节,后续数据和 EOF 残留请求都会丢弃。channel_eof 先补处理残留请求,再取得退出码;若 clients 已没有该通道,说明它已被 reject_exec 拒绝,可能是 ERR 进入 russh 待发队列后客户端仍发送 EOF,此时只发送 close,exec 阶段发送的码是该通道唯一的 exit-status。非视图错误继续输出裸文本(DEFER-HP-17)。
定位符在 HTTP、SSH 与 LFS 入口共用同步分类,先识别首段视图保留名,再判定名字、版本与 filter ID 语法。HTTP 在分派 Git handler 前、SSH 在建立 SmartSession 前,以一次配置快照判定是否启用视图、服务是否只读。启用状态下的 upload-pack 在第 3 层接入前暂返回「不存在」。位置、顺序与状态码见设计 §6.1「入口分层」和「错误契约」。
SSH git-lfs-authenticate 与 git-lfs-transfer 对视图路径写一行 ERR view not found 并以退出码 1 结束,与 HTTP LFS 的 404 同类;这是设计 §6.1 第 2 层「同样拒绝」的具体形式。
本卡 integration_git_ssh 中的原始 SSH 请求和 git 客户端沿用该 target 既有 storage-only 用例的宿主回环方式:宿主 ssh 和 git 经 127.0.0.1 连接。请求与应答字节不取决于执行位置;宿主 git 只断言 not found、returned error: 403、remote error: view not found、remote error: view URLs are read-only 四种稳定子串。此执行位置按设计 §7.4 的 HP-18 例外登记。
定位符通过认证后才解析;HTTP git_info_refs 在认证分支之后、v2 能力宣告短路之前解析,HTTP git_upload_pack 在 check_upload_pack_access 与读取请求体之间解析,SSH exec_request 在 check_upload_pack_access 之后、v2 短路之前解析。未认证请求不查视图表。具体顺序及应答见设计 §6.1「入口分层」「认证先于解析」「逐请求解析」和「错误契约」。
HTTP 每个请求解析一次;SSH 每个 exec 解析一次,ResolvedView 随通道状态中的 SmartSession 保存。该 exec 内的各条协议命令各建一个 ViewRepo,共用 exec 时取得的配置快照。
handle_upload_pack 当前:
session.data(channel, String::from_utf8(buf.to_vec()).unwrap()).unwrap();buf 是 pkt-line bytes,虽然当前 ACK/NAK 文本大多是 UTF-8,但协议层应按 bytes 处理,不应经过 String::from_utf8。
建议:
- 所有 Git protocol payload 统一用 bytes 发送。
- 删除协议二进制路径上的 UTF-8 假设。
session.data调用只传Vec<u8>或 bytes,不做 String 转换。
历史风险:曾 advertise 一些未完整实现或解析不足的能力。当前状态(均已解决):
include-tag:已从 upload-pack advertise 移除(pack 生成未按 include-tag 语义验证)。delete-refs:已重新 advertise(HTTP smoke 覆盖 CL delete;Monorepo 拒绝 Git-client tag;SSH delete 矩阵仍待补齐)。atomic:已从 advertise 移除(未实现原子 ref 更新)。quiet:已从 advertise 移除(未实现 progress 抑制语义)。no-thin:(2026-09-16)重新 advertise。移除期间任何 delta 压缩触底服务端已知对象的 push 都会以 thin pack 到达,而 pack 解码器对包外基对象 fail-closed(git-internaldecode "Pack references bases that are not in the pack"),导致 receive-pack 连接中断、ref 不推进(缺陷 RCV-01:git 2.34/2.49 复现,pack.window=0可绕过)。no-thin语义(客户端不得发送 thin pack)正是解码器当前契约的正确配套,与上游 Mega 一致;同时unpack_stream将解码失败由 panic 收敛为 typedProtocolError(2026-09-16)。report-status-v2:已从 advertise 移除(未实现 v2 完整语义)。ofs-delta:仍 advertise;OFS_DELTA pack 编解码由git-internalcrate 实现并自测(internal/pack/decode.rs处理 offset delta),mega2 侧覆盖 advertise/parse(parse_capabilities_recognizes_ofs_delta)。
建议:
- 建立 capability truth table:advertise、parse、act-on、test 四列。
- 没有行为支持和测试的 capability 先不要 advertise。
- 已完成首批:
atomic、report-status-v2、quiet、no-thin和 uploadinclude-tag已先从 advertise 移除;delete-refs已在 HTTP CL delete smoke 覆盖后重新声明(Monorepo Tag 通过 API 管理)。 - ✅ 对
object-format=sha1明确策略:SHA-1 为协议默认格式,SHA-1-only server 不 advertiseobject-format(协议允许 SHA-1 默认时省略;mega2 策略对 SHA-1-only repo 不 advertise),由单测advertised_capabilities_keep_sha1_default_and_do_not_advertise_object_format锁定。
src/ceres/protocol/smart.rs::try_read_pkt_line 已定义 PktLine enum:
Data(Bytes)、Flush、Delim、ResponseEnd,并返回
Result<PktLine, ProtocolError>。Malformed input 不再通过 unwrap / panic
处理,而是显式返回 ProtocolError::InvalidInput,且失败时不消费输入
buffer。
已覆盖的边界:
- 空输入或不足 4 字节的 length header。
- 非 hex length header。
- reserved length
0003与 length 小于 header 的场景。 - length 大于剩余 buffer。
0000flush-pkt、0001delim-pkt、0002response-end-pkt。
仍待后续:
- HTTP 和 SSH 当前仍先完整缓冲 request/channel 数据,再复用该 parser 解析。 后续需要抽出真正的 streaming pkt-line reader,避免大请求完整驻留内存。
早期实现只处理 want、have、done。当前已补齐现代客户端常用的部分扩展:
- protocol v1 upload-pack 解析
deepen/deepen-relative,并返回shallowresponse。 deepen-since/deepen-not会明确返回ProtocolError::InvalidInput,不 silent misbehave。- HTTP 和 SSH 均支持 protocol v2 capability advertisement、
ls-refs和fetch。 - protocol v2
ls-refs在 head 为零 ID 时不写 HEAD 行,因此不会输出capabilities^{}伪 ref 或symref-target;ls_refs_zero_head_flush_only锁定空 ref 列表只返回 flush。v0info/refs保留伪 ref,以承载 capability 列表。 - protocol v2
fetch支持filter blob:none,pack 只发送 commits + trees,不发送 blob objects。
仍需后续确认或扩展:
- promisor remote
- tree filters(如
tree:<depth>) want-ref- 大仓库 fetch 性能
建议:
- 用真实 Git CLI 矩阵验证
git clone --depth=1、HTTP/SSH v2 fetch、git clone --filter=blob:none的端到端行为。 - 对未实现 filter spec(例如 tree filters)继续返回明确协议错误或 fallback,不 advertise 超出实现范围的语义。
- 中期将 upload-pack negotiation 改为 streaming pkt-line reader,减少大仓库 fetch 的 request body 聚合风险。
当前 receive-pack 在 unpack 后更新 refs 和触发 side effects。代码里已有 monorepo/import 的 finalize 事务设计,但 advertised atomic 表示客户端可以期待“全部 ref 更新要么都成功,要么都失败”。
风险:
- tag 更新在循环中较早持久化,branch finalize 后续失败时是否能整体回滚需要确认。
- monorepo attach、CL、conversation、build hook 等 side effects 与 ref update 的事务边界需要明确。
- 并发 push 的锁粒度和 race 行为需要测试。
建议:
- 若不能保证 Git 意义上的 atomic,先不要 advertise
atomic。 - 建立 receive-pack transaction boundary 文档。
- 对并发 push 同一 ref、非 fast-forward、删除 ref、tag update、mixed branch/tag push 建集成测试。
当前 HTTP receive-pack 需要 Bearer 或 Basic Auth token。upload-pack 没有认证检查。SSH 侧通过 public key 认证后允许 upload-pack/receive-pack。
这可能是有意设计,但需要明确策略:
- public repo 是否允许匿名 clone/fetch。
- private repo 是否需要 fetch 认证。
- push 权限是否只验证“用户存在”,还是要验证 repo/path 权限。
- SSH authenticated user 是否写入
SmartSession.auth用于 commit binding。
当前 HTTP receive-pack 会设置 authenticated_user,但 SSH publickey 认证后没有显式把 username 注入 SmartSession.auth.authenticated_user。这可能导致 SSH push 的 commit binding 变成 anonymous。
建议:
- 建立统一的
ProtocolAuthContext。 - HTTP 和 SSH 都在进入
SmartSession前完成认证与授权。 - SSH auth_publickey 成功时保存 username,并传入 receive-pack session。
- 明确 fetch 是否需要认证;如果需要,upload-pack 也要走相同 authz。
SSH 中 git-lfs-transfer 返回明确 unsupported failure,git-lfs-authenticate 返回 HTTP LFS URL。这符合 Git LFS 可 fallback 的 hybrid 模式,但不是纯 SSH LFS transfer。
建议:
- 文档明确:当前支持 Git LFS hybrid SSH -> HTTP,不支持 pure SSH LFS transfer。
git-lfs-transfer应返回明确的 unsupported/failure,而不是普通文本导致客户端误判。git-lfs-authenticate返回 body 应符合 Git LFS SSH adapter 预期,包括 href、header、expires_at,以及 upload/download operation 差异。- LFS HTTP endpoints 应补齐认证和 repo path 绑定,避免所有 repo 共用同一
/info/lfs语义造成隔离问题。
2026-06-28 更新:已抽出 GitProtocolPath parser(src/contract/git_protocol/path.rs),统一处理 repo path、仅去除末尾 .git suffix、service endpoint 与 HTTP 方法校验,并保留 third-party.git root repo 禁用规则。src/server/http_server.rs::handle_smart_protocol 不再内联后缀判断和 404 unwrap(),而是直接调用 parser。剩余工作:404/400/403/405 返回策略可随认证统一进一步标准化。
2026-10-20(MTR-94):HTTP Router 外层对禁用 traces 的 GET/POST 保留命名空间请求先返回 HTTP 404(JSON 错误消息为 traces locator not found),覆盖 smart discovery/upload-pack/receive-pack,避免 v2 discovery、receive 探测和请求解压绕过关闭入口。根段规则同时检查原始 URI 与一次百分号解码后的字节路径;只移除 Git endpoint 前仓库名的一个末尾 .git,不把普通嵌套 .traces 或 .traces-backup 当成保留根。拒绝先于业务鉴权、body 消费和 Native/Import 分派,不查询 scope 存在性。 LFS 重写前的 URI 由服务端保存在请求扩展,禁用门同时检查它与当前路由 URI,避免移除仓库前缀后丢失保留根。字面根名为 %2etraces 的代码仓,其 /%2etraces/… URL 在 disabled 时同样拒绝;enabled 时保持既有分派。具体关闭语义及尚未接通的 enabled 数据面见 traces 协议。
2026-10-21(MTR-100):SSH 在既有连接认证及 exec 解析后检查关闭开关;根 .traces 请求在 SmartSession、广告及 stdin 消费之前返回 ERR traces locator not found、exit status 1、EOF 并关闭通道。匹配字面路径及点段折叠,不作 HTTP 百分号解码;普通认证、普通代码分派与 storage-only receive-pack 限制不变。该守卫不启用 traces 数据面;匹配规则与实际验收边界见 traces 协议 和执行计划。
2026-10-23(MTR-97 候选):内部 wire 解码准入采用可取消异步输入与有界解码worker;固定限额、生命周期和当前验收状态见 traces 协议 与 MTR-97 任务卡。真实 HTTP/SSH 数据面仍由后继卡接线。
历史建议(已落地):
- 抽出
GitProtocolPathparser,统一处理 repo path、.gitsuffix、service endpoint。 - 路由层只做粗分发,路径语义在 parser 中测试。
- 404/400/403/405 返回策略标准化。
目标:在修改实现前建立可重复的真实 Git 客户端测试矩阵。
已新增 scripts/git_protocol_smoke.sh 作为第一版真实 Git CLI smoke matrix。该脚本面向已经启动的 mega2 HTTP/SSH 服务,默认覆盖只读 HTTP 场景(基础 clone/fetch、shallow clone、protocol v2 fetch、filter blob:none);SSH 通过 MEGA2_SSH_REPO_URL 启用同类只读场景;HTTP/SSH CL push(断言不新增公开 refs/heads/*)与 Git 客户端 Tag 推送拒绝 通过 MEGA2_GIT_SMOKE_PUSH=1 显式启用;HTTP LFS push/clone/locks-list 通过 MEGA2_GIT_SMOKE_LFS=1 + MEGA2_GIT_SMOKE_PUSH=1 显式启用,LFS 用例会从远端默认分支创建普通子提交、显式配置 <remote>/info/lfs endpoint,并对实际生成的 refs/cl/* 做定向 fetch、checkout、LFS pull 与清理,避免默认修改远端公开分支、不依赖孤儿初始化、全量 clone 或 Git LFS 对根路径 remote 的默认 URL discovery。CI 当前自动启用 HTTP read-only 矩阵、HTTP CL push + tag-reject 和 HTTP LFS round-trip;SSH push 仍保留为手动 opt-in。用户可见规则见 ../user-guide.zh.md。
(2026-06-30)CI 自动化回归 gate 已落地;2026-07-01 扩展 CL push 与 LFS;2026-08-03 对齐 Monorepo 分支/tag 规则):.github/workflows/git-protocol-smoke.yml 在 PR 和 main push 时自动启动 PostgreSQL + Redis 测试栈、构建 release 二进制、seed mail secret、启动 service http,然后以 monorepo 根路径 http://ci-smoke:<masked-token>@127.0.0.1:9000/ 为目标运行 scripts/git_protocol_smoke.sh 的 HTTP 矩阵(ls-remote、clone、fetch、protocol v2 fetch/ls-remote、shallow clone depth=1、blob:none partial clone、CL push(无新公开分支)、拒绝 Git-client tag push、LFS push/clone/pull/locks-list)。workflow 直接在 smoke DB 的 access_token 表插入一次性 token 并 mask 日志输出,满足 push 所需认证;同时安装 git-lfs 并启用 MEGA2_GIT_SMOKE_LFS=1,让 LFS round-trip 成为默认 CI gate。该 workflow 在协议路径变更(src/ceres/protocol/**、src/contract/git_protocol/**、src/server/http_server.rs、scripts/git_protocol_smoke.sh、docs/refactoring/protocol.md)时触发,满足阶段 0 "每个后续阶段都能复用该矩阵防止回归"的验收标准。
prepare_pack 以单条 SQL 对就绪状态、根链和 want 归属做单快照复查。未就绪或 want 已被回收时 reason 为 warming up;根链停追时为 root chain halted。计数阶段读取待发 tree 的存储字节,对 L0 mega_tree 行验证哈希,不自洽时拒绝并报告 does not match its stored entries;tree 缺失或无法解析时按缺对象处理,报告 is missing。这两种拒绝不改变视图就绪状态。
每次 L0 拒绝使 view_pack_tree_mismatch_total 加一,并发出含 metric、filter_id、tree_id 的 ERROR 事件。缺对象也发出含 filter_id、tree_id 的 ERROR 事件,不带 metric,不增加该计数。v2 的 NAK 轮不做打包预检。打包方法只按计数结果编码,不再读取 mega_view_commit_map。四类失败的线上应答见历史投影设计 §6.1 错误契约。
口径(强制):
git clone/git fetch不等于覆盖字面git pull。字面 pull 仅以下方cargo:…_pull_…格计;不得用 clone/fetch 冒充 pull 覆盖。
单元格取值只能是:cargo:<exact_fn>、smoke:<case>、DEFER-GM-*、或 N/A+理由。本表是唯一完整矩阵;integration.md 只保留 target 索引与回链。
同一格需要多个用例时,各取值以 、 分隔,每个取值仍须是上述形式之一。
| 用户命令 | HTTP | SSH | Auth | Repo-shape |
|---|---|---|---|---|
| ls-remote | smoke:HTTP_ls-remote | smoke:SSH_ls-remote | N/A+只读广告默认匿名 | N/A+Monorepo根路径;ImportRepo见DEFER-GM-01 |
v2 ls-refs 空仓库(不存在的 /<path>.git) |
cargo:integration_git_cli_v2_missing_path_empty | N/A+与 HTTP 共用 handle_v2_ls_refs,应答字节由 ls_refs_missing_monorepo_path_flush_only 锁定 |
N/A+只读广告默认匿名 | N/A+Monorepo 不存在的路径;ImportRepo 缺失返回 NotFound |
| clone | cargo:integration_git_cli_http_round_trip | cargo:integration_git_ssh_authenticated_clone | cargo:integration_git_cli_auth_anonymous_disabled_rejects_clone | cargo:integration_git_cli_failpath_clone_missing_repo_keeps_service_alive |
| fetch | smoke:HTTP_fetch | smoke:SSH_fetch | N/A+随clone/token往返覆盖 | N/A+Monorepo;ImportRepo见DEFER-GM-01 |
| pull(字面) | cargo:integration_git_cli_http_pull_cl_ref_round_trip | cargo:integration_git_ssh_pull_cl_ref_round_trip | N/A+pull用例内鉴权与HTTP匿名默认 | N/A+定向refs/cl;非默认main快进 |
| push(CL) | cargo:integration_git_cli_http_round_trip | cargo:integration_git_ssh_authenticated_push_creates_cl_ref | cargo:integration_git_cli_auth_push_without_token_returns_401_challenge | N/A+Monorepo不新建refs/heads |
| CL ref delete(清理) | smoke:HTTP_push_CL | smoke:SSH_push_CL | N/A+删除随push_CL清理;无独立Auth用例 | N/A+仅删除本用例生成的refs/cl;不覆盖公开分支删除 |
| tag push(拒绝) | cargo:integration_git_cli_http_rejects_git_client_tag_push | smoke:SSH_reject_Git-client_tag_push | N/A+拒绝路径不依赖token形态 | N/A+Monorepo禁客户端tag创建 |
| tag delete(拒绝) | N/A+本计划未单列 tag 删除拒绝用例;Monorepo 禁止 Git 客户端 Tag | N/A+同 HTTP;SSH 未单列 tag 删除拒绝 | N/A+非鉴权矩阵轴 | N/A+公开 refs/tags 删除非本计划目标 |
| branch delete(公开) | N/A+Monorepo不提供公开refs/heads删除场景 | N/A+同HTTP | N/A+非鉴权矩阵轴 | N/A+公开分支删除非目标 |
| LFS push | cargo:integration_git_lfs_http_round_trip | DEFER-GM-02 | N/A+LFS往返内token | N/A+Monorepo+显式info/lfs |
| LFS pull | cargo:integration_git_lfs_http_round_trip | DEFER-GM-02 | N/A+随LFS往返 | N/A+定向CL取回后git_lfs_pull |
| LFS locks(list) | smoke:HTTP_LFS_push_and_clone | DEFER-GM-02 | N/A+随LFS smoke | N/A+只读list |
| SSH lifecycle/topology | N/A+HTTP不经sshd | cargo:integration_git_ssh_service_lifecycle_isolated | cargo:integration_git_ssh_wrong_key_is_rejected | N/A+cargo-native自启拓扑 |
| Mega refs fixture | cargo:integration_git_cli_mega_fixture_refs_round_trip | N/A+夹具守卫留在HTTP target | N/A+夹具不改鉴权面 | N/A+GM-09 go/no-go后启用或取消 |
| shell SSH 广度 CI | N/A+HTTP已有CI smoke | DEFER-GM-04 | N/A+DEFER范围 | N/A+DEFER范围 |
| missing-repo 客户端失败 | DEFER-GM-05 | DEFER-GM-05 | N/A+空仓广告语义 | N/A+原DEFER-IT-12→DEFER-GM-05由GM-11B收口 |
| 视图 receive-pack 拒绝 | cargo:integration_git_ssh_view_layer2_git_client_read_only | cargo:integration_git_ssh_view_layer2_ssh_read_only | cargo:layer2_receive_pack_forbidden_before_auth_and_body | N/A+视图前缀固定只读 |
| 视图 LFS 404 | cargo:layer2_lfs_not_found | cargo:integration_git_ssh_view_layer2_ssh_lfs_rejected | cargo:layer2_lfs_not_found | N/A+视图前缀不进入 LFS 命名空间 |
| 未知或已禁用的视图 | cargo:layer2_disabled_not_found、cargo:integration_git_cli_view_layer3_http_unknown | cargo:integration_git_ssh_view_layer2_ssh_not_found、cargo:integration_git_ssh_view_layer3_unknown | cargo:layer2_disabled_not_found、cargo:layer3_before_resolve_auth | cargo:layer2_enabled_unregistered_not_found |
| 视图 ls-remote | cargo:integration_git_cli_view_layer3_http_ls_remote | cargo:integration_git_ssh_view_layer3_ls_remote | cargo:layer3_before_resolve_auth | N/A+视图只有 ViewRepo 一种形态 |
| 视图 clone | cargo:integration_git_cli_view_pack_http_josh_proxy | cargo:integration_git_ssh_view_pack_ssh_josh_proxy | N/A+读授权与路径仓库相同 | cargo:integration_git_cli_view_pack_http_clone_gitlink |
| 视图 fetch | cargo:integration_git_cli_view_pack_http_fetch_after_trunk_push | cargo:integration_git_ssh_view_pack_ssh_josh_proxy | N/A+读授权与路径仓库相同 | N/A+视图只有 ViewRepo 一种形态 |
| 已就绪的空视图 | cargo:integration_git_cli_view_pack_http_clone_ready_empty | cargo:integration_git_ssh_view_pack_ssh_ready_empty | N/A+读授权与路径仓库相同 | N/A+视图只有 ViewRepo 一种形态 |
| 未就绪的视图 | cargo:integration_git_cli_view_layer3_http_unready | cargo:integration_git_ssh_view_layer3_unready | cargo:layer3_before_resolve_auth | N/A+视图只有 ViewRepo 一种形态 |
| 视图 fetch 非本视图提交(not our ref) | cargo:integration_git_cli_view_precheck_not_our_ref | cargo:integration_git_ssh_view_precheck_git_client_not_our_ref | N/A+只读,anonymous_access 默认放行 | N/A+视图 URL(/.filter/、/.view/) |
| 视图 clone 遇 L0 tree 不自洽 | cargo:integration_git_cli_view_precheck_l0_clone | cargo:integration_git_ssh_view_precheck_git_client_l0_clone | N/A+只读,anonymous_access 默认放行 | N/A+视图 URL(/.filter/、/.view/) |
| GAP | 缺口 | 承接 |
|---|---|---|
| GAP-01 | 无字面 git pull | GM-02 |
| GAP-02 | anonymous_access=false 无真实 CLI | GM-03 |
| GAP-03 | LFS 不在 cargo 分层门 | GM-05 |
| GAP-04 | SSH 无确定性 cargo 拓扑与指纹播种 | GM-06 |
| GAP-05 | Mega 夹具许可/体积/生成方式未审计 | GM-09 |
| GAP-06 | 场景表与 target/CI 归属漂移 | GM-11B |
| GAP-07 | DEFER-IT-12 missing-repo 边界未收口 | DEFER-GM-05 |
历史建议清单(已被上表取代为权威单元格,仅保留作叙述背景):
HTTP:
git ls-remote http://host/repo.git
git clone http://host/repo.git
git fetch
git -c protocol.version=2 fetch
git push HEAD:refs/heads/<tmp> → 期望新建 refs/cl/*,refs/heads/* 不变(`MEGA2_GIT_SMOKE_PUSH=1`)
git push --delete origin refs/cl/<id>(清理;`MEGA2_GIT_SMOKE_PUSH=1`)
git push origin refs/tags/<name> → 期望失败(Monorepo;`MEGA2_GIT_SMOKE_PUSH=1`)
git clone --depth=1
git -c protocol.version=2 ls-remote
git -c protocol.version=2 clone --filter=blob:none
SSH:
git ls-remote ssh://user@host:port/repo.git
git clone ssh://user@host:port/repo.git
git clone --depth=1 ssh://user@host:port/repo.git
git -c protocol.version=2 ls-remote ssh://user@host:port/repo.git
git -c protocol.version=2 clone --filter=blob:none ssh://user@host:port/repo.git
git fetch
git -c protocol.version=2 fetch
git push HEAD:refs/heads/<tmp> → CL(同上;`MEGA2_GIT_SMOKE_PUSH=1`)
git push origin refs/tags/<name> → 期望失败(`MEGA2_GIT_SMOKE_PUSH=1`)
LFS:
git lfs install
git lfs track
git push with LFS object(`MEGA2_GIT_SMOKE_LFS=1` + `MEGA2_GIT_SMOKE_PUSH=1` 时启用)
git clone with LFS object(`MEGA2_GIT_SMOKE_LFS=1` + `MEGA2_GIT_SMOKE_PUSH=1` 时启用)
git lfs locks(`MEGA2_GIT_SMOKE_LFS=1` + `MEGA2_GIT_SMOKE_PUSH=1` 时启用,只读 list)
每个用例记录:
- Git 客户端版本。
- transport:HTTP 或 SSH。
- repo 类型:
ImportRepo或Monorepo。 - auth 类型:anonymous、Bearer、Basic token、SSH key。
- 预期状态码或 SSH exit status。
- server log 中是否有 panic、敏感信息或 malformed pkt-line。
验收标准:
- 当前已支持能力有明确 passing/failing 表。
- 每个后续阶段都能复用该矩阵防止回归。
目标:消除协议入口上的 panic,让非法客户端输入返回可诊断错误。
工作项:
info/refsquery 解析改为Result。- 缺失、重复、额外参数或非法
service返回 400。 - SSH exec command 解析改为显式 parser。
- 非法 SSH command 返回 channel failure,不默认 upload-pack。
read_pkt_line改为返回Result。- 所有协议二进制 payload 按 bytes 处理,不经过 UTF-8 String。
验收标准:
- malformed HTTP query 不 panic。
- malformed SSH exec 不 panic。
- malformed pkt-line 不 panic。
- Git 客户端收到明确失败,而不是连接被异常关闭。
目标:用协议边界替代 PACK magic 搜索。
工作项:
- 已完成首批:receive-pack 先读取 command list 到 flush-pkt。
- 已完成首批:flush-pkt 后剩余 bytes 作为 pack stream。
- 后续:实现 streaming pkt-line reader,避免完整 body / channel 数据缓冲。
- ✅ 支持无 pack 的 delete-only 和 pack-less create/update:flush-pkt 后剩余为空时跳过
unpack_stream/receiver_handler;非空剩余必须仍以PACK开头。pack-less 非删除命令要求目标 object 已存在(branch → commit,tag → 任意已存 object),否则ng … target object {id} not found。 - ✅ 空命令列表校验:splitter 在 flush-pkt 前无 command 时返回
ProtocolError::InvalidInput,避免无命令请求进入 ref 处理。 - 已完成首批:HTTP 和 SSH receive-pack 共用同一 parser。
- ✅ FC-08:monorepo 不允许的 tag 与
refs/heads/main删除在持久化前ng;失败 tag 不再二次update_refs;仅至少一个ok的 branch 命令才finalize_receive_pack(tag-only 不 finalize);多余非删除 branch 按命令ng(第一条仍可 finalize),而不是整包拒绝。CL 删除(delete-only)仍允许。 - ✅ FC-09:receive-pack 删除按 advertised old id 条件删除;CAS 未命中时不删除已被并发更新的 ref,报告
moved since advertisement。
验收标准:
- 已覆盖:command payload / capability 中出现
PACK不误切分。 - 待覆盖:
PACK跨 chunk 不影响 push(需要 streaming parser 或真实 Git CLI 矩阵)。 - ✅
git push --delete可正常返回 report-status(delete-only 跳过 unpack,由is_delete_only_push_detects_pure_delete_vs_mixed锁定)。 - ✅ pack-less 非删除请求被 splitter 接受(由
split_receive_pack_request_accepts_pack_less_non_delete锁定)。 - ✅ 空命令列表返回协议错误(由
split_receive_pack_request_rejects_empty_command_list锁定)。 - malformed command list 返回协议错误。
目标:只 advertise 真正支持且有测试的 capability。
工作项:
- 建立 capability truth table。
- 移除或补齐
atomic、report-status-v2、quiet、include-tag、delete-refs等能力。 - 明确
ofs-delta、no-thin、side-band-64k的 encode/decode 测试。(✅ 2026-09-16:no-thin由 advertise 断言 + RCV-01 端到端回归覆盖,见上表与 truth table) - ✅ 对 SHA-1 object format 做显式策略:SHA-1 为协议默认格式,SHA-1-only server 不 advertise
object-format(协议允许 SHA-1 默认时省略;mega2 策略对 SHA-1-only repo 不 advertise),由advertised_capabilities_keep_sha1_default_and_do_not_advertise_object_format锁定。
验收标准:
- advertise 的每个 capability 都有 parse/act-on/test 证据。
- 标准 Git 客户端不会因为误导性 capability 进入未实现路径。
| Capability | Advertised? | Parsed? | Acted On? | Tested? | 说明 |
|---|---|---|---|---|---|
report-status |
✅ receive-pack | ✅ | ✅ 生成 unpack ok + per-ref status |
✅ receive_pack_advertises_only_supported_baseline_capabilities |
基础 report-status v1 语义 |
side-band-64k |
✅ both | ✅ | ✅ build_side_band_format |
✅ build_side_band_format_wraps_payload_when_side_band_64k_enabled + build_side_band_format_passthrough_when_capability_absent |
pack data 通过 side-band 传输 |
ofs-delta |
✅ both | ✅ | ✅ pack decode 委托 git-internal(支持 offset delta 编解码,见 git-internal::internal::pack::decode) |
✅ advertise/parse:parse_capabilities_recognizes_ofs_delta + advertise 断言(pack decode 由 git-internal 自测) |
OFS_DELTA pack 编解码由 git-internal 实现并自测;mega2 侧仅覆盖 advertise/parse |
multi_ack_detailed |
✅ upload-pack | ✅ | ✅ negotiation ACK 逻辑 | ✅ parse_capabilities 单测 |
upload-pack negotiation |
no-done |
✅ upload-pack | ✅ | ✅ 与 multi_ack_detailed 联动 | ✅ negotiation 单测 | 允许在 multi_ack_detailed 下提前发 pack |
shallow |
✅ upload-pack | ✅ | ✅ deepen / deepen-relative 生成 shallow pack 和 shallow response;ViewRepo(P0)不覆写 supports_shallow_fetch,HTTP v0/v2 depth 返回 400;SSH 同样拒绝但写裸文本 error: …(DEFER-HP-17) |
✅ capability parse/advertise 单测 + shallow traversal 单测 | protocol v1 shallow clone 基础语义 |
ls-refs |
✅ protocol v2 | ✅ | ✅ 处理 ref-prefix、symrefs、peel |
✅ v2 capability / command parse 单测 | protocol v2 refs discovery |
fetch=shallow filter |
✅ protocol v2 | ✅ | ✅ v2 fetch 支持 want/have/done、deepen、filter blob:none;ViewRepo(P0)不覆写 supports_filtered_fetch,HTTP v2 depth/filter 返回 400,SSH 同样拒绝但写裸文本 error: …(DEFER-HP-17);v0 不宣告 filter |
✅ v2 command parse 单测 + pack generation gates + capability honesty 单测 | v2 fetch;filter blob:none 只发送 commit/tree objects;RepoHandler::supports_shallow_fetch/supports_filtered_fetch 门控 |
agent=mega/0.1.0 |
✅ both | ❌ | ❌ | ❌ | 信息性,不影响协议行为 |
atomic |
❌ 已移除 | ✅ | ❌ | N/A | 未实现原子 ref 更新,已从 advertise 移除 |
report-status-v2 |
❌ 已移除 | ✅ | ❌ | N/A | 未实现 v2 语义,已从 advertise 移除 |
delete-refs |
✅ 已声明 | ✅ HTTP CL delete + Monorepo tag-reject smoke | ❌ | N/A | HTTP smoke 已覆盖 CL delete;Monorepo 禁止 Git-client Tag;SSH delete 矩阵仍未补齐 |
quiet |
❌ 已移除 | ❌ | ❌ | N/A | 未实现 progress 抑制,已从 advertise 移除 |
no-thin |
✅ receive-pack(2026-09-16 重新 advertise) | ❌(客户端侧语义,服务端无需 parse) | ✅ 依赖客户端不发送 thin pack;服务端解码器对残余 thin/malformed pack fail-closed 并经 unpack_stream 转为 typed 错误(2026-09-16) |
✅ receive_pack_advertises_only_supported_baseline_capabilities + RCV-01 端到端回归(默认 delta push) |
移除期间 thin pack 触发解码 panic/断连(RCV-01);重 advertise 以匹配解码器 fail-closed 契约 |
include-tag |
❌ 已移除 (upload) | ❌ | ❌ | N/A | pack 生成未按 include-tag 语义验证,已从 advertise 移除 |
server-option |
❌ 已移除 (v2) | ✅ | ❌ | ✅ v2_capability_advertisement_does_not_advertise_server_option |
v2 parsed capabilities 未被 inspect/act-on,advertise 会误导客户端;2026-06-30 从 v2 advertise 移除 |
object-format |
❌ protocol v1;✅ protocol v2 object-format=sha1 |
✅ v2 capability advertisement | N/A | ✅ v1 advertised_capabilities_keep_sha1_default_and_do_not_advertise_object_format + v2 capability 单测 |
v1 保持 SHA-1 默认不 advertise;v2 capability list 显式声明 sha1 |
残余风险:ofs-delta 的 pack 编解码由 git-internal crate 实现并自测,mega2 侧已覆盖 advertise/parse;如需端到端 OFS_DELTA pack 矩阵可在 git-internal 侧补足。
目标:HTTP 和 SSH 使用同一协议认证语义。
工作项:
- ✅ 定义协议认证上下文:
SmartSession.auth: AuthContext(username+authenticated_user: PushUserInfo),HTTP 与 SSH 共用。 - ✅ HTTP Bearer / Basic token 认证填充同一 context(
git_receive_pack_auth→SmartSession::set_authenticated_user)。 - ✅ SSH publickey 认证成功后保存 username(
SshServer.authenticated_user),exec 阶段传入SmartSession(set_authenticated_user),commit binding 不再匿名。 - ✅ 明确 upload-pack 是否允许匿名访问:
check_upload_pack_access(git_config, auth)按git.anonymous_access(默认true,向后兼容)放行匿名 clone/fetch,关闭时无 token 返回ProtocolError::Forbidden;HTTPinfo/refsupload 分支(http.rs:53)、git_upload_pack(http.rs:217)与 SSH(ssh.rs:149)共用,mod.rs3 个单测锁定 allow/deny/authenticated。 - 🔶 receive-pack 检查 repo/path 级 push 权限:
check_push_permission(state, auth, repo_path)未认证(无username)直接Forbidden,已认证时对Repository(repo_path)走 CedarpushRepo授权(state.entity_store非空时按策略裁决,为空则放行);HTTP receive-pack 两处(http.rs:64/355)与 SSH(ssh.rs:140)均在 unpack 前调用。更细粒度的 repo/path ACL 与基于策略的 push-deny 协议层单测待后续。 - ✅ commit binding 使用同一 authenticated actor(
bind_commit_to_user读取auth.authenticated_user,HTTP/SSH 路径统一)。
验收标准:
- ✅ HTTP push 和 SSH push 都能绑定到正确用户。
- 🔶 private repo fetch 策略明确且有测试:
check_upload_pack_access的匿名/关闭策略已有 3 个单测;anonymous_access=false的端到端矩阵待补。 - 🔶 未授权(未认证)push 返回
Forbidden,不进入 unpack(check_push_permission在 unpack 前拒绝无 token 请求);基于策略的 push-deny 协议层单测待后续。
目标:提高 SSH 多 channel 和 LFS 客户端兼容性。
工作项:
- 引入
GitSshChannelState,按ChannelId保存状态。 channel_eof只处理当前 channel。- ✅
git-lfs-transfer通过 SSH stderr extended-data 返回规范 unsupported 错误,并通过 channel failure 触发客户端 fallback。 - ✅
git-lfs-authenticate/git-lfs-transfer已校验 upload/download operation;git-lfs-authenticate仍返回同一 HTTP LFS endpoint,后续如需按 operation 拆分 header/URL 再补。 - ✅ LFS HTTP endpoint 已绑定认证上下文与 repo path。HTTP LFS 端点原先完全匿名(未套
cedar_guard)。认证模型以 batch 端点为授权闸门(src/api/router/lfs_router.rs):objects/batch按operation分流——download为读、upload为写。形态分流(plan-20260909 / ADR-LF-01):push_policy=review(省略push_auth)下,读遵循git.anonymous_access(默认true,与 upload-pack 一致),写要求有效 mono access token(Bearer 或 Basic 密码位,经UserStorage);push_policy=trunk下写/读对齐git.push_auth——none时读写均可匿名(与匿名 receive-pack 同级网络前提);token时写要求[[git.push_tokens]]命中且paths覆盖LfsRepoContext(空前缀视为/),读仍可anonymous_access || token。未授权写返回带WWW-Authenticate的401,路径不覆盖返回403。lockcreate/unlock为写、list/verify为读,同样按此策略。纯策略函数lfs_access_allowed(review)、enforce_trunk_lfs_access(trunk)与enforce_lfs_access收敛决策;token_covers_repo/lookup_push_token与 receive-pack 共用。object 传输端点(PUT/GET /objects/{oid})是 batch 下发的能力 URL,不再逐请求鉴权:git-lfs 不会稳定地对 transfer 请求附带凭据(会导致上传PUT在 body 传输中途收到401而 broken pipe)。上传安全性由两层保证:(1)lfs_upload_object(handler)要求对象必须已由uploadbatch 注册 metadata(否则Not found),而uploadbatch 走写鉴权闸门;(2) 内容寻址不可变——lfs_upload_object校验上传字节的sha256等于所声明的 OID 且大小等于注册 size,并对已存在对象跳过写入,因此即便匿名直连PUT也只能(重复)存入恰好哈希到该 OID 的字节,无法篡改或伪造对象。rawGET为匿名(内容寻址能力 URL,绕过anonymous_access);OID 为 sha256 内容哈希,知道它即隐含已有该内容的引用。repo path 绑定:rewrite_lfs_request_uri在剥离/info/lfs前缀前先把 repo 前缀存入LfsRepoContext请求扩展,lock 端点据此把锁行 key 命名空间化为{repo}\u{1f}{ref}(scoped_lock_ref),使不同 repo 下同名 ref 的锁不再共用一行;object 由 OID 内容寻址,天然跨 repo 安全,无需隔离。空 repo(/api/v1/lfs内部挂载)回退到裸 ref key 保持向后兼容。
验收标准:
- ✅ 单 SSH connection 多 channel 不串状态(
SshServer已按ChannelId隔离GitSshChannelState)。 - ✅ Git LFS 客户端能稳定完成 HTTP LFS push/clone(object 传输不逐请求鉴权,避免 transfer
PUT因中途401broken pipe;由 CIgit-protocol-smoke的 LFS round-trip 覆盖)。 - ✅ 未认证的 LFS 写操作(
objects/batch operation=upload、lock create-unlock)返回 401,不再匿名可写;读操作遵循anonymous_access策略(由lfs_access_policy_matrix锁定)。匿名直连 objectPUT因缺少 batch 注册的 metadata 返回Not found;即便针对已注册 OID,也因sha256/size 校验与「已存在则跳过」而无法篡改或伪造。 - ✅ LFS lock 操作不会跨 repo 混淆:锁行 key 按 repo 命名空间化(由
locks_are_namespaced_by_repository锁定);object 内容寻址(OID)天然跨 repo 安全。
目标:提高 clone/fetch 在大仓库和现代 Git 客户端下的兼容性。
工作项:
- ✅ 实现
deepen/ shallow clone 基础语义:upload-pack 解析deepen/deepen-relative,Monorepo::shallow_pack做 depth-limited traversal,并返回shallowpkt-lines。 - ✅ 支持
deepen-since、deepen-not或明确拒绝:当前明确返回ProtocolError::InvalidInput。 - ✅ 评估并实现 protocol v2 的
ls-refs和fetch:HTTP 通过Git-Protocolheader,SSH 通过GIT_PROTOCOLenv request。 - ✅ 评估 partial clone filter:已实现 protocol v2
filter blob:none;tree filters 暂未实现完整语义,后续需按真实 Git CLI 矩阵决定是否扩展。
验收标准:
git clone --depth=1行为正确。- 不支持的 modern feature 有明确错误或 fallback,不 silent misbehave。
- 大仓库 fetch 不需要一次性读取大请求体(仍待 streaming pkt-line reader 完成)。
| 优先级 | 工作 | 原因 |
|---|---|---|
| P0 | 建立真实 Git 客户端兼容性矩阵 | ✅ 已落地并扩展(2026-07-01):scripts/git_protocol_smoke.sh + .github/workflows/git-protocol-smoke.yml CI 自动化回归 gate,覆盖 HTTP read-only 场景(ls-remote/clone/fetch/v2 fetch/shallow/blob:none)、HTTP branch/tag push+delete 以及 HTTP LFS push/clone/pull/locks-list;SSH push/delete 保留为脚本手动 opt-in。最小往返集(clone→push→再 clone + 用例隔离)已进 cargo target bin/tests/integration_git_cli.rs(IT-03,Linux 目标 OS,cargo test -p mega2 --test integration_git_cli);正路径广度矩阵仍以脚本为准,不在 bin/tests/ 重复 |
| P0 | 修复 HTTP query、SSH exec、pkt-line parser 的 panic | 非法客户端输入不能打崩服务 |
| P0 | receive-pack 用 pkt-line flush 分界替代搜索 PACK |
已完成首批;HTTP branch/tag push+delete 已进入 CI;SSH push/delete 仍为手动 opt-in;后续补 streaming parser |
| P1 | capability truth table,移除未实现 advertise | 避免误导 Git 客户端进入未实现语义 |
| P1 | SSH payload 全部按 bytes 发送 | Git 协议是二进制协议,不能假设 UTF-8 |
| P1 | 统一 HTTP/SSH auth context | ✅ 已落地:HTTP/SSH 共用 check_upload_pack_access(匿名策略,可配置)+ check_push_permission(Cedar pushRepo 授权);commit binding 绑定 authenticated actor。更细 repo/path ACL 与 push-deny 协议层单测待后续 |
| P2 | SSH per-channel state | ✅ 已实现(2026-06-28):SshServer 按 ChannelId 维护独立 GitSshChannelState |
| P2 | LFS hybrid response 加固 | 提升 Git LFS 客户端兼容性 |
| P3 | tree filters / promisor remote / streaming upload-pack parser | 进一步优化现代 Git 客户端和大仓库体验;shallow clone、protocol v2、filter blob:none 已完成基础支持 |
在 README 或部署文档中,当前阶段建议明确声明:
- 支持 Git smart HTTP 的基础 clone/fetch/push,以及 protocol v2
ls-refs/fetch。 - 支持 Git SSH 的基础 clone/fetch/push,以及通过
GIT_PROTOCOL=version=2启用 protocol v2ls-refs/fetch。 - 支持 Git LFS HTTP endpoints,以及 SSH
git-lfs-authenticatehybrid 模式。 - 暂不支持 pure SSH LFS transfer。
- 支持 shallow fetch/clone 基础语义(
deepen/deepen-relative);兼容性仍需要真实 Git CLI 矩阵确认。 - 支持 protocol v2 partial clone
filter blob:none;暂不承诺 tree filters 或完整 promisor remote 语义。 - advertise 的 capability 以实现和测试为准,未实现能力不应对外声明。
object-format=blake3(及 servablesha256)是 git-internal / Libra extension,不宣称与标准 Git 客户端互通。
第一批 PR 建议控制在 P0:
- 新增真实 Git CLI smoke test 脚本或集成测试说明。
info/refsquery 解析返回Result,非法输入返回 400。- SSH exec command parser 独立成函数并加单元测试。
read_pkt_line返回Result并覆盖 malformed input。- 已完成首批:receive-pack 按 pkt-line flush 分界,不再搜索
PACK。 - 已完成首批:SSH upload-pack 初始响应删除 UTF-8 转换,payload 按 bytes 写回 channel。
完成这些之后,再开始 capability 收敛、认证统一和 LFS 加固。
check_push_permission 切换到三态 helper(ADR-UN-01):off 短路放行(默认,零影响);shadow 放行但记录 would-deny(event=authz_would_deny 结构化字段);enforce 拒绝无权限 push。资源经 UN-11 归一为根仓库 Repository::"/",根实体缺失 fail-closed。首建 ensure 在 HTTP listener 绑定前完成(start_http)。
SSH 面(UN-03)与 HTTP 面共享同一 AppContext.entity_store 实例(service multi 单进程内四方恒等:context↔storage↔HTTP↔SSH)。独立 service ssh 在命令层对 enforcement != off 拒绝启动(指引改用 service multi 或保持 off);SSH listener 绑定前完成幂等首建。
RepoHandler::check_wants_and_ready(&[String]) 与
RepoHandler::prepare_pack(&[String], &[String]) 默认返回 Ok(()),因此 Monorepo 和
ImportRepo 的协商结果保持不变。前者在 v0/v2 每个带 want 的协商轮、任何 ACK、NAK 或
acknowledgments 之前运行;后者只在确定发包前运行。v0 中 have 非空且没有
multi_ack_detailed 的分支不发包,只运行第一个钩子;对应的设计方法表已按此订正。
钩子失败时不会调用任何 pack 方法。v2 的 ready 轮即使已将 acknowledgments 写入缓冲,
也会丢弃该缓冲并返回错误。ViewUnavailable 的 HTTP 应答是带 Retry-After 的 503;
PackRejected 的 HTTP 应答是 200、application/x-git-upload-pack-result 和一个 ERR
pkt-line。错误字段与完整应答表见 错误文档
和 history-projection 设计 §6.1「错误契约」。视图 URL 的错误产生方和
黑盒覆盖由后续入口与打包卡登记,本节不重复场景覆盖表行。
2026-10-24(MTR-98 自身Claude审查、v0.42.69完整C/D已核):内部发布事实由受控 PACK 与本 stream 已发布 raw 闭包推导,原始字节、取消、schema 归档及可见性边界见 Traces 唯一协议源。封闭事实桥尚未接入 HTTP/SSH;逐提交 checkpoint 历史资格仍待 MTR-101,不能据此放行 wire 发布。
2026-10-25(MTR-101内部实现):逐提交历史校验及受控发布入口已完成真实A4 42例,P2覆盖与正文缺口已补齐;最终候选自身Claude ER05 R2及五门C已PASS,0.42.71已提交推送并发布,main/tag实际D全绿。原A3与ER05 R1按旧输入保留。显式基线、私有witness、错误分类与成本见Traces唯一协议源。HTTP/SSH公开接线仍由后继任务交付。
原候选历史原文:2026-10-25(MTR-101 未验收候选):逐提交历史校验与受控发布入口已在工作区接线,实际边界与待验收状态见 Traces 唯一协议源。当前尚无本卡 A、代码审查或 C/D 通过结论;HTTP/SSH 接线仍由后继任务交付。
russh 的实际锁定版本为 0.64.1,包含 GHSA-j7h2-66j4-ghjf 的公钥请求/签名算法一致性修复,以及 GHSA-4wc5-f2rc-q74m 的 agent 重复 lifetime 约束修复。后者先验证完整约束,再插入身份和创建过期任务;本项目未启用 agent 服务或转发入口。
0.64.0 移除的可选 legacy-ed25519-pkcs8-parser 在旧实际 feature 树中未启用;本次不新增 feature,不改变现有标准 OpenSSH 密钥、用户公钥指纹或 github_sync 密钥持久化接口。测试使用临时密钥和私有传输,负例只有两个短 lifetime 约束,不运行高放大资源耗尽演示。源码/验收/审查/发布与 GitHub 告警终态分开登记于日期计划的 FIX-MTR-11;依赖升级本身不等于远端告警已经关闭。
授权快照、闭包减集、取消和外存语义仅以traces唯一契约及MTR99任务卡为准。A1已通过,自己的R1源码/内存PASS但H0 FAIL正在前滚修订;未发布、HTTP/SSH未接线。磁盘TMPDIR、同步IO及完整闭包成本、stored parser错误分类由任务卡具名P2承接,不在此复制协议规则。