Skip to content

feat(coordination): 增加跨机许可的受管 CLI 入口 - #136

Merged
Kucell merged 3 commits into
mainfrom
feat/coordination-permit-managed-cli
Nov 1, 2026
Merged

Kucell merged 3 commits into
mainfrom
feat/coordination-permit-managed-cli

Conversation

@Kucell

@Kucell Kucell commented Oct 31, 2026 •

Copy link
Copy Markdown
Owner

背景

跨机许可的库能力此前已在 origin/main(MR !128 / !129 / !132),但没有可调用的受管入口:

  • git show origin/main:bin/cli.js | grep -in permit 零命中;
  • 全仓引用那四个 permit 模块的文件只有模块自身(零调用方);
  • M-044 真机实测(VC-044-013/014/015 全 PASS)靠 acl-sva/probe-ms004-vc.js 直接 require() 产品模块跑通——那是实测探针,不是产品 CLI。

10-29 的契约复审对「加一个五命令 CLI」的裁定是 BLOCKED,列出 5 条未闭合的契约缺口。此后实施者持续推进,把上述缺口的大部分落到代码上,但从未提交——本分支此前零提交,改动只存在于工作区。这正是 M-053 侧产品安全无法解除 BLOCK 的直接原因:能力没有交付,收敛条件「等待 M-044 出具能力交付签认」永远无法满足。

本 MR 补上产品入口与它依赖的编排层。

改动范围

第一批 = CLI 薄层 + 受管会话 + 编排层,共 37 个精确路径(+4043 / -372,另见下方「第二批修复」补入的 6 个路径):

  • CLI:bin/cli.js(挂载 case "permit")、lib/cli/contract.js、lib/commands/permit-managed-cli.js(140 行,零判定逻辑)
  • 许可编排:lib/coordination/permit-{authority-service,batch-session,managed-session,revocation-signing,target-service}.js、cross-machine-permit.js、permit-delivery.js、protected-permit-store.js、protected-pin-store.js
  • 受管会话:lib/governed/managed-caller-{session,supervisor}.js
  • 测试与夹具:tests/coordination/permit-*.test.js(7 个)、tests/governed/{executor-response-auth,managed-caller-facts-fail-closed,managed-caller-session,permit-supervisor-adapter}.test.js、3 个夹具
  • 同步更新:tests/dispatch/phase-zero-source-manifest.json 中 bin/cli.js 的受保护 blob 指纹(pin 随 bin/cli.js 变更同步更新是本仓既有惯例)

明确不在本批范围

27 个 permit-witness-* / permit-legacy-* / permit-sqlite-* 模块、4 个原生包(permit-witness-windows、permit-witness-macos、permit-sqlite-observer、permit-upgrade-linux-guard)及其 C/C++/C# 夹具、permit-witness-validation.yml、local-publish-validate / upgrade / patches 的相关改动。

不交付的理由是验收证据不足:这些包的服务身份、LocalMachine 证书、密钥 ACL 尚无真实 Windows 验收证据(阶段 A 设计稿状态为「设计候选/真实 Windows 验收 BLOCKED,生产关闭」)。须另开 Decision 后单独交付。

安全边界(不可放宽)

  1. 私钥不出内存:不序列化、不进环境变量、不进命令行、不传给子进程、不写文件;issue 只写出签名后的 permit。CLI 层有两道正则断言拒绝私钥材料。
  2. 公钥只从 pin 域取:验签路径只走 retrieveVerificationKey → publicKeyFor,不从签名消息或撤销列表取。
  3. 时钟中毒即拒:不提供绕过 assertDomainNotClockPoisoned 的开关。
  4. 撤销强制:不提供跳过 revokedFingerprints 检查的开关。
  5. deadline 不自算:必须从 reserve() 返回值读回,不用 issued_at + ttl 推导。
  6. 框架通用性:代码、提交说明、分支名不含任何实战项目标识(check-framework-generality PASS)。

验证

  • 全量 616 个测试文件跑完,8 项失败与 6 项超时经逐项串行复跑全部通过或确认为环境所致,无一由本批引入:
    • 4 项为并行资源竞争(单独串行复跑全部通过);
    • 2 项在未改动的 origin/main 基线上同样失败(受保护事务存储限定 Linux 平台);
    • 2 项为磁盘空间耗尽所致。
  • 专项串行通过:permit-authority-admission 99.4s、permit-authority-signing-gate 39.2s、permit-witness-worker-isolation 5.0s、permit-legacy-archive-evidence 77.7s、permit-phase-a-sqlite 18.3s。
  • 门禁:check-framework-generality PASS、check-l3-boundary 0 违规、check-template-parity 3/3 PASS、check-portable-paths 0 违规。
  • 本地安装闭环(local-publish-validate,不 publish 到 npm):干净检出上 EXIT=0,cortex-agent 1.15.7 → 1.16.0,permit 进入契约命令表(62 个命令),无受管会话时 fail-closed 且不创建输出文件。

边界声明

本 MR 不授权、也不主张:

  • 在受保护部署上启用签发(core dump 实测门独立于本 MR);
  • 安装受保护服务、创建服务或计划任务、提权、修改系统目录 ACL;
  • 新建 Windows 账号、切换登录用户、账号权限切换验证;
  • 连接 Windows 执行敏感 UIA 或主动试验;
  • VC-044-013 / 014 / 015 已 PASS——三条断言须在真实受保护部署上实测后方可转 PASS,代码层通过不能替代实测;
  • 「跨机许可交付已完成」;
  • 第二批的提交推送。

M-053 侧产品安全维持 BLOCK、MS-008 维持 PARTIAL,直至本 MR 经独立复核且在真实受保护部署上取得 VC-044-013/014/015 的实测证据。

关联治理记录:.agent/decisions/D-M044-MS004-PERMIT-CLI-SURFACE-DELIVERY-OPEN.json(Owner 裁定 A)、.agent/artifacts/M-044-MS-004-PERMIT-CLI-SURFACE-BATCH1-20261031/


第二批修复:依赖闭包漏提交(commit 1b11a3f5)

第一批的依赖闭包没有完整入库,干净 checkout 下 CI 的 full-test job 失败:

Error: Cannot find module './permit-witness-contract'

受影响的测试文件(8 个):cross-machine-permit、permit-batch-session、
permit-delivery、permit-managed-flow、permit-revocation-signing、
permit-target-service、protected-permit-store、protected-pin-store。

根因(三处,均为交付边界错误,非设计缺陷)

  1. 见证契约缺失:lib/coordination/protected-permit-store.js 新增 34 处 witness 调用
    (canonicalBytes / deriveTransition / createCheckpoint / normalizeTargetState /
    assertCheckpointMatches / LIMITS),却引用了从未提交过的
    lib/coordination/permit-witness-contract.js。
  2. 锁域能力缺失:lib/coordination/protected-pin-store.js 改为以格式 3 的域标记绑定固定
    SQLite 锁 inode,调用 coordination.assertWindowsFilePermissions 与
    coordination.assertAnchorPathIsNotRedirected,但已提交的 protected-store-lock.js
    尚未导出这两个成员。
  3. 测试未随 API 语义更新:protected-pin-store 的 open() / initialize() 语义已分离,
    已提交的配套测试仍以 open() 打开未初始化目录,并缺少三个 fixture
    (protected-pin-store-process.js、protected-pin-store-v1-source.txt、
    protected-pin-store-v2-source.txt)。

复算方法

用相对 require 闭包复算(脚本见
.agent/artifacts/M-044-MS-004-BATCH1-DEP-CLOSURE-20261101/check-dep-closure.js):

  • 基线 d1bfad49:13 项缺失,全部为既有假阳性(require("./x") 指向同目录目录项、
    require("../y") 归一化等解析差异);
  • 8d8c1e12(修复前):14 项,新增缺失恰好 1 个——lib/coordination/permit-witness-contract.js。

修复后再复算,缺失回到基线水平,无新增。

修复内容

补入六个文件,内容与第二批交付清单记录的 SHA-256 逐字节一致,不引入新的实现:

文件 SHA-256
lib/coordination/permit-witness-contract.js 8e35965ba2d79eaca9dad31af9d4c4fcc351da25df3b4f81adc7649e3d81765a
lib/coordination/protected-store-lock.js b028604860523630f7d223b41857521a3091eee09f738f488d2cfebb50b1b1b3
tests/coordination/cross-machine-permit.test.js 8403c7e06c43c54dd50d28eb54027c5601150286b712ee815bd88f5cdb27f53c
tests/coordination/fixtures/protected-pin-store-process.js 1a033b549d8e7a4657e70ac84d246143e09a6e7ba9407875c0b5bdaf1c928b6a
tests/coordination/fixtures/protected-pin-store-v1-source.txt 7e86ff51e7a5179d1feb91d36be5fd8dce5bf0553c3f17336246dfa24aff8f22
tests/coordination/fixtures/protected-pin-store-v2-source.txt 3e63b43a901a3bd5f3223b5f65106121b871b64005d62b5d1294d4a3644c6055

安全边界不变:

  • permit-witness-contract.js 仅依赖 node 内置模块,不触网、不读环境凭据、不做认证或
    授权判定;其头部自述为「候选状态契约与离线编解码,不是见证服务,也不是授权」;
  • protected-store-lock.js 的两个新成员只做锚点路径与 Windows ACL 的可写性检查:祖先链
    遇符号链接即 fail-closed(原先是 break 继续),并按 Windows 原生适配器判定写者集合;
  • 三个 fixture 是测试夹具(一个子进程夹具与两份 legacy 格式源码快照)。

修复后的验证

干净检出(8d8c1e12 + 本次六个文件)上:

  • 先前因缺模块失败的八个测试文件全部通过;
  • 全量 558 个测试文件跑完,554 通过、4 失败;四项为
    governance/github-control-store、governance/git-transaction-store、
    runtime-port/strict-entry、runtime-state/runtime-admission,在未改动的 origin/main
    基线上同样失败
    (createGitTransactionStore 限定 Linux 平台),非本次引入;CI 的 ubuntu
    运行时不受影响;
  • 门禁 check-framework-generality / check:l3 / check:portable-paths / check:parity /
    check:runtime-artifact-location 全部 PASS;提交说明与分支名无实战项目标识。

对第二批边界的影响

上述六个文件原先登记在第二批清单中,现随第一批一并入库。第二批的实际剩余范围因此减少
六个路径
,清单须按此重新核对后再由 Owner 裁定。

CI 状态说明

两个阻塞点均已闭合。 当前状态:28 个 job 全部通过,0 失败。

阻塞点一:full-test 失败(依赖闭包漏提交)—— 已修复

第一批的依赖闭包未完整入库,干净 checkout 下 CI full-test 失败:

Error: Cannot find module './permit-witness-contract'

根因与修复见上方「第二批修复:依赖闭包漏提交」。修复提交 1b11a3f5,
补入六个文件,内容与第二批交付清单记录的 SHA-256 逐字节一致。

阻塞点二:feedback 复审闭包 pin —— 已由独立复核者裁定并更新

canonical-control-offline.yml 的 feedback job 对 277 个文件的「已复审闭包」 逐文件断言
entry.sha === approved.sha。这是该 gate 设计的复审边界,不是功能回归。

实施方不自行更新该 pin——自行修改「必须经独立复审才可变更」的守卫等于自审自过,
正是这个 gate 要防止的事。因此走的是独立复核流程:

轮次 复核对象 裁定 说明
第一轮 8d8c1e12 REVISE 阻断项 B1-1(见证契约未提交)、B1-2(三份 pin-store 夹具未提交)。明确「不得写入 workflow」
第二轮 1b11a3f5 PASS 闭包 274/277 字节一致、3 项变化、mode 差异 0;依赖扫描无新增缺失;两组测试 146/146 与 70/70;无会话门禁五条命令均 exit 3 且零副作用;六个补入文件的安全边界已复核

复核报告:

  • .agent/missions/M-044/evidence/ms004-batch1-closure-independent-review-2026-11-01.md(第一轮,REVISE)
  • .agent/missions/M-044/evidence/ms004-batch1-closure-independent-review-r2-2026-11-01.md(第二轮,PASS)

据此更新的基线(提交 5ea7fdbc):

reviewed     = 1b11a3f55d761c41aa60ca0b4a3ef4485c2f0937
baseline.sha = 26705201071c014805979e9f093fefde4dee99ae

tree SHA 由复核者独立执行 git rev-parse '1b11a3f5^{tree}' 得出,实施方独立复算一致。
canonical-control-offline.yml 不在 277 闭包内,更新这两处值不产生自引用。

剩余边界

CI 全绿不等于部署验收。本 MR 不主张:

  • 在受保护部署上启用签发(core dump 实测门独立于本 MR);
  • 安装受保护服务、创建服务或计划任务、提权、修改系统目录 ACL;
  • 新建 Windows 账号、切换登录用户、账号权限切换验证;
  • 连接 Windows 执行敏感 UIA 或主动试验;
  • VC-044-013 / 014 / 015 已 PASS——三条断言须在真实受保护部署上实测后方可转 PASS,
    代码层通过不能替代实测;
  • 「跨机许可交付已完成」;
  • 第二批的提交推送。

M-053 侧产品安全维持 BLOCK、MS-008 维持 PARTIAL,直至本 MR 经独立复核且在真实受保护部署上
取得 VC-044-013/014/015 的实测证据。

关联治理记录:.agent/decisions/D-M044-MS004-PERMIT-CLI-SURFACE-DELIVERY-OPEN.json(Owner 裁定 A)、
.agent/artifacts/M-044-MS-004-PERMIT-CLI-SURFACE-BATCH1-20261031/、
.agent/artifacts/M-044-MS-004-BATCH1-DEP-CLOSURE-20261101/。

cortex-agent added 3 commits October 31, 2026 22:31
跨机许可的库能力此前已在 origin/main(批次签发与验签、登记型锚点域、
跨机登记与取钥路径),但没有可调用的受管入口:bin/cli.js 里没有任何
permit 派发,引用这些模块的文件只有模块自身,零调用方。既有真机实测
走的是直接 require 产品模块的探针,不是产品 CLI。

本次补上产品入口与它依赖的编排层:

- lib/commands/permit-managed-cli.js:薄适配层,五个子命令
  issue/register/key/verify/revoke,零判定逻辑;直接调用被拒绝,
  必须在已认证的受管会话内经 executor 通道执行。
- lib/coordination/permit-authority-service.js:受保护服务侧的批次密钥
  持有与签发,私钥不落盘、不进参数、不进环境变量、不传给子进程。
- lib/coordination/permit-target-service.js:目标侧事实取自 pin 域,
  不接受命令行断言作为已观测事实。
- lib/coordination/permit-revocation-signing.js:撤销列表以签名信封签发。
- lib/coordination/permit-batch-session.js、permit-managed-session.js:
  批次编排与受管会话接入。
- lib/governed/managed-caller-{session,supervisor}.js:应答方向绑定与
  事实来源 fail-closed 的补强。

安全约束(不可放宽):公钥只从 pin 域取;时钟中毒即拒;撤销强制;
deadline 必须从 reserve() 返回值读回而非自行推导;代码与命令不含任何
实战项目标识。

验证:全量 616 个测试文件跑完,8 项失败与 6 项超时经逐项甄别均非本次
引入——4 项为并行资源竞争(单独串行复跑全部通过),2 项在未改动的
origin/main 基线上同样失败(受保护事务存储限定 Linux 平台),2 项为磁盘
空间耗尽所致。专项串行通过:permit-authority-admission 99.4s、
permit-authority-signing-gate 39.2s、permit-witness-worker-isolation 5.0s、
permit-legacy-archive-evidence 77.7s、permit-phase-a-sqlite 18.3s。
门禁 check-framework-generality、check-l3-boundary、check-template-parity、
check-portable-paths 全部通过。

本批不含原生 witness 包、legacy 迁移与 SQLite 线——它们的真实 Windows
服务身份与证书/密钥 ACL 尚无实测验收证据,须另行评审后单独交付。
本批也不主张任何跨机许可断言在真实受保护部署上成立。

Refs M-044, MS-004
第一批把跨机许可的受管入口交付到产品 CLI,但它的依赖闭包没有
完整入库,干净 checkout 下 CI 的 full-test 因此失败:

- lib/coordination/protected-permit-store.js 新增 34 处 witness 调用
  (canonicalBytes / deriveTransition / createCheckpoint /
  normalizeTargetState / assertCheckpointMatches / LIMITS),却引用了
  从未提交过的 lib/coordination/permit-witness-contract.js。
- lib/coordination/protected-pin-store.js 改为以格式 3 的域标记绑定
  固定 SQLite 锁 inode,调用 coordination.assertWindowsFilePermissions
  与 coordination.assertAnchorPathIsNotRedirected,但已提交的
  protected-store-lock.js 尚未导出这两个成员。
- protected-pin-store 的 open()/initialize() 语义已分离,配套测试仍
  以 open() 打开未初始化目录,并缺少三个 fixture
  (protected-pin-store-process.js、protected-pin-store-v1-source.txt、
  protected-pin-store-v2-source.txt)。

本次按已核对的字节内容补齐上述六个文件。它们与第二批交付清单
记录的 SHA-256 逐字节一致,不引入新的实现,只修复第一批的交付边界。

影响面:

- permit-witness-contract.js 仅依赖 node 内置模块,不触网、不读环境
  凭据、不做认证或授权判定;其头部自述为「候选状态契约与离线编解码,
  不是见证服务,也不是授权」。
- protected-store-lock.js 的两个新成员只做锚点路径与 Windows ACL 的
  可写性检查:祖先链遇符号链接即 fail-closed(原先是 break 继续),
  并按 Windows 原生适配器判定写者集合。
- 三个 fixture 是测试夹具(一个子进程夹具与两份 legacy 格式源码快照)。

安全约束(不可放宽):不新增任何跨机许可断言;不主张任何断言在真实
受保护部署上成立;第一批仍不含原生 witness 包、legacy 迁移与 SQLite
线——它们的真实 Windows 服务身份与证书/密钥 ACL 尚无实测验收证据,
须另行评审后单独交付。

验证:干净检出(8d8c1e12 + 本次六个文件)上,先前因缺模块失败的
八个测试文件全部通过——cross-machine-permit、permit-batch-session、
permit-delivery、permit-managed-flow、permit-revocation-signing、
permit-target-service、protected-permit-store、protected-pin-store。
全量 558 个测试文件跑完,554 通过、4 失败;四项均为
governance/github-control-store、governance/git-transaction-store、
runtime-port/strict-entry、runtime-state/runtime-admission,在未改动的
origin/main 基线上同样失败(createGitTransactionStore 限定 Linux 平台),
非本次引入,CI 的 ubuntu 运行时不受影响。

Refs M-044, MS-004
独立复核者对 1b11a3f 裁定 PASS,
并给出确切的新基线值对:

  reviewed     = 1b11a3f
  baseline.sha = 2670520

tree SHA 由复核者独立执行 git rev-parse '1b11a3f5^{tree}' 得出;实施方
独立复算一致。

复核依据(见 .agent/missions/M-044/evidence/
ms004-batch1-closure-independent-review-r2-2026-11-01.md):

- 277 文件闭包相对旧复审基线 274 项字节一致、3 项不同,mode 差异 0;
  三项变化与上一轮冻结提交字节完全一致。
- 静态相对依赖扫描与 d1bfad4 对照未发现新增缺失;witness 模块已在提交树内,
  protected-permit-store.js 可独立加载。
- 两组指定测试分别 146/146 与 70/70 通过。
- 五个无受管会话子命令均退出 3,permit --help 退出 0,目录无变化。
- 六个补入文件的安全边界已复核。

本 workflow 文件不在 277 文件闭包内,更新这两处值不产生自引用。

Refs M-044, MS-004
@Kucell
Kucell merged commit 1722d17 into main Nov 1, 2026
28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant