identity-backup and private-pages asked BSD's stat -f %Lp first and fell back to GNU's stat -c %a. On Linux, stat -f is file system status, which succeeds, so the assertion compared a page of file system details with 600 or 700 and failed on any Linux host, not only as root. lib.sh's mode asks GNU's first, which BSD's stat refuses, then BSD's.
- commit
- 982bfb4699bdd9951235fa500c394268f13b8e83
- parent
- 18f6a757c8e0e2c96166361830122eb3ea9973a7
- author
- cat <admin@dev.site>
- ci
- ✓ passed in 73s, signed by cat
- kind
- fix risk score 0.7 of 3, Jev's estimate
- review
- #5 Pass the scenarios in the container, as root
ci attestation
forge-attestation 1 type ci commit 982bfb4699bdd9951235fa500c394268f13b8e83 tree dfa384d7053b390bf7e52615160f876b7cb4a00f script .forge/ci e6f038ae810b87f90a4be115a762a9c91dd76a01 result pass exit 0 started 2026-10-18T23:00:06Z duration 73s runner (not shown here; refs/notes/ci has it) system Darwin 25.5.0 arm64 env host log sha256:149b42165d732e16f4c4d6c4da1e853b30bb7536facfa9df5d85fb11f0a297fa 240 lines |remote: review #4: /dami/greet/reviews/4/ |pushed wip/i18n |5638b3c running .forge/ci: greet.sh: say what it is | | sh: /bin/sh | | ok greet |5638b3c pass in 0s, signed |pushed main |remote: review #4: /dami/greet/reviews/4/ |pushed wip/i18n |6fa5e69 running .forge/ci: wave at the world | | sh: /bin/sh | | FAIL greet : got 'hello, world o/', want 'hello, world' |6fa5e69 fail in 1s, signed |forge: 1 commit(s) did not pass |remote: review #6: /dami/greet/reviews/6/ |pushed ana/wave |539e861 running .forge/ci: update the test for the wave | | sh: /bin/sh | | ok greet |539e861 pass in 0s, signed |remote: review #6: /dami/greet/reviews/6/ |pushed ana/wave |warning: You appear to have cloned an empty repository. |site home: deployed 9aee97a -> /sites/ana/dotfiles/home/ |created ana/notes |remote: review #1: /ana/notes/reviews/1/ |pushed ana/todo |landing #1 A todo list: ana/todo -> main |82a886a running .forge/ci: web, server and Python versions of greet | | sh: /bin/sh | | ok greet |82a886a pass in 0s, signed |pushed main |7555125 running .forge/ci: messages: notes for the later regions | | sh: /bin/sh | | ok greet |7555125 pass in 0s, signed |remote: review #7: /dami/greet/reviews/7/ |pushed dami/regions |created dami/forge |warning: You appear to have cloned an empty repository. |site guide: deployed 9091ed7 -> /sites/dami/forge/guide/ |(node:28310) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time |(Use `node --trace-warnings ...` to show where the warning was created) |built ana/dotfiles in 0s -> /Users/dami/Library/Caches/forge/ci/35f7a65d0235/demo/root/.forge/www |(node:28473) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time |(Use `node --trace-warnings ...` to show where the warning was created) |built ana/notes in 1s -> /Users/dami/Library/Caches/forge/ci/35f7a65d0235/demo/root/.forge/www |(node:28611) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time |(Use `node --trace-warnings ...` to show where the warning was created) |built dami/forge in 0s -> /Users/dami/Library/Caches/forge/ci/35f7a65d0235/demo/root/.forge/www |(node:28741) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time |(Use `node --trace-warnings ...` to show where the warning was created) |built dami/greet in 2s -> /Users/dami/Library/Caches/forge/ci/35f7a65d0235/demo/root/.forge/www |(node:29405) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time |(Use `node --trace-warnings ...` to show where the warning was created) |built - in 0s -> /Users/dami/Library/Caches/forge/ci/35f7a65d0235/demo/root/.forge/www |226 of 226 pages render the same without 11ty |guide: 4 files, links ok |ok
Signature: good, cat
| M | test/ | 4 | ++++ |
| M | test/ | 2 | +- |
| M | test/ | 2 | +- |
@@ -188,6 +188,10 @@ site_commit() {
188188 t=$(printf '100644 blob %s\tindex.html\n' "$b" | git mktree) && git commit-tree -m "site: $2" "$t")189189 }190190 191+# mode path: its permission bits, in octal (GNU stat first: BSD's -f is192+# GNU's file system status, which succeeds).193+mode() { stat -c %a "$1" 2>/dev/null || stat -f %Lp "$1"; }194+191195 t_sha256() { { sha256sum "$1" 2>/dev/null || shasum -a 256 "$1"; } | cut -d' ' -f1; }192196 193197 # release_sign dir key owner/repo tag [namespace]: dir/SHA256SUMS.sig, a@@ -29,7 +29,7 @@ missing "$st/.forge/identity.db-shm"
2929 missing "$st/.forge/.identity.db-litestream"3030 missing "$st/.forge/private"3131 missing "$FORGE_ROOT/.forge/identity.snapshot.tmp"32-eq "$(stat -f %Lp "$st/.forge/identity.db" 2>/dev/null || stat -c %a "$st/.forge/identity.db")" 60032+eq "$(mode "$st/.forge/identity.db")" 6003333 ok node "$T_HOME/lib/identity.ts" check "$st/.forge/identity.db"3434 3535 r=$T/restored@@ -35,7 +35,7 @@ has "$p/dami/secret/index.html" 'HTTPS takes a token: <code>ssh git@forge.test t
3535 lacks "$FORGE_WWW/dami/open/index.html" 'private-mark'3636 eq "$(ls "$p")" dami3737 eq "$(ls "$p/dami")" secret38-eq "$(stat -f %Lp "$FORGE_ROOT/.forge/private" 2>/dev/null || stat -c %a "$FORGE_ROOT/.forge/private")" 70038+eq "$(mode "$FORGE_ROOT/.forge/private")" 7003939 for a in $(grep -rhoE '(href|src)="/assets/[^"]+"' "$p" --include=index.html | sed -E 's/^[a-z]+="//; s/"$//' | sort -u); do4040 exists "$FORGE_WWW$a"4141 done