fix(core,docs): M308 r1 —— 读表工具写错(又一句「文档比代码多」)+ .exe 名字判据空转 + adopt 之后的取值器文档
p2-1 文档:`--check-pinned-keyring` **要私钥**(`do_check_pinned(args.key)`),语义是「Secret 里那把
钥是否已钉住」这条发布前门禁,不是读表工具。`docs/update-trust-anchor.md` 的「当场看一眼」与
`signing-runbook.md` §0 那句「现在 --check-pinned-keyring 绿」(与同文件 §:116 自相矛盾)都换成
`check_signing_ready.py` 的 ① 行(真只读,实测打「就绪 —— 标记之间 1 条:ull-release…」)。
p2-2 判据:`is_launcher_candidate` 的 `|| name.ends_with(".exe")` 此前**删掉也不红**(唯一含 `.exe`
的用例同时给了 0o755)。补 `a_windows_exe_without_the_exec_bit_is_still_the_launcher`
(win-x64 + 归档内 `unlucky-launcher.exe` + MZ + **0644** 能装上),删那半条判据即红。
p2-3 文档:`StagedPackage::size()` / `integrity()` 的注释在 `adopt` 之后不再成立(前者是本体的字节数、
后者是**归档**的摘要),改成「这个文件写出来的字节数」/「为它背书的那份摘要」。
This commit is contained in:
1 parent
af82658d08
commit
06712ff6e9
4 files changed
+45
-9
No files matched your search
@@ -197,6 +197,30 @@ fn a_macos_tar_gz_runs_the_whole_chain() {
|
||||
assert_eq!(std::fs::read(job.dest()).expect("读目标"), MACHO);
|
||||
}
|
||||
|
||||
/// Windows 的名字兜底:归档里的 `unlucky-launcher.exe` 带 **0644**(没有可执行位)也认。
|
||||
///
|
||||
/// 为什么需要这一条:`is_launcher_candidate` 是两条判据取并集(可执行位 **或** `.exe` 名字)。
|
||||
/// 发布矩阵里 Windows 发裸 `.exe`,可「清单给 win-* 挂一个归档」是合法输入,而 tar 里没有 unix
|
||||
/// 权限位、`make_artifacts.py` 也只给启动器打 0o755——名字这条兜底不能是空转的。
|
||||
///
|
||||
/// 抓得住:把 `is_launcher_candidate` 里 `|| name.to_ascii_lowercase().ends_with(".exe")` 删掉,
|
||||
/// 本用例立刻红(归档里一个候选都没有 ⇒ `LauncherMissing`)。
|
||||
#[test]
|
||||
fn a_windows_exe_without_the_exec_bit_is_still_the_launcher() {
|
||||
let stage = "unlucky-launcher_9.9.9_windows_x64";
|
||||
let archive = tar_gz(&[
|
||||
(&format!("{stage}/unlucky-launcher.exe"), PE, 0o644),
|
||||
(&format!("{stage}/LICENSE"), b"license text", 0o644),
|
||||
]);
|
||||
let target = Target::new(OsFamily::Windows, Arch::X64);
|
||||
let (_dir, job) = fixture(target, "portable-zip", &archive);
|
||||
let applied = job
|
||||
.apply(&Version::parse("0.2.2").expect("版本"), Channel::Stable)
|
||||
.expect("应当装上(名字判据兜住没有可执行位的那份)");
|
||||
assert!(matches!(applied, Applied::Installed { .. }));
|
||||
assert_eq!(std::fs::read(job.dest()).expect("读目标"), PE);
|
||||
}
|
||||
|
||||
/// 归档里没有本体(只有随包文本)⇒ `LauncherMissing`。抓得住「只认可执行位」这条判据被放松。
|
||||
#[test]
|
||||
fn an_archive_without_a_launcher_is_refused() {
|
||||
|
||||
@@ -56,13 +56,20 @@ impl StagedPackage {
|
||||
&self.path
|
||||
}
|
||||
|
||||
/// 实际字节数(已与清单核对过,等于清单声明的 `size`)。
|
||||
/// 实际字节数(**这个文件**写出来的字节数)。
|
||||
///
|
||||
/// `stage` 产出的那份就是清单声明的 `size`(双检已核对);M308 起 `unpack` 还会用
|
||||
/// [`Self::adopt`] 造出「从归档里拆出来的本体」那一份,那时它是**本体**的字节数,
|
||||
/// 不是归档的。跨卷复制那一步靠它核对该搬多少字节,所以这个字段必须始终是「本文件的」。
|
||||
#[must_use]
|
||||
pub const fn size(&self) -> u64 {
|
||||
self.size
|
||||
}
|
||||
|
||||
/// 校验用的摘要。
|
||||
/// 为这个文件背书的那份摘要。
|
||||
///
|
||||
/// `stage` 产出的是清单里写的那条摘要(对**下载到的字节**算的);`adopt` 产出的(拆出来的本体)
|
||||
/// 沿用**归档**的摘要——拆出来的字节由「归档过了长度+摘要双检」背书,本模块不为它另算一份。
|
||||
#[must_use]
|
||||
pub fn integrity(&self) -> &Integrity {
|
||||
&self.integrity
|
||||
|
||||
@@ -33,16 +33,20 @@ PinnedKey { key_id: "ull-release", public_key_hex: "1c3687ec…" }
|
||||
## 当场看一眼(只读命令)
|
||||
|
||||
```bash
|
||||
# ① 信任表里有几条(标记之间)
|
||||
python3 packaging/sign_manifest.py --check-pinned-keyring
|
||||
|
||||
# ② 就绪度播报(三行:表非空 / 环境里有钥且同源 / 最近一次发布痕迹)
|
||||
# ① 就绪度播报:第一行就是「标记之间有几条 PinnedKey」,只读、不需要任何私钥
|
||||
python3 packaging/check_signing_ready.py
|
||||
|
||||
# ③ 直接读表
|
||||
# ② 直接读表(最原始的那一眼)
|
||||
sed -n '/PINNED-KEYS/,/PINNED-KEYS/p' crates/core/src/update/trust.rs
|
||||
```
|
||||
|
||||
`check_signing_ready.py` 的 ① 那一行是**读表**的正确入口:它按标记解析本文件、数条目并点名
|
||||
`key_id` 与公钥前缀。它的退出码是**就绪度**(① 表非空 **且** ② 环境里有同源私钥才 exit 0),
|
||||
不是「表读到了没有」——没配 Secret 的机器上它照样打出 ① 那一行,只是整体 exit 1。
|
||||
|
||||
⚠ **别拿 `sign_manifest.py --check-pinned-keyring` 当读表工具**:它要私钥
|
||||
(`ULL_MANIFEST_SIGNING_KEY` 或 `--key <文件>`),语义是「**Secret 里那把钥**是否已钉住」这条
|
||||
**发布前门禁**;没钥时它直接 `error: 没有签名密钥…` + exit 1(M308 r1 实测)。想只读看表就用上面两条。
|
||||
|
||||
`check_signing_ready.py` 的 ① 那一行的判据是「标记之间有几条 `PinnedKey`」,**不是**「表是不是
|
||||
空的」——所以哪天有人把标记之间清空,它会立刻喊未就绪(那句文案里的「空表」说的是那一天)。
|
||||
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
M254 审计当时读到 `crates/core/src/update/trust.rs` 的 `PRODUCTION` 表在 `PINNED-KEYS` 标记之间是
|
||||
**空的**(空表 = `KeyringEmpty` 一律拒装 ⇒ 用户端表现为「更新永远失败」)。**那条读数已作废**:
|
||||
commit `68362e5` 钉入 `ull-release` 之后,正式构建认得这把钥签的清单。下表「今天」一列也随之为
|
||||
历史(现在 `--check-pinned-keyring` 绿,其余两行取决于环境里有没有配 Secret)。已存在的部分(都能用):
|
||||
历史:表**不是**空的了(只读读数见 `python3 packaging/check_signing_ready.py` 的 ① 行,今天打
|
||||
「就绪 —— 标记之间 1 条:ull-release」),其余两行取决于环境里有没有配 Secret。已存在的部分(都能用):
|
||||
|
||||
| 环节 | 在哪 | 今天的状态 |
|
||||
|---|---|---|
|
||||
|
||||
Reference in new issue
Block a user