import { existsSync, readFileSync, mkdirSync, appendFileSync } from 'node:fs';
import { dirname, join } from 'node:path';

//#region src/lib/server/audit-log.ts
/**
* Append-only audit log for Studio admin actions.
*
* Writes newline-delimited JSON entries to
* `<projectPath>/.cleo/audit/studio-actions.jsonl`. Every admin mutation
* (scan, clean, delete, reindex, backup, doctor, gc, migrate) SHOULD
* call {@link recordAudit} both pre- and post-action so a trail of
* intent + outcome exists even when the underlying CLI fails.
*
* Reads are capped to the trailing N entries so the log can grow
* indefinitely without blowing the Studio process.
*
* @task T990
* @wave 1E
*/
/**
* Resolve the audit log file path for the given project root.
*
* Defaults to `<projectPath>/.cleo/audit/studio-actions.jsonl`.
*/
function resolveAuditLogPath(projectPath) {
	return join(projectPath, ".cleo", "audit", "studio-actions.jsonl");
}
/**
* Append a new audit entry. Never throws — logging failures must not
* break an admin action. Swallows errors silently (they surface via
* the action's own error envelope).
*/
function recordAudit(projectPath, entry) {
	try {
		const path = resolveAuditLogPath(projectPath);
		if (!existsSync(dirname(path))) mkdirSync(dirname(path), { recursive: true });
		const full = {
			timestamp: (/* @__PURE__ */ new Date()).toISOString(),
			...entry
		};
		appendFileSync(path, `${JSON.stringify(full)}\n`, { encoding: "utf8" });
	} catch {}
}
/**
* Read the last `limit` audit entries (newest first).
*
* Returns `[]` when the file does not exist. Malformed lines are
* skipped silently.
*/
function readAuditLog(projectPath, limit = 50) {
	try {
		const path = resolveAuditLogPath(projectPath);
		if (!existsSync(path)) return [];
		const lines = readFileSync(path, "utf8").split("\n").filter((line) => line.trim().length > 0);
		const entries = [];
		for (const line of lines.slice(-limit).reverse()) try {
			const parsed = JSON.parse(line);
			if (typeof parsed.timestamp === "string" && typeof parsed.actor === "string" && typeof parsed.action === "string" && (parsed.result === "success" || parsed.result === "failure" || parsed.result === "dry-run" || parsed.result === "initiated")) entries.push({
				timestamp: parsed.timestamp,
				actor: parsed.actor,
				action: parsed.action,
				target: parsed.target ?? null,
				result: parsed.result,
				detail: parsed.detail ?? null,
				meta: parsed.meta
			});
		} catch {}
		return entries;
	} catch {
		return [];
	}
}

export { recordAudit as a, readAuditLog as r };
//# sourceMappingURL=audit-log-BXVi9iyE.js.map
