/** * Service-account key material handling for `hikoutei setup`. * * The secure key-file reading and validation logic of the setup flow, * extracted verbatim: parse/validate raw key JSON, securely read an existing * key file through ONE descriptor boundary (no-follow, non-block, * lstat/fstat inode binding, owner-only mode 0600 applied and verified * through the still-open descriptor before any read, sanitized path-only * failures), and promote either the non-secret metadata or the validated * in-memory credential. The private key exists only in process memory for * the run and never appears in results, messages, the checkpoint, or the * `.env` file. */ import type { KeyMetadataResult, SecureKeyReadResult } from "./keyContract.js"; import { type Stats } from "node:fs"; /** * Parses and validates raw service-account key JSON (no filesystem access). * * Shared by the secure descriptor read and by tests. The key material is * never returned; only the non-secret metadata is promoted. The validated * in-memory key material is available to the credential reader * (`readServiceAccountKeyCredentialSecurely`) for the SA verify phase. */ export declare function parseServiceAccountKeyJson(raw: string, sourceLabel: string): KeyMetadataResult; /** * Filesystem operations the secure key read uses; injectable for tests. */ export interface KeyFileFs { lstatSync(path: string): Stats; openSync(path: string, flags: number): number; fchmodSync(fd: number, mode: number): void; fstatSync(fd: number): Stats; readFileSync(fd: number, encoding: "utf8"): string; closeSync(fd: number): void; } /** * Securely reads an existing service-account key file through ONE * descriptor boundary and enforces owner-only mode 0600. * * A missing file is `absent`. An existing entry must be a regular file (a * symlink is refused outright; directories, FIFOs, and sockets are refused * too). The file is opened with `O_NOFOLLOW` (where the platform defines it * — a symlink swapped in between the type check and the open fails with * ELOOP/EMLINK and is refused) plus `O_NONBLOCK` (where the platform * defines it — a FIFO swapped in between the type check and the open * returns from the open instead of blocking), the descriptor is * fstat-verified as a regular file with the SAME device/inode the lstat * observed BEFORE any fchmod (a directory, FIFO, socket, device, or * replaced-file entry is refused with zero chmod and zero read calls), and * only then is mode 0600 applied THROUGH the open descriptor * with `fchmod` and the resulting mode verified on the same descriptor * before a single byte is read — never an existsSync/readFileSync * check-then-use sequence, so an alias planted mid-read cannot receive the * chmod or be read through. Only after the descriptor is secured is the * content parsed and validated (JSON shape, RSA private key, project, * client email, and non-secret key id). Any inspect/open/type/chmod/read/ * parse failure fails closed with a stable path-only message that never * contains raw error text or key material, and the descriptor is closed * exactly once (a close failure never overrides the verdict). Supported * platforms (macOS/Linux) can * enforce owner-only modes; Windows automatic setup is refused before this * code runs. */ export declare function readServiceAccountKeySecurely(keyPath: string, fs?: KeyFileFs): SecureKeyReadResult; /** * Result of the secure, descriptor-based key credential read. * * Same descriptor boundary as `readServiceAccountKeySecurely`, but the * validated `private_key` is promoted into process memory for the SA * access verify phase: the verifier is given the credentials in memory and * NEVER reopens the key pathname, so a mid-run replacement cannot redirect * it. The key material exists only in memory for the run; it is never * returned by the setup result, never written to the checkpoint or `.env`, * and never included in any error message. */ export type SecureKeyCredentialReadResult = { readonly status: "absent"; } | { readonly status: "ok"; readonly credentials: { readonly projectId: string; readonly clientEmail: string; readonly privateKey: string; }; } | { readonly status: "invalid"; readonly message: string; }; /** * Securely reads an existing service-account key file and promotes the * validated credential into process memory. * * Identical descriptor security to `readServiceAccountKeySecurely` * (regular file, no-follow, non-block, lstat/fstat inode binding, owner-only * 0600 through the descriptor before any read, sanitized failures), but * the returned credentials carry the validated `privateKey` so the SA * access verifier can authenticate from memory. The private key is only in * process memory for the run and never appears in results, messages, the * checkpoint, or the `.env` file. */ export declare function readServiceAccountKeyCredentialSecurely(keyPath: string, fs?: KeyFileFs): SecureKeyCredentialReadResult; //# sourceMappingURL=keyMaterial.d.ts.map