Repository navigation
[REQ-128][CODE] 将 package compatibility 单一权威接入 Catalog、详情与安装预检 #702
Description
⚠️ 本期范围裁决(2026-07-30,owner)—— 优先于下方原文与基线REQ-128 分四相,本期只做 Phase 1,只支持单组件 package(无 Bundle)。裁决见
alpha-work#49。一、上游已交付,本票 pin 它们
产物 位置 host contract( #694)alpha-code@55890367,packages/ui-mac/src/shared/host-extension-package-contract/,aggregate SHAc3c53e05…producer artifact( alpha-web#95/#97)alpha-web@b7174810,contracts/extension-package/artifact/,aggregate SHAae9f43cc2a7cf279ff06d2846ff45f39cbb0fdd2fd0c4c5d91718968692e4887secret prerequisite( #696)alpha-code@77b5554e,shared/package-secret-prerequisite.tsPhase 1 契约闭包:profile =
skill/agent/mcp-local/mcp-remote(无cloud);
mcp-remote的auth枚举不含oauth/alpha-connection;
capability 词表只有alpha.secret-prerequisite.v1。二、本票被删除的范围(不实现,不写它们的测试)
- Development plan 第 4 条的「同 ID package shadow legacy」与「binding mismatch 不 fallback」
—— 本期不做 legacy projection,因此不存在同 ID legacy 对偶,这两条无对象。
保留:malformed package 本身被拒;连 prelude 都无法安全解码时拒整个新快照并回 LKG。- Acceptance 里
catalog-package-legacy-compat.test.ts的 v0.1.0–v0.1.2 oracle 与
shadow/no-fallback 半场。该文件已由#694交付,现在测的是旧壳同级键容忍
与entries[]非空,本票沿用它、不要改回 oracle。- safe view 里的
skippedOptional[]与 prerequisite 的optional-disconnected
—— 单组件 package 没有 optional child;optional-disconnected属 Alpha Connection(#704,Phase 2)。
Phase 1 的 prerequisite 状态只需ready | required-action。
不要为将来保留这两个字段的插槽。三、
alpha.secret-prerequisite.v1的兑现在本票下游
#696交付的shared/package-secret-prerequisite.ts目前零生产调用者 ——
运行期入口链由本票(evaluator 接线)与#713(admission)交付。
本票负责让 evaluator 真的消费它做 prerequisite 判定;
端到端兑现证据由#713收尾时给出,本票不声称已闭合。四、从前三票两轮审计学到的、必须带进本票的四条
- artifact SHA 门是字节漂移门,不是语义门。
#694R1 实测:把 URL 的 HTTPS/凭证/canonical
判断整个禁用后重新生成 artifact,SHA--check全绿。本票的 consumer drift gate 同理 ——
必须另有直接断言语义的负向用例。- 闸门要测我们真走的那条路。
#696R2 实测:canary 闸靠把entry.source改成"alpha"才够得着
分支,而真实 catalog 里 8 条 MCP 一条 alpha 源都没有 ⇒ 每次真实首装走的是未覆盖的分支。
写任何闸门前先问:这条路,走我们自己的 catalog 和 runbook,到得了吗?- 条件门的判据不能与被校验对象同源。
alpha-web#95R1 实测:pin 校验闸的 skip 判据
就是被校验的 pin 本身 ⇒ 伪造一套自洽的假 pin,闸门自己关掉并通过。
本票 vendor#97artifact 时会遇到同一形态 —— 取不到就必须红,不能跳过。- 源码文本闸门挡不住组装点。
#696R1 实测:零回显闸读 7 个硬编码源文件,
而 preload result 的真实组装点不在清单里 ⇒ 两个绕过全绿。断言返回值,不要断言源码文本。五、反过度工程(owner 直令)
必须在当前框架下开发。
remote-catalog.ts/catalog-channels.ts的签名、信任、快照集一致性、
密钥轮换/吊销、LKG 已完备,不要动它们。不新建通用框架 / 抽象层 / registry 引擎;
不引入新依赖;不为 Phase 2/3/4 预留插槽、空接口、TODO 钩子;不做预防性抽象;
发现超范围缺陷写回票,不顺手修。
Covers
alpha-work#49 AC3/AC4/AC7:把 host contract 与 web producer corpus 接到
Catalog refresh、browse、detail 与 install preflight,建立 main-owned 单一兼容权威。
Solution baseline
REQ-128 accepted baseline
§2.3、§2.5。
Ground truth and boundary
- 主要落点:
packages/alpha-contracts-consumer/**:pinalpha-web#97artifact。packages/ui-mac/src/main/remote-catalog.tspackages/ui-mac/src/main/catalog-channels.ts- 新
packages/ui-mac/src/main/package-installability.ts - preload/shared safe-view types 与 production wiring tests。
- renderer 只接
CatalogPackageViewV1,不接 execution payload、asset URL、config 或
secret target。
Development plan
- vendor docs: S18 开批 —— REQ-022~038 全量清扫批(冲突矩阵 + 拍板落档) #97 schema/vectors/profile rules,锁 commit + SHA,接现有 consumer drift gate。
- 实现唯一
evaluatePackageForHost():验 shallow header/binding → profile/capability →
payload fetch/strict decode → safe projection。 - 冻结 safe-view union:
- verdict
compatible | update-required | blocked - main-owned action/reasonCode
skippedOptional[]- prerequisite
ready | required-action | optional-disconnected
- verdict
- Catalog refresh、browse、detail 与 install preflight全部调用同一函数;同 ID package
shadow legacy,malformed/binding mismatch 不 fallback,无法解 prelude 回 LKG。 - install IPC 只收 catalogId/scope/attempt/grants;main 重取已签 snapshot并重判。
Acceptance and named gates
package-installability.wiring.test.ts:四条生产入口同源,renderer tamper 无效。catalog-package-legacy-compat.test.ts:v0.1.0–v0.1.2 oracle、shadow/no-fallback/LKG。- unknown profile/capability 对 payload fetch/decoder/secret/OAuth/planner 调用数为零。
- safe-view reason/action exhaustive;远程文案不能决定按钮或安全 verdict。
Dependencies
Blocked by alpha-code#694 和 alpha-web#97。
Out of scope
认证执行、transaction、renderer 页面实现、动态 decoder、provider-specific UI。
Exit condition
Merged PR + pinned artifact + production wiring tests + canonical docs impact handled。
Activity
jinjunnn commentedon Jul 30, 2026
从 #694 R1 审计转记的一条
#694交付的是纯 decoder + 注入式 effects,其 synthetic decoder 先 fetch 全部字节、再比对
payloadRef.bytes。审计判定这属生产接线问题,不该在契约票拦,转到本票。要求:本票做生产 fetch 接线时,在读取字节前就用
payloadRef.bytes设上界,恶意/故障服务器不得靠无界响应体拖垮 main。请在本票的 named gate 里加一条可执行断言
(喂一个声称 1KB、实际持续吐字节的响应,证明读取在上界处中止且零落盘)。
[#696][CODE] secret prerequisite 消费 host Envelope + 删除 renderer 明文回显 (#…
jinjunnn commentedon Jul 31, 2026
跨模型对抗审计记录:R1 + R2(2026-07-31)
M 级预算 ≤2,已用满。PR #728 squash 合并为
691f5a57。特殊情况:实现方 codex 两次被外部杀在自检阶段(都不是看门狗),没留下自检报告 ——
无第零问检查、无 OUT-OF-SCOPE、无"拒绝的扩张"。代码之外的一切事实由编排者逐条复核,
并在派审时明确告知审计方"平时由实现方自证的部分这次没人做过"。
R1:52 处 mutation,30 处零红存活
catalogId也全绿(单夹具盲区,与#696canary 同构)fetchPackagePayload零覆盖、preflight 值校验零覆盖)#713—— 今天均不可达,#713让它们上路编排者自己核实过的(未采信实现方,因其无自证):四条入口结构、safe view 形状
(零 payload/URL/config/secret target)、vendored artifact 逐字节与 pin、漂移门是真语义门、
闸门登记簿、typecheck 与 base 一致、north-star。
R2:R1 四条全 FIXED,又开出 2 Major
{verdict:"blocked"}近乎恒真(preflight 每条失败分支都是 blocked)⇒ 把loadVerifiedCatalog换成恒返回{source:"none"}的常量、摘掉「main 重取已签事实重判」这一核心反篡改性质,仍全绿reason)refreshChannelCatalog第四参默认值是 fail-open 的() => ({ok:true})⇒ 坏候选被写成新 LKG ⇒ 健康 LKG 丢失、断网后仍空白,违反remote-catalog.ts抬头的「永不空白」全部修复只动测试与夹具,零生产代码改动,每条均反向验证变红。
两处过程记录(都是「假闸门」形态,留给后来人)
一、编排者的判断被审计证伪。 我判「候选消费门与
:225的最终评估互为冗余、属纵深防御」,并在派 R2 时写明"能构造出行为不同的输入我就是错的"。审计给了反例:
健康 LKG + 一份签名合法但
packages[]坏掉的候选 —— 门在时挡在 coherent-set 落盘之前、健康 LKG 继续服务;门不在时坏候选被写成新 LKG,
:225只能把整份结果打成none,健康 LKG 就此丢失。它是承重闸。 审计同时纠正:用例其实已存在于
catalog-channels.test.ts,没被守住的是生产调用点 —— 又是 B1 的形状。二、编排者写的第一版 Major-2 用例本身就是假闸门。 它在 HEAD 与 NEW-D 变异下都绿 ——
因为
remote-catalog.test.ts里channelBody的缺省sequence恒为 5,与 seed 那份相同 ⇒候选先被 R5 replay 规则拒掉、根本走不到消费门。修法是
docOver:{sequence:6},并加一条
error断言把「绿的理由必须是消费门」钉死 —— 否则将来任何让候选提前被别的规则拒掉的改动,都会把它悄悄退化回假闸门。审计方亦坦承其原 probe 是手搓 harness 用了
++seq,"撞对的不是想对的"。
一条如实留着的未解观察
编排者接手时全量跑出现过 1 次失败(3287/1),未保存输出、叫不出它的名字;
之后编排者跑 9 次、审计跑 31 次均未复现。不写它是"基线既有",也不写是本票引入 ——
两者都没核实。
已知不修(留痕)
refreshChannelCatalog的consumeCatalog默认值是 fail-open 缺省 —— 想改必填,但本仓 tsconfig 排除
*.test.ts、bun 又剥类型,45 处现有调用不会红,类型层收口是假绿;Major-2 的行为测试已让唯一的生产调用点受守。preload 的
packageDetail桥两侧同删不红(cases 文件 mock 掉 electron、不覆盖 preload 面),且今天 renderer 侧无消费方,
属 owner 分期裁决内(UI 归后续),非缺陷。
[#695][CODE] 通用详情页呈现 package 兼容、组件与 prerequisite (#730)
[#713][CODE] package admission:digest 绑定、重取重验与端到端 secret 兑现 (#734)