export declare const PRIVATE_DIR_MODE = 448; export declare const PRIVATE_FILE_MODE = 384; /** Create (or reuse) a directory and reassert owner-only traversal mode. */ export declare function ensurePrivateDir(dir: string): void; /** Best-effort chmod reassert when reading an existing credential file. */ export declare function reassertPrivateFileModes(dir: string, filePath: string): void; /** * Write via an exclusive temp file and atomic rename so readers never observe a * partial file or a transient wider mode. Cleans up the temp file on failure. */ export declare function atomicWriteFile(dir: string, fileName: string, writeTemp: (tmpPath: string) => void): void; /** * A caller that has stopped waiting for an asynchronous write. * * A write nobody is waiting for any more cannot be cancelled — no fs API revokes * a request a filter driver is sitting on — so it goes on running, one step at a * time, minutes after the job it belonged to was erased. The latch is how it is * told that, so that whatever it does next it UNDOES rather than leaves behind. * See the abandonment handling in atomicWriteUtf8Async. */ export interface AsyncWriteAbandoned { /** Set by the caller the moment it gives up on the write. */ abandoned: boolean; } /** * The same write, off the event loop. * * The synchronous twin above is right for everything that runs at startup or on * a CLI turn. It is wrong on the ONE path that runs inside the WebSocket frame * handler — a Windows job start — because the desktop app embeds this runtime on * Electron's main loop, where a filesystem an on-access scanner is holding turns * a small write into a stalled heartbeat and the "Reconnecting…" wedge this * whole effort exists to prevent (see tray.ts, diag-log.ts). * * Semantics are otherwise identical, including the temp-file cleanup on failure * and the errno the caller classifies (job-scripts.ts): the only difference is * which thread waits. * * ABANDONMENT is the one thing the synchronous twin never had to think about. A * caller that timed out (JOB_SCRIPT_IO_TIMEOUT_MS) has already failed its start * and deleted the job's directory — while THIS call is still parked inside the * scanner. It resumes into a world where its directory is gone, and its very * first step is `mkdir(recursive)`: it would recreate the id-shaped directory * the caller just removed and drop a wrapper.cmd or a `.tmp` into it, leaving a * directory with no meta.json that pruneUnreadable then keeps for the whole * retention window. So each step checks the latch and undoes what it has done: * the temp file, the renamed file, and the directory itself when this call is * what created it. */ export declare function atomicWriteUtf8Async(dir: string, fileName: string, contents: string, giveUp?: AsyncWriteAbandoned): Promise; export declare function atomicWriteUtf8(dir: string, fileName: string, contents: string): void; export declare function atomicWriteBuffer(dir: string, fileName: string, data: Buffer): void;