/** 자격증명 파일 권한 — 소유자만 읽고 쓴다. */ export declare const CREDENTIAL_FILE_MODE = 384; /** 자격증명 디렉터리 권한 — 소유자만 진입한다. */ export declare const CREDENTIAL_DIR_MODE = 448; export interface AtomicWriteOptions { /** * 최종 파일 권한. temp 파일에 **rename 전에** 적용하므로, 파일이 대상 경로에 나타나는 * 첫 순간부터 이 권한이다 — write 후 chmod 하는 방식에 있던 "잠깐 0644" 창이 없다. * 기존 파일을 덮어쓸 때도 inode 가 통째로 갈리므로 느슨한 권한이 자동으로 교정된다. */ mode?: number; /** 상위 디렉터리를 만들 때 쓸 권한. 이미 있으면 건드리지 않는다. */ dirMode?: number; /** 테스트용 주입 — 기본은 fs.renameSync. */ rename?: (from: string, to: string) => void; /** 테스트용 주입 — 기본은 Atomics.wait 기반 동기 대기. */ sleep?: (ms: number) => void; } /** * Windows 에서 rename 이 일시적으로 실패할 때의 대기 간격(ms). 합계 정확히 1000ms. * * 왜: Windows 는 다른 프로세스가 대상 파일을 열고 있으면(백신·검색 인덱서·OneDrive, 또는 * tokens.json 을 읽는 중인 다른 mimi-seed 프로세스) rename 을 EPERM/EBUSY/EACCES 로 거절한다. * 그 핸들은 보통 수십~수백 ms 안에 닫히므로, 짧게 물러났다 다시 시도하면 대부분 통과한다. * 동기 writer 안에서 기다리므로 총합(1초)이 곧 최악의 블로킹 시간이다 — 늘리지 말 것. */ export declare const RENAME_RETRY_DELAYS_MS: readonly [10, 20, 40, 80, 160, 320, 370]; /** 재시도할 오류 코드. ENOENT 등은 잠금이 아니라 진짜 실패이므로 즉시 던진다. */ export declare const RENAME_RETRY_CODES: ReadonlySet; export type RenameRetryDeps = Pick; /** * 일시적 잠금 오류(EPERM/EBUSY/EACCES)에만 정해진 간격으로 재시도하고, 그 외 오류는 즉시 던진다. * 마지막 시도가 실패하면 그 오류를 그대로 던진다 — temp 정리는 호출부(writeFileAtomic)의 catch 가 한다. */ export declare function renameWithRetry(from: string, to: string, deps?: RenameRetryDeps): void; export declare function writeFileAtomic(filePath: string, contents: string | Uint8Array, options?: AtomicWriteOptions): void; export declare function writeJsonAtomic(filePath: string, value: unknown, options?: AtomicWriteOptions): void; /** 자격증명 JSON 저장 — 0600 파일 / 0700 디렉터리를 강제한다. */ export declare function writeCredentialJson(filePath: string, value: unknown): void; /** 이미 직렬화된 자격증명(서비스 계정 키 원본, keystore 바이너리 등) 저장. */ export declare function writeCredentialFile(filePath: string, contents: string | Uint8Array): void;