修好「總管可以放行」那道門——它在 Linux(=每個雲端 session)上是焊死的(inkstone/ISEP#90 ④)
三支閘(prod-write-guard/main-and-prod-push-guard/stage-before-prod-guard)
判斷戳記新不新,都寫成這一行:
MT=$(stat -f %m "$STAMP" 2>/dev/null || stat -c %Y "$STAMP" 2>/dev/null || echo 0)
macOS(BSD stat)上 `-f %m` 就是 mtime,對的。
**GNU coreutils 的 `-f` 是「顯示檔案系統資訊」**,而且它一邊回非零、
一邊往 stdout 吐一整段區塊 ⇒ `||` 接上的秒數被那段文字污染
⇒ 下一行的 `case "$NOW$MT" in *[!0-9]*) return 1` 必然命中
⇒ **在 Linux 上那三支閘的戳記永遠不會被接受。**
後果不是少一個便利功能:那三支閘都是「擋下來、但總管看過就能放行」,
而放行那道門在雲端打不開 ⇒ **它們在雲端等於純擋**,
總管照著閘自己印的指示做,做幾次都打不開,閘也不會告訴他門是壞的
(inkstone/InkStoneCo#99 那次「連續四次蓋不出戳記」就是這個形狀)。
· hooks/lib/mtime.sh:先 `-c %Y`(GNU)再 `-f %m`(BSD),**每一步都驗是不是純數字**
——這個 bug 的成因正是「命令失敗了卻還是印了東西」,只看離開碼會再被騙一次。
四支用到的檔各自帶一份 inline fallback:這道門不能因為少一個檔案就再關上一次。
· scripts/gate-ok:把散在各閘訊息裡的七種逃生口收斂成一個名字、一種形狀
(`gate-ok <閘名> [參數]`)。原因是逃生口原本是「臨時湊出來的 Bash 指令」,
而臨時湊的指令沒有穩定形狀可以事先放行——settings.json 的 allow 只能逐條完全比對,
多一個 `&&`、換一個 session id 就落在規則外。它蓋的戳記與閘原本認的完全同一個檔、
同一種語意(單次、綁 repo、綁 session、有效期都沒動),換掉的只有「怎麼蓋」。
測試 hooks/tests/gate-ok.test.sh:16/16。既有的三支測試(29/16/10)不受影響。
拿 main 跑同一份:②⑤(門打得開)紅、⑥⑦⑧(門沒變寬)全綠
⇒ 這支補的正是既有測試從來沒驗過的那半邊。
This commit is contained in:
@@ -48,11 +48,23 @@ except Exception: print("")
|
||||
# **15 分鐘內一條並行的 subagent 把 commit 推上了另一個 repo 的 main**。
|
||||
# ⇒ **多條 subagent 並行時,「時間窗」本身就是漏洞。** 所以改成單次用完即丟。
|
||||
# ⇒ 而且只在**真的要擋的那一刻**才檢查——放在檔頭會被任何一條無關指令把戳記燒掉。
|
||||
# 🔴 戳記的 mtime 一律走 lib/mtime.sh:舊寫法(`stat -f %m || stat -c %Y`)在 Linux 上
|
||||
# **永遠算不出數字**(GNU 的 `-f` 是「檔案系統資訊」,它一邊回非零一邊吐一整段文字,
|
||||
# 於是後面接上的秒數被那段垃圾污染)⇒ 這支閘給總管的逃生口在雲端整個焊死,
|
||||
# 而閘不會告訴他門是壞的(inkstone/ISEP#90 ④,全文見 hooks/lib/mtime.sh)。
|
||||
# lib 不在時就地補一份同順序的定義——這道門不能因為少一個檔案就再關上一次。
|
||||
. "$(dirname "$0")/lib/mtime.sh" 2>/dev/null || file_mtime() {
|
||||
_fm=$(stat -c %Y "$1" 2>/dev/null || true)
|
||||
case "${_fm:-}" in ''|*[!0-9]*) _fm=$(stat -f %m "$1" 2>/dev/null || true) ;; esac
|
||||
case "${_fm:-}" in ''|*[!0-9]*) _fm=0 ;; esac
|
||||
printf '%s' "$_fm"
|
||||
}
|
||||
|
||||
STAMP="/tmp/.prod-write-ok"
|
||||
stamp_ok() {
|
||||
[ -f "$STAMP" ] || return 1
|
||||
NOW=$(date +%s 2>/dev/null || echo 0)
|
||||
MT=$(stat -f %m "$STAMP" 2>/dev/null || stat -c %Y "$STAMP" 2>/dev/null || echo 0)
|
||||
MT=$(file_mtime "$STAMP")
|
||||
case "$NOW$MT" in *[!0-9]*) return 1 ;; esac
|
||||
[ "$NOW" -gt 0 ] && [ "$MT" -gt 0 ] || return 1
|
||||
[ $((NOW - MT)) -lt 900 ] || return 1
|
||||
|
||||
Reference in New Issue
Block a user