Files
deepseek-harness/scripts/gate-log-helper.mjs
T

221 lines
7.2 KiB
JavaScript

#!/usr/bin/env node
/** Pin the repository and each log-path component before creating or operating on private logs. */
import { constants } from 'node:fs'
import { chmod, lstat, mkdir, open, readdir, stat, unlink } from 'node:fs/promises'
import { isAbsolute, sep } from 'node:path'
const MAX_REQUEST_BYTES = 8 * 1024 * 1024
const LOG_NAME = /^[a-zA-Z0-9][a-zA-Z0-9.-]*\.log$/
function errorCode(error) {
return typeof error === 'object' && error !== null && 'code' in error
? error.code
: undefined
}
async function readRequest() {
const chunks = []
let bytes = 0
for await (const chunk of process.stdin) {
bytes += chunk.length
if (bytes > MAX_REQUEST_BYTES) throw new Error('request exceeds the gate-log helper limit')
chunks.push(chunk)
}
return JSON.parse(Buffer.concat(chunks).toString('utf8'))
}
function assertInteger(value, label, minimum) {
if (!Number.isSafeInteger(value) || value < minimum) {
throw new Error(`${label} must be an integer of at least ${minimum}`)
}
}
function assertLogName(name) {
if (typeof name !== 'string' || !LOG_NAME.test(name)) {
throw new Error(`invalid gate-log filename ${JSON.stringify(name)}`)
}
}
function assertRequest(request) {
if (typeof request !== 'object' || request === null) throw new Error('gate-log request must be an object')
switch (request.operation) {
case 'write':
assertLogName(request.filename)
assertInteger(request.retention, 'retention', 1)
if (typeof request.content !== 'string') throw new Error('gate-log content must be a string')
return
case 'prune':
assertInteger(request.retain, 'retain', 0)
return
case 'clean':
return
default:
throw new Error(`unsupported gate-log operation ${JSON.stringify(request.operation)}`)
}
}
function assertIdentity(value, label) {
if (
typeof value !== 'object'
|| value === null
|| typeof value.dev !== 'string'
|| typeof value.ino !== 'string'
) {
throw new Error(`missing expected ${label} identity`)
}
}
function identityOf(metadata) {
return { dev: String(metadata.dev), ino: String(metadata.ino) }
}
function sameIdentity(metadata, expected) {
return String(metadata.dev) === expected.dev && String(metadata.ino) === expected.ino
}
async function assertPinnedRepository(repository) {
if (
typeof repository !== 'object'
|| repository === null
|| typeof repository.root !== 'string'
|| !isAbsolute(repository.root)
|| typeof repository.relative !== 'string'
|| repository.relative === ''
|| repository.relative === '..'
|| repository.relative.startsWith(`..${sep}`)
|| isAbsolute(repository.relative)
) {
throw new Error('invalid repository-relative gate-log path')
}
assertIdentity(repository.identity, 'repository')
const pinnedMetadata = await stat('.', { bigint: true })
if (!pinnedMetadata.isDirectory() || !sameIdentity(pinnedMetadata, repository.identity)) {
throw new Error('gate-log repository identity changed before the helper started')
}
const rootMetadata = await lstat(repository.root, { bigint: true })
if (
!rootMetadata.isDirectory()
|| rootMetadata.isSymbolicLink()
|| !sameIdentity(rootMetadata, repository.identity)
) {
throw new Error('gate-log repository root is not a real directory')
}
}
async function enterLogDirectory(relativePath, create) {
const traversed = []
for (const component of relativePath.split(sep)) {
if (component === '' || component === '.' || component === '..') {
throw new Error(`invalid gate-log path component ${JSON.stringify(component)}`)
}
traversed.push(component)
let componentMetadata
try {
componentMetadata = await lstat(component, { bigint: true })
} catch (error) {
if (errorCode(error) !== 'ENOENT') throw error
if (!create) return undefined
try {
await mkdir(component, { mode: 0o700 })
} catch (mkdirError) {
if (errorCode(mkdirError) !== 'EEXIST') throw mkdirError
}
componentMetadata = await lstat(component, { bigint: true })
}
const shown = traversed.join('/')
if (!componentMetadata.isDirectory() || componentMetadata.isSymbolicLink()) {
throw new Error(`gate-log path component is not a real directory: ${shown}`)
}
const expected = identityOf(componentMetadata)
process.chdir(component)
const pinnedMetadata = await stat('.', { bigint: true })
if (!pinnedMetadata.isDirectory() || !sameIdentity(pinnedMetadata, expected)) {
throw new Error(`gate-log path component identity changed before pinning: ${shown}`)
}
}
await chmod('.', 0o700)
return identityOf(await stat('.', { bigint: true }))
}
async function removeOldLogs(retain, newest) {
assertInteger(retain, 'retain', 0)
const entries = await readdir('.', { withFileTypes: true })
const logs = []
for (const entry of entries) {
if (!entry.isFile() || !LOG_NAME.test(entry.name)) continue
let metadata
try {
metadata = await lstat(entry.name, { bigint: true })
} catch (error) {
if (errorCode(error) === 'ENOENT') continue
throw error
}
if (!metadata.isFile() || metadata.isSymbolicLink()) continue
logs.push({ name: entry.name, mtimeNs: metadata.mtimeNs })
}
logs.sort((left, right) => {
if (left.name === newest) return 1
if (right.name === newest) return -1
if (left.mtimeNs < right.mtimeNs) return -1
if (left.mtimeNs > right.mtimeNs) return 1
return left.name.localeCompare(right.name)
})
const removed = []
for (const entry of logs.slice(0, Math.max(0, logs.length - retain))) {
try {
await unlink(entry.name)
removed.push(entry.name)
} catch (error) {
if (errorCode(error) !== 'ENOENT') throw error
}
}
return removed
}
async function writeLog(request) {
assertLogName(request.filename)
assertInteger(request.retention, 'retention', 1)
if (typeof request.content !== 'string') throw new Error('gate-log content must be a string')
const handle = await open(
request.filename,
constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW,
0o600,
)
try {
await handle.writeFile(request.content, 'utf8')
await handle.chmod(0o600)
} finally {
await handle.close()
}
const removed = await removeOldLogs(request.retention, request.filename)
return { filename: request.filename, removed }
}
async function main() {
const request = await readRequest()
assertRequest(request)
await assertPinnedRepository(request.repository)
const directory = await enterLogDirectory(request.repository.relative, request.operation === 'write')
if (directory === undefined) return { removed: [] }
switch (request.operation) {
case 'write': {
const result = await writeLog(request)
return { ...result, directory }
}
case 'prune':
return { directory, removed: await removeOldLogs(request.retain) }
case 'clean':
return { directory, removed: await removeOldLogs(0) }
default:
throw new Error(`unsupported gate-log operation ${JSON.stringify(request.operation)}`)
}
}
try {
process.stdout.write(`${JSON.stringify(await main())}\n`)
} catch (error) {
process.stderr.write(`gate-log-helper: ${error instanceof Error ? error.message : String(error)}\n`)
process.exitCode = 1
}