fix: normalize Debian payload modes #68
No reviewers
Labels
No labels
attention
blocked
blocker:ci-red
blocker:conflict
blocker:drill-pending
blocker:unrequested
bug
claimed
documentation
enhancement
epic
merge-next
needs-ruling
needs-triage
offsite
post-merge
ready
release
scope:ci
scope:cli
scope:docs
scope:manifests
scope:packaging
stale
state:addressing
state:bots-reviewing
state:building
state:needs-human
No milestone
No project
No assignees
4 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: heavy-duty/stoke#68
Loading…
Reference in a new issue
No description provided.
Delete branch "build/63-normalize-deb-modes"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Refs #63
Summary
Normalize Debian payload permissions independently of the builder umask and cover the real archive modes under hostile and standard umasks.
Worklog
Acceptance criteria
Verification
Round log
Round at
44bbeadfRound passed with no written reply.
fix: normalize Debian payload modesto WIP: fix: normalize Debian payload modes📣 round answered at head
44bbeadff6WIP: fix: normalize Debian payload modesto fix: normalize Debian payload modes🔎 reviewing head
44bbeadff6npm ci && npm testin a detached worktree — 150/150 pass;npm run check:governance— 4 identities, 5 scope rows valid.chmod -R go-w→test/build-deb.test.jsfails on0600/0700archive modes.npm ci,node_modulespresent) atumask 077andumask 022→ payload and control modes identical.dist/untouched bynpm test; no temp dirs left behind on a passing run.scripts/build-deb.sh,test/build-deb.test.js,changelog.d/63.md.🔎 reviewing head
44bbeadff644bbead: diff scoped to exactly the 3 sanctioned paths; build script matches the spec one-liner, L73 and lintian block untouched; changelog fragment matches sibling format44bbeadvia submit-verdict.sh (wrapper-verified). Non-blocking nits noted in the verdict body🔎 reviewing head
44bbeadff6Approve at head
44bbeadff6c882d383b0afa440f2e1d1ffda14b4.Reviewed the whole PR against #63's acceptance criteria in a detached worktree at this head (
npm cifirst — a fresh worktree carries nonode_modules).What I ran
npm test— 150/150 pass.npm run check:governance—4 identities resolved; 5 scope rows valid.chmod -R go-w, left everything else at this head, re-rannode --test test/build-deb.test.js: fails, and fails on the right thing —./usr/lib/stoke/src/atdrwx------and every data file at-rw-------against the expecteddrwxr-xr-x/-rw-r--r--. Restored, test passes again. The assertion is not vacuous: thedeepEqualacross the two umasks catches the divergence and the per-entry loop catches an identical-but-wrong pair, so neither escape route in the test plan is open.npm ci, so the payload it inspects has nonode_modules— the one part of the payload whose incoming modes the build does not control. I ran the real script twice in the worktree, realnpm ci, once underumask 077and once underumask 022, and compareddpkg-deb -c: identical, includingcommander/and.package-lock.json. Every./usr/directory0755, every regular file0644,./usr/lib/stoke/src/cli.js0755. The0700parent directory that made/usr/bin/stokeunreachable is gone.dpkg-deb --ctrl-tarfile | tar -tvalso matches across both umasks (./control0644), so no residual umask path into the artifact.npm testcreates nodist/in the worktree andgit statusis clean after; the copied script relocatesROOTviaBASH_SOURCEexactly as the spec intends. AC 5: thenpmstub isexit 0on a prependedPATH, and the script invokesnpmby name only — no network path left.scripts/build-deb.sh,test/build-deb.test.js,changelog.d/63.md. AC 7:ci / test (pull_request)andlabels / labels (pull_request)are bothsuccesson this SHA.The fix itself is the spec's line, and the L70-71 comment now describes what the code guarantees rather than what
go-wcould not.lintianL99-101 is untouched,|| trueincluded, as the issue requires. The changelog fragment matches its siblings' shape.Refs #63carries no closing keyword before the number anywhere in the body.Could not verify
lintianis not installed on this box, so the build's lint step printedNote: lintian not installed; skipping package lint.in both of my runs. I did not observe thenon-standard-file-permwarnings disappear; I substituted the directdpkg-deb -cmode read, which is the stronger check and the one #63 makes the gate..debor runstokeas a non-root user through/usr/bin/stoke. The unreachability claim is checked at the mode level only.Non-blocking nits (approval does not hang on these)
test/build-deb.test.js:37hardcodesstoke_1.5.0_all.deb. The artifact name comes frompackage.json, which this repo bumps every release (7 bumps so far, most recentlychore: prepare 1.5.0 release). I confirmed the trap by setting the version to1.6.0:npm testfails withdpkg-deb: error: failed to read archive '.../stoke_1.5.0_all.deb'— a mode test failing on an unrelated release-prep commit, with a message that does not name the cause.require(path.join(ROOT, 'package.json')).versionin the path would close it.t.afteronly after bothbuildPackagecalls return, so a failing first build leaks itsmkdtemproot. My mutation run left one/tmp/stoke-build-deb-test-*behind.test/publish-release.test.jsusestry/finallyinside its helper, which does not have this gap.Approve — head
44bbeadreviewed whole against #63's acceptance criteria; every criterion verified by running it, not by reading it.What I ran (worktree at
44bbead, detached throwaway):npm test— 150/150 pass. The first run failed 68 tests withCannot find module 'commander': my fresh worktree had nonode_modules. Afternpm ciall 150 pass; the failures were my environment, not the PR. The tree stayed byte-clean afterward and nodist/was created — the test's temp-ROOT staging (script relocation via BASH_SOURCE,mkdtempunderos.tmpdir(),t.aftercleanup) demonstrably keeps every write inside its temp directory.chmod -R go-wmakesnode --test test/build-deb.test.jsfail on exactly the defect #63 documents —drwx------ ./usr/lib/stoke/src/,-rw-------payload files — while cli.js still reads0755. Restored the fix; the test passes 1/1. The failure case genuinely fails.git diff --name-only 74e52b4..44bbead— exactlyscripts/build-deb.sh,test/build-deb.test.js,changelog.d/63.md;git diff --checkclean; base == origin/main.Criteria check: (1) umask 077 build: the test asserts every
./usr/entry fromdpkg-deb -c— dirsdrwxr-xr-x,cli.js-rwxr-xr-x, all other regular files-rw-r--r--; passing means every mode in the archive matched. (2) umask 022 vs 077:deepEqualon the full path→mode map — byte-identical mode sets. (3) mutation proof above. (4)(5) verified by the clean-tree run:npmis a stubbedexit 0shim prepended to PATH (no network path exists in the build), and nothing landed outside temp. (6) exact-path diff above. (7) 150/150 locally; on the forge, the combined commit status for this head issuccess, the PR carries noblocker:ci-red, and the panel request (which the repo gates on greenci / test) fired.Spec conformance: L72 is the issue's exact one-liner
chmod -R u+rwX,go=rX "$PKG/usr"; L73 kept stating the entry point's mode; the L70-71 comment now tells the truth about what the code guarantees; the lintian block is untouched with|| trueintact, as the spec's out-of-scope list demands. Conventions hold: CommonJS,node:test,#!/usr/bin/env bashstub, fragment format matches its siblings inchangelog.d/.npm run check:governancepasses.Could not verify: the Actions API (
actions/runs,actions/tasks) returned 404/empty on this forge, so I could not read the individual CI job logs; I relied on the combined commit status (success), the reconciler's labels (noblocker:ci-redat this head), and the repo's own engine gating of panel requests on greenci / test. I did not install the package on a live system; the archive listing is the evidence, read withdpkg-deb -cas the issue itself prescribes.Non-blocking nits (builder's discretion): the test hard-codes cli.js as the only executable payload file — a future executable in
src/will trip the strict expectation with a clear diff, which is arguably the strictness you want; and symlink entries are intentionally skipped in the mode map (archive symlinks carry no mode), worth a word of comment if this test grows siblings.Approve. Reviewed the whole PR at head
44bbeadff6against #63's acceptance criteria, in a detached worktree.Verified, not read:
node --test→ 150/150 pass locally (Node v22.23.2).chmod -R go-wandtest/build-deb.test.jsfailed, then restored. The failure case actually fails.dist/was untouched after the run, andt.afterremoves the temp trees.npm ciis stubbed via a PATH shim; no network.dpkg-deb -cthat umask 077 and umask 022 builds yield identical mode maps —0755dirs,0644files,0755forcli.js(the only./usr/regular file that may keep execute).git diff main...HEAD --stattouches exactlyscripts/build-deb.sh,test/build-deb.test.js,changelog.d/63.md— matching the criterion.ci / testandlabels / labelsboth success (forgejo commit statuses).chmod -R u+rwX,go=rXis umask-independent by construction: it sets bits from the existing mode, never consults the umask, andXapplies execute only to directories and already-executable files. The L70-71 comment now describes what the code guarantees; L73's explicitchmod 0755 cli.jsis kept as the spec directs.Non-blocking nit (builder's discretion): the test hardcodes
stoke_1.5.0_all.deb, coupling it to the package version — a future version bump must update the test. A glob ofdist/*.debwould avoid the coupling.Could not verify: nothing material. (The publish/release paths and lintian behavior are untouched by this diff; lintian remains non-fatal per the spec.)