pi 评审 2026-09-15 §三 给了决定:**开,但拆两条**。理由我采纳并写进注释:
合成的结果会是"看起来覆盖了、其实只覆盖一半"。
## 为什么要这两条(实测实例,不是设想)
写文件的工具**不理会 umask**(umask 022,它建的仍是 0600),而
`deploy/redeploy-plugin.sh` 用 `cp -a "$SRC/."` 打快照 ⇒ **0600 会进生产**。
实测:快照里 `src/paths.mjs`/`src/turn-cwd.mjs` 是 0600、仓库 0644,
而 **`cmp` 五个 same、① 报"逐字节一致"** —— 两头都不报警:
`collectFiles` 只把**内容**做 sha256,`check-deploy-drift` 只在脚本上判可执行位。
## 两条的分工(别合成一条)
- `deploy/check-file-modes.sh` = **政策**:源文件不得比 0644 更严。
**不看快照** ⇒ 能抓"两边都 0600",而一致性那条永远抓不到(两边一致 ⇒ 恒绿)。
- `check-deploy-drift.mjs` 新增 **①b**(`collectModes`/`diffModes`)= **一致性**:
部署副本的权限 = 仓库那一份。抓不到"两边都错"。
## 落地
**政策侧**:新脚本判「已跟踪文件里 group/other 任一读位缺失」。
实测判出 **53 个**(含 `plugins/pi-mail-bridge/package.json`、`src/naming.mjs`、
`client/harmony/.../*.ets`、`docs/GUI-PLAN-HARMONY.md` 等)—— 全部 `chmod 644` 修掉,
现在 exit 0。**区分力实测**:把 `deploy/check-shared-libs.sh` 临时改 0600 ⇒ 判据红并点名它,
恢复后绿;0755 的可执行脚本**不**被判红(有读位,不是"更严")。
★ 也修正了我先前的一处过报:那 53 个里有凭据类命名的文件吗 —— **0 个**(先查了才批量改)。
**一致性侧**:①b 一上线就抓到**真实的**、**先于本次改动**存在的漂移:
`plugins/*-mail-bridge/lib/permission-grants.{js,d.ts}`、`rename-proposal.{js,d.ts}`
在三个宿主的快照里是 **600**、仓库是 **644**(pi 宿主 1 处、dsh 4 处、opencode 2 处)。
⇒ 这条缝**一直存在**,只是此前没有任何判据看着它。
**处理**:不单独 redeploy 去"洗"权限(那要重启 pi 宿主,为权限位重启服务不值得),
**下一次正常部署顺带修好** —— 这是记账,不是新欠账。
①b 现在是**失败**态(真实不一致),所以 `drift` 整表 exit 1;这与"① 全过"并存是对的,
两条量的是不同的东西。
## 自检
给 `collectModes`/`diffModes` 加了 4 条自检(`--self-check`),四条一起写,
因为"能发现差异"单独一条会被一个**恒判"都不同"**的坏实现骗过:
① 权限相同不得误报;② 内容一致但 0600 vs 0644 必须被发现(连数值一起断言);
③ 权限差异不污染 ① 的内容判据;④ 仅一侧存在的文件不算权限漂移(归 ① 的文件集判据)。
★ 其中两条我**第一版写错了**并当场修掉,都记在注释里:
- 用了 `lib/x.mjs` 做样本,而上面 `mk(b,'DIFFERENT')` 已把它改成内容不同
⇒ ③ 红在**内容**上,而它想验的是"权限不污染内容";改用一对独立的内容相同文件。
- 夹具真实创建的是 `lib/x.mjs` 而不是我以为的 `lib/same.mjs`(ENOENT 才发现)。
验证:`--self-check` 全绿;pi 桥 509/509;`check-shared-libs` exit 0;
`check-file-modes.sh` exit 0;`install.sh --check` exit 0。
67 lines
3.2 KiB
Bash
Executable File
67 lines
3.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# 源文件的权限位**政策**:不许比 0644 更严。
|
||
#
|
||
# # 为什么要这条(一个实测出来的实例)
|
||
#
|
||
# 这台机器上写文件的工具**不理会 umask**(umask 是 022,但它建的仍是 0600)。
|
||
# 后果不是"本地难看",而是它会**进生产**:`deploy/redeploy-plugin.sh` 用
|
||
# `cp -a "$SRC/." "$STAGING/"` 打快照,`-a` 保留权限位 ——
|
||
# 于是快照里 `src/paths.mjs`/`src/turn-cwd.mjs` 是 **0600**,而仓库是 0644。
|
||
#
|
||
# 两头都不报警:
|
||
# · `cmp` 只比**内容** ⇒ 报"逐字节相同"(实测就是这样);
|
||
# · `check-deploy-drift.mjs` 只比**内容**、且只在脚本上判**可执行位**(`mode & 0o111`)。
|
||
# ⇒ "线上与仓库不一致"里,**只有权限位这一类**完全没有判据看着。
|
||
#
|
||
# # 与漂移侧那条的分工(pi 评审 2026-09-15 §三 明确要求分开)
|
||
#
|
||
# · **本脚本 = 政策**:源文件不得比 0644 更严。它**不**看快照,
|
||
# 所以"两边都是 0600"这种情况它能抓到,而漂移侧永远抓不到(两边一致 ⇒ 恒绿)。
|
||
# · **漂移侧 = 一致性**:部署副本的权限位 = 仓库那一份。
|
||
# 它抓不到"两边都错"。
|
||
# 两条别合成一条:合成的结果是"看起来覆盖了、其实只覆盖一半"。
|
||
#
|
||
# # 为什么"更严"也算错
|
||
#
|
||
# 这些文件是**源码**,要被构建/测试/部署以不同身份读(`install.sh` 会切身份做可写性判定,
|
||
# 判据里还有以 nobody 跑的分支)。0600 在"跑的人恰好是属主"时不炸,一旦换身份就是
|
||
# EACCES —— 而那串报错看起来是**代码问题**。这条链一路上在消的就是这一类。
|
||
set -uo pipefail
|
||
|
||
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||
cd "$REPO"
|
||
|
||
# 允许的最严权限:0644。比它更严(组/其他读位缺失)即判红。
|
||
# 例外:**可执行**脚本的 0755 不是"更严",它多了执行位、读位齐全,属正常。
|
||
fail=0
|
||
worst=""
|
||
count=0
|
||
while IFS= read -r f; do
|
||
[ -n "$f" ] || continue
|
||
# 只判 git 已跟踪的文件(未跟踪的构建产物不在这条政策范围内)
|
||
git ls-files --error-unmatch "$f" >/dev/null 2>&1 || continue
|
||
[ -f "$f" ] || continue
|
||
mode="$(stat -c '%a' "$f" 2>/dev/null)" || continue
|
||
# 取八进制后三位
|
||
m="${mode: -3}"
|
||
o="${m: -1}" # other 位
|
||
g="${m:1:1}" # group 位
|
||
# other 与 group 都必须有读位(4 及以上);否则这条政策判红
|
||
if [ "$(( o & 4 ))" -eq 0 ] || [ "$(( g & 4 ))" -eq 0 ]; then
|
||
count=$((count + 1))
|
||
[ -z "$worst" ] && worst="$f"
|
||
printf ' [FAIL] 权限过严:%s 是 %s(政策要求不严于 0644)\n' "$f" "$mode" >&2
|
||
fi
|
||
done < <(git ls-files)
|
||
|
||
if [ "$count" -gt 0 ]; then
|
||
printf '\n 共 %d 个源文件比 0644 更严(首个:%s)。\n' "$count" "$worst" >&2
|
||
printf ' 药方:chmod 644 <文件>。原因:写文件的工具不理会 umask,而 `cp -a` 会把这个\n' >&2
|
||
printf ' 权限位带进生产快照,且 `cmp`/漂移判据都看不见它。\n' >&2
|
||
printf ' 这是**政策问题**(源文件应当可被构建/测试/部署以不同身份读),不是代码问题。\n' >&2
|
||
exit 1
|
||
fi
|
||
|
||
printf ' 源文件权限政策:通过(没有任何已跟踪文件比 0644 更严)\n'
|
||
exit 0
|