fs-local: POSIX-only mode-bit assertions, document Windows DACL-inheritance semantics

Windows drives only the read-only attribute through chmod and reports
synthetic stat mode bits, so writeFileAtomic's mode arguments are inert
there; write-in-progress privacy comes from the staging dir (created in
the target's parent) inheriting the destination directory's DACL.
Production is deliberately unchanged -- the chmod calls are benign
no-ops and platform-guarding them out buys nothing. Tests guard the
mode-bit expects to POSIX; there is no Windows ACL assertion because an
ACL check would pin OS inheritance plus the machine's %TEMP% ACL, not
this package. Decision and rejected alternatives (explicit DACLs,
Get-Acl/icacls test verification) recorded in the new RFC.
This commit is contained in:
Huanqi Cao
2026-07-05 21:15:46 +08:00
committed by imccyu
parent 715aa7372a
commit e47ae0643c
5 changed files with 49 additions and 6 deletions
+15 -4
View File
@@ -367,6 +367,12 @@ describe('streamWholeText', () => {
})
})
// Windows drives only the read-only attribute through `chmod` and reports
// synthetic `stat` mode bits, so mode assertions are POSIX-only; on Windows
// write-in-progress privacy comes from the destination directory's inherited
// DACL (docs/rfc/implemented/architecture/2026-07-05-windows-fs-permissions.md).
const posixModes = process.platform !== 'win32'
describe('writeFileAtomic — temp-file safety', () => {
it('writes through a private staging dir and owner-only temp file', async () => {
const file = join(dir, 'a.txt')
@@ -374,17 +380,22 @@ describe('writeFileAtomic — temp-file safety', () => {
await writeFileAtomic(file, 'hello', 0o640, undefined, {
inspectTemp: async ({ stagingDir, tempPath }) => {
inspected = true
expect((await stat(stagingDir)).mode & 0o777).toBe(0o700)
expect((await stat(tempPath)).mode & 0o777).toBe(0o600)
const [staging, temp] = await Promise.all([stat(stagingDir), stat(tempPath)])
expect(staging.isDirectory()).toBe(true)
expect(temp.isFile()).toBe(true)
if (posixModes) {
expect(staging.mode & 0o777).toBe(0o700)
expect(temp.mode & 0o777).toBe(0o600)
}
},
})
expect(inspected).toBe(true)
expect(await readFile(file, 'utf8')).toBe('hello')
expect((await stat(file)).mode & 0o777).toBe(0o640)
if (posixModes) expect((await stat(file)).mode & 0o777).toBe(0o640)
expect((await readdir(dir)).filter(n => n.includes('.tmp'))).toEqual([])
})
it('creates new files owner-only by default', async () => {
it.skipIf(!posixModes)('creates new files owner-only by default', async () => {
const file = join(dir, 'a.txt')
await writeFileAtomic(file, 'hello', undefined, undefined)
expect((await stat(file)).mode & 0o777).toBe(0o600)