Static release carry: explicit 0444 under UMask 0027 #9

Merged
eureka merged 2 commits from hands/static-carry-mode-0444 into main 2026-11-14 08:44:32 +00:00
Owner

Cause: carry_and_flip created the carried site file with OpenOptions::mode(0o444). The create mode is masked by the umask, and the service runs UMask=0027, so the file landed 0440 root:root. www-data could not read it and the sealed-tree verifier (accepts only 0444/0555) rejected it. Seen on the first Ratatoskr release (receipt /opt/commons/handoff/rat146-a-receipt-20261114.md); S6 is held until a fixed Idunn is deployed and a second release is made.

Fix: file.set_permissions(0o444) on the open handle before the write and rename. One line plus the import.

Proof: new test static_release_carry_is_0444_under_the_service_umask re-runs itself in a child process under umask(0o027) (umask is process-global, so no sibling test sees it; the parent also fails if the child filter matched no test).

  • Red (set_permissions line commented out): child fails, left: 288 right: 292 (0o440 vs 0o444).
  • Green: cargo test --lib static_release 15 passed, including the existing default-umask test.

Sibling sites on the static-release path: none unfixed. Other .mode(...) creates either set permissions explicitly (route stage 8095, write_root_owned_file 8193) or only narrow (0600 create_private_file, 0400 activation credential, which also sets permissions).

🤖 Generated with Claude Code

Cause: `carry_and_flip` created the carried site file with `OpenOptions::mode(0o444)`. The create mode is masked by the umask, and the service runs `UMask=0027`, so the file landed 0440 root:root. www-data could not read it and the sealed-tree verifier (accepts only 0444/0555) rejected it. Seen on the first Ratatoskr release (receipt /opt/commons/handoff/rat146-a-receipt-20261114.md); S6 is held until a fixed Idunn is deployed and a second release is made. Fix: `file.set_permissions(0o444)` on the open handle before the write and rename. One line plus the import. Proof: new test `static_release_carry_is_0444_under_the_service_umask` re-runs itself in a child process under `umask(0o027)` (umask is process-global, so no sibling test sees it; the parent also fails if the child filter matched no test). - Red (set_permissions line commented out): child fails, `left: 288 right: 292` (0o440 vs 0o444). - Green: `cargo test --lib static_release` 15 passed, including the existing default-umask test. Sibling sites on the static-release path: none unfixed. Other `.mode(...)` creates either set permissions explicitly (route stage 8095, write_root_owned_file 8193) or only narrow (0600 create_private_file, 0400 activation credential, which also sets permissions). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The carry file was created with .mode(0o444), which the service's UMask=0027
masks to 0440; www-data could not read it and the sealed-tree verifier
rejected it. Set the permissions on the open handle before the rename, and
prove it in a child process under umask 0027.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
eureka merged commit 140fbc3161 into main 2026-11-14 08:44:32 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
GameCult/Idunn!9
No description provided.