Publish Container / build (push) Successful in 15m46s
- Atomic temp-file + rename for all JSON data writes (no truncated files on crash) - /api/bible-passage: rate limit, range caps (60 verses), bounded cache - Admin webhooks: https-only, block private/internal/Tailscale addresses (checked at registration and delivery), no redirects - Resend webhook token compare is timing-safe - DOMPurify on rendered study notes and broadcast preview - CI runs lint + tests before build - Permissions-Policy and HSTS (production) headers; JSON error handler for /api - Tests for URL safety and atomic writes Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
27 lines
1.1 KiB
JavaScript
27 lines
1.1 KiB
JavaScript
import { test } from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import { mkdtemp, readFile, readdir, writeFile as plainWrite, rm } from 'node:fs/promises'
|
|
import os from 'node:os'
|
|
import path from 'node:path'
|
|
import { writeFile } from '../server/atomic-write.js'
|
|
|
|
test('replaces file contents and leaves no temp files', async () => {
|
|
const dir = await mkdtemp(path.join(os.tmpdir(), 'atomic-'))
|
|
const file = path.join(dir, 'a.json')
|
|
await plainWrite(file, 'old')
|
|
await writeFile(file, '{"ok":true}', 'utf8')
|
|
assert.equal(await readFile(file, 'utf8'), '{"ok":true}')
|
|
assert.deepEqual(await readdir(dir), ['a.json'])
|
|
await rm(dir, { recursive: true })
|
|
})
|
|
|
|
test('a failed write keeps the old file and cleans up', async () => {
|
|
const dir = await mkdtemp(path.join(os.tmpdir(), 'atomic-'))
|
|
const file = path.join(dir, 'a.json')
|
|
await plainWrite(file, 'old')
|
|
await assert.rejects(() => writeFile(file, { not: 'a string' }))
|
|
assert.equal(await readFile(file, 'utf8'), 'old')
|
|
assert.deepEqual(await readdir(dir), ['a.json'])
|
|
await rm(dir, { recursive: true })
|
|
})
|