import { BaseCleaner } from "./BaseCleaner"; import { CacheCategory, CacheInfo, CacheType, SafetyTier } from "../types"; import { Stats } from "fs"; /** * Minimal filesystem surface the tmp cleaner depends on. Injecting it keeps the * safety-critical walk and the guarded deleter deterministically testable * (sockets, uids, and symlinks that memfs cannot model) without touching the * production path, which uses the real fs/promises functions below. */ export interface TmpFs { readdir(p: string): Promise; lstat(p: string): Promise; realpath(p: string): Promise; rm(p: string, opts: { recursive: boolean; force: boolean; }): Promise; } /** * Anything modified/changed within this window is treated as in-use and never * offered, even under the aggressive profile. The single cheapest, spawn-free * "active task" signal. */ export declare const IN_USE_FLOOR_MS: number; /** * Default boundary (days) between the aggressive-only "caution" band and the * default-cleaned "probably-safe" band. Per-run override via `--older-than`. */ export declare const DEFAULT_TMP_MAX_AGE_DAYS = 3; /** * Names always excluded. The file-type check already skips sockets/FIFOs, but a * regular DIRECTORY can wrap live sockets the top-level type check cannot see * (e.g. an ssh agent dir holding a socket). These protect those wrappers. */ export declare const TMP_NEVER_PATTERNS: RegExp[]; /** * Names owned by dedicated cleaners; excluded so tmp never double-sizes or * double-deletes what go-build / pip already manage. */ export declare const TMP_CLAIMED_PATTERNS: RegExp[]; export declare function matchesNeverName(name: string): boolean; export declare function matchesClaimedName(name: string): boolean; /** * Resolve the temp roots: realpath-canonicalized, deduped, existing dirs only. * macOS `os.tmpdir()` -> /var/folders//T (the reclaimable bulk) and /tmp -> * /private/tmp; realpath collapses those aliases. We NEVER ascend to a root's * parent (its 0/C/X siblings on macOS are live Darwin state). On Windows only * os.tmpdir() (%TEMP%, per-user) exists; /tmp and /var/tmp realpath-fail and drop. */ export declare function resolveTmpRoots(rawRoots?: string[], realpathSyncFn?: (p: string) => string, statSyncFn?: (p: string) => { isDirectory(): boolean; }): string[]; /** * Return the matching root if `realPath` is a STRICT descendant of exactly one * root, else null. Equality with a root returns null: a root is never a * deletion target. This is the containment boundary the inherited clearPath and * safeRmrf both lack. */ export declare function isWithinRoots(realPath: string, roots: string[]): string | null; /** Tier from age. = the in-use floor) is aggressive-only. */ export declare function tierForAgeDays(ageDays: number, thresholdDays: number): SafetyTier; interface WalkResult { eligible: boolean; reason?: string; newestActivityMs: number; size: number; } interface WalkBudget { deadline: number; nodesLeft: number; } /** * Bounded recursive subtree guard — the real liveness mechanism. Disqualifies * the ENTIRE candidate if any descendant is a socket/FIFO/device, or any * descendant's max(mtime,ctime) is within the in-use floor, or the subtree * cannot be fully verified within the budget. Liveness uses mtime/ctime, NOT * atime: our own readdir bumps directory atime and would self-disqualify * everything. Also returns the newest activity (for tiering) and total size. */ export declare function analyzeTree(rootPath: string, topStat: Stats, now: number, budget: WalkBudget, fs?: TmpFs): Promise; /** * System temp cleaner. Reclaims abandoned files across the user's temp roots, * enabled by default, while structurally refusing to touch anything a live * process could need — spawn-free (file-type + ownership + name + recency * heuristics, no lsof). Extends BaseCleaner for tier-gating and consent, but * OVERRIDES clearPath with a guarded deleter because the inherited path has no * containment check. */ export declare class TmpCleaner extends BaseCleaner { private readonly fsImpl; private readonly rootsOverride?; private readonly budgets; name: string; type: CacheType; description: string; private roots; private cachedCategories; private discoveredAt; private discoveryInFlight; constructor(fsImpl?: TmpFs, rootsOverride?: string[] | undefined, budgets?: { perCandidateMs: number; globalMs: number; }); private getRoots; isAvailable(): Promise; getCacheInfo(): Promise; getCacheCategories(): Promise; /** Run (or reuse within one scan) discovery. Mirrors app-caches memoization. */ private discover; private runDiscovery; /** * Guarded deleter — replaces BaseCleaner.clearPath, which follows symlinks and * rm-rf's with no containment check. Per path: reject symlinks, canonicalize, * assert strict-descendant of a temp root, re-verify the subtree is still * inactive (TOCTOU shrink), then fully remove the entry. Any failure or guard * rejection skips the path and logs — it never crashes the run and never * deletes something it could not prove safe. */ protected clearPath(p: string): Promise; } declare const _default: TmpCleaner; export default _default; //# sourceMappingURL=tmp.d.ts.map