In internal/provider/file/deploy.go (used by the cron, service and certificate providers):
WriteFile truncates the target in place, so a crash mid-write leaves a partial config, unit or certificate on disk.
os.WriteFile does not change permissions of an existing file, so a changed Mode is never applied, and the SHA-match shortcut only compares content.
DeployRequest.Owner and Group are stored in the file state but never applied; the file package has no chown.
internal/provider/node/user/debian_ssh_key.go uses the same non-atomic pattern for authorized_keys.
Fix: write to a temp file in the same directory, set mode (and owner/group when given), then rename. Apply mode, owner and group even when the content hash matches, or remove Owner/Group from the API if they will not be supported.
Found in the September 2026 codebase review. Tracked in the review tracking issue.
In
internal/provider/file/deploy.go(used by the cron, service and certificate providers):WriteFiletruncates the target in place, so a crash mid-write leaves a partial config, unit or certificate on disk.os.WriteFiledoes not change permissions of an existing file, so a changedModeis never applied, and the SHA-match shortcut only compares content.DeployRequest.OwnerandGroupare stored in the file state but never applied; the file package has nochown.internal/provider/node/user/debian_ssh_key.gouses the same non-atomic pattern forauthorized_keys.Fix: write to a temp file in the same directory, set mode (and owner/group when given), then rename. Apply mode, owner and group even when the content hash matches, or remove Owner/Group from the API if they will not be supported.
Found in the September 2026 codebase review. Tracked in the review tracking issue.