const require_chunk = require("./chunk-DakpK96I.cjs");
const require_atomic_write = require("./atomic-write-BYmF-ThH.cjs");
let commander = require("commander");
let path = require("path");
path = require_chunk.__toESM(path, 1);
let fs = require("fs");
fs = require_chunk.__toESM(fs, 1);
let gray_matter = require("gray-matter");
gray_matter = require_chunk.__toESM(gray_matter, 1);
let zod_validation_error = require("zod-validation-error");
let zod = require("zod");
let crypto = require("crypto");
let ansis = require("ansis");
ansis = require_chunk.__toESM(ansis, 1);
let child_process = require("child_process");
//#region src/schemas/main-facts.ts
const MainFactsSchema = zod.z.object({
	name: zod.z.string().min(1),
	domain: zod.z.string().optional(),
	email: zod.z.string().optional(),
	phone: zod.z.string().optional(),
	industry: zod.z.string().optional(),
	relationship_stage: zod.z.enum([
		"prospect",
		"active",
		"churned",
		"paused"
	]),
	deal_value: zod.z.number().optional(),
	currency: zod.z.string().default("EUR"),
	primary_contact: zod.z.string().optional(),
	timezone: zod.z.string().optional(),
	tags: zod.z.array(zod.z.string()).default([]),
	created: zod.z.preprocess((v) => v instanceof Date ? v.toISOString().slice(0, 10) : v, zod.z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "YYYY-MM-DD required")),
	updated: zod.z.preprocess((v) => v instanceof Date ? v.toISOString().slice(0, 10) : v, zod.z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "YYYY-MM-DD required"))
});
//#endregion
//#region src/fs/safe-path.ts
/**
* Filesystem path-segment safety. A segment (customer slug, custom-object name,
* KB article id/category, …) is safe iff it cannot escape its parent directory:
* no path separators, no `..`, no NUL, not "." or empty, and bounded in length.
* Enforced wherever an untrusted value (from an MCP tool, API, or import) is used
* to build a file path, to prevent path-traversal (arbitrary read/write).
*/
function isSafePathSegment(segment) {
	return typeof segment === "string" && segment.length > 0 && segment.length <= 128 && segment !== "." && !segment.includes("/") && !segment.includes("\\") && !segment.includes("\0") && !segment.includes("..");
}
function assertSafePathSegment(segment, kind = "path segment") {
	if (!isSafePathSegment(segment)) throw new Error(`Invalid ${kind}: ${JSON.stringify(segment)}`);
}
//#endregion
//#region src/fs/customer-dir.ts
function assertSafeSlug(slug) {
	assertSafePathSegment(slug, "customer slug");
}
function getCustomerDir(dataDir, slug) {
	assertSafeSlug(slug);
	return path.default.join(dataDir, "customers", slug);
}
function customerExists(dataDir, slug) {
	return fs.default.existsSync(getCustomerDir(dataDir, slug));
}
/** List all customer slugs (immediate subdirectories of customers/). */
function listCustomerSlugs(dataDir) {
	const dir = path.default.join(dataDir, "customers");
	if (!fs.default.existsSync(dir)) return [];
	return fs.default.readdirSync(dir).filter((s) => {
		try {
			return fs.default.statSync(path.default.join(dir, s)).isDirectory();
		} catch {
			return false;
		}
	});
}
async function ensureCustomerDir(dataDir, slug) {
	const customerDir = getCustomerDir(dataDir, slug);
	fs.default.mkdirSync(customerDir, { recursive: true });
	fs.default.mkdirSync(path.default.join(customerDir, "attachments"), { recursive: true });
	fs.default.mkdirSync(path.default.join(customerDir, "transcripts"), { recursive: true });
}
async function writeMainFacts(dataDir, slug, facts) {
	const filePath = path.default.join(getCustomerDir(dataDir, slug), "main_facts.md");
	const clean = Object.fromEntries(Object.entries(facts).filter(([, v]) => v !== void 0));
	require_atomic_write.writeFileAtomic(filePath, gray_matter.default.stringify("", clean));
}
async function readMainFacts(dataDir, slug) {
	const filePath = path.default.join(getCustomerDir(dataDir, slug), "main_facts.md");
	if (!fs.default.existsSync(filePath)) throw new Error(`main_facts.md not found for customer '${slug}'`);
	const data = (0, gray_matter.default)(fs.default.readFileSync(filePath, "utf-8")).data;
	for (const key of ["created", "updated"]) if (data[key] instanceof Date) data[key] = data[key].toISOString().slice(0, 10);
	const result = MainFactsSchema.safeParse(data);
	if (!result.success) throw new Error((0, zod_validation_error.fromZodError)(result.error, {
		prefix: `Schema error in ${filePath}`,
		prefixSeparator: ":\n  - ",
		issueSeparator: "\n  - "
	}).message);
	return result.data;
}
//#endregion
//#region src/fs/json-store.ts
/**
* Small shared JSON persistence helpers. Many modules independently reimplemented
* the same "read a JSON file, fall back to a default on missing/parse-error" and
* "write a `{ key: items }` array store" logic — this centralizes both so the
* behavior (and the silent-fallback semantics) is defined in exactly one place.
*
* Writes go through writeFileAtomic, so a crash mid-write can never leave a
* half-written (corrupt) JSON file — readers always see either the old or the
* new complete document. This matters for the config, audit, and state files
* the whole product depends on.
*/
/** Read and parse a JSON file, returning `fallback` if it is missing or invalid. */
function readJsonFile(filePath, fallback) {
	if (!fs.default.existsSync(filePath)) return fallback;
	try {
		return JSON.parse(fs.default.readFileSync(filePath, "utf-8"));
	} catch {
		return fallback;
	}
}
/** Atomically write `value` as pretty-printed JSON, creating parent dirs as needed. */
function writeJsonFile(filePath, value) {
	require_atomic_write.writeFileAtomic(filePath, JSON.stringify(value, null, 2));
}
/**
* Read an array stored under `key` in a `{ [key]: T[] }` JSON document. Returns
* an empty array if the file is missing, unparsable, or the key is not an array.
*/
function readJsonArray(filePath, key) {
	const arr = readJsonFile(filePath, {})[key];
	return Array.isArray(arr) ? arr : [];
}
/** Write an array under `key` as a `{ [key]: items }` JSON document. */
function writeJsonArray(filePath, key, items) {
	writeJsonFile(filePath, { [key]: items });
}
//#endregion
//#region src/ui/colors.ts
const success = (s) => ansis.default.green(s);
const error = (s) => ansis.default.red(s);
const warning = (s) => ansis.default.yellow(s);
const info = (s) => ansis.default.cyan(s);
const bold = (s) => ansis.default.bold(s);
//#endregion
//#region src/commands/backup.ts
function getConfigPath(dataDir) {
	return path.default.join(dataDir, ".agentic", "config.json");
}
function readAgenticConfig(dataDir) {
	const filePath = getConfigPath(dataDir);
	if (!fs.default.existsSync(filePath)) return {};
	try {
		return JSON.parse(fs.default.readFileSync(filePath, "utf-8"));
	} catch {
		return {};
	}
}
function writeAgenticConfig(dataDir, config) {
	writeJsonFile(getConfigPath(dataDir), config);
}
function countDir(dir) {
	let files = 0;
	let bytes = 0;
	if (!fs.default.existsSync(dir)) return {
		files,
		bytes
	};
	const walk = (d) => {
		try {
			for (const entry of fs.default.readdirSync(d)) {
				const full = path.default.join(d, entry);
				try {
					const stat = fs.default.statSync(full);
					if (stat.isDirectory()) walk(full);
					else {
						files++;
						bytes += stat.size;
					}
				} catch {}
			}
		} catch {}
	};
	walk(dir);
	return {
		files,
		bytes
	};
}
function countCustomers(dataDir) {
	const dir = path.default.join(dataDir, "customers");
	if (!fs.default.existsSync(dir)) return 0;
	try {
		return fs.default.readdirSync(dir).filter((f) => {
			try {
				return fs.default.statSync(path.default.join(dir, f)).isDirectory();
			} catch {
				return false;
			}
		}).length;
	} catch {
		return 0;
	}
}
function sha256File(filePath) {
	if (!fs.default.existsSync(filePath)) return "";
	const hash = (0, crypto.createHash)("sha256");
	hash.update(fs.default.readFileSync(filePath));
	return hash.digest("hex");
}
function buildManifest(dataDir, dirs, zipPath, encrypted) {
	let totalFiles = 0;
	let totalBytes = 0;
	for (const d of dirs) {
		const { files, bytes } = countDir(path.default.join(dataDir, d));
		totalFiles += files;
		totalBytes += bytes;
	}
	return {
		version: "1",
		createdAt: (/* @__PURE__ */ new Date()).toISOString(),
		dxcrmVersion: "0.1.0",
		directories: dirs,
		customerCount: countCustomers(dataDir),
		fileCount: totalFiles,
		totalBytes,
		sha256: sha256File(zipPath),
		encrypted
	};
}
function appendBackupLog(dataDir, entry) {
	const logPath = path.default.join(dataDir, ".agentic", "backup-log.json");
	let entries = [];
	if (fs.default.existsSync(logPath)) try {
		entries = JSON.parse(fs.default.readFileSync(logPath, "utf-8"));
	} catch {
		entries = [];
	}
	entries = entries.filter((e) => e.filename !== entry.filename);
	entries.unshift(entry);
	if (entries.length > 100) entries = entries.slice(0, 100);
	writeJsonFile(logPath, entries);
}
function readBackupLog(dataDir) {
	const logPath = path.default.join(dataDir, ".agentic", "backup-log.json");
	if (!fs.default.existsSync(logPath)) return [];
	try {
		return JSON.parse(fs.default.readFileSync(logPath, "utf-8"));
	} catch {
		return [];
	}
}
async function runBackup(output, dataDir, opts = {}) {
	const dir = dataDir ?? process.cwd();
	const customersDir = path.default.join(dir, "customers");
	if (!fs.default.existsSync(customersDir)) {
		console.error(error("✗ No customers directory found."));
		process.exit(1);
	}
	const zipPath = output ?? path.default.join(dir, `dxcrm-backup-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.zip`);
	const includeDirs = ["customers/"];
	if (fs.default.existsSync(path.default.join(dir, ".agentic"))) includeDirs.push(".agentic/");
	try {
		(0, child_process.execSync)(`zip -r "${zipPath}" ${includeDirs.join(" ")}`, { cwd: dir });
		const manifest = buildManifest(dir, includeDirs, zipPath, opts.encrypt ?? false);
		const manifestPath = path.default.join(dir, ".dxcrm-manifest-tmp.json");
		fs.default.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
		try {
			(0, child_process.execSync)(`zip -j "${zipPath}" "${manifestPath}"`, { cwd: dir });
		} catch {}
		fs.default.unlinkSync(manifestPath);
		const verified = verifyBackupFile(zipPath);
		appendBackupLog(dir, {
			filename: path.default.basename(zipPath),
			path: zipPath,
			createdAt: manifest.createdAt,
			sizeBytes: fs.default.existsSync(zipPath) ? fs.default.statSync(zipPath).size : 0,
			verified,
			encrypted: opts.encrypt ?? false,
			customerCount: manifest.customerCount,
			fileCount: manifest.fileCount
		});
		if (opts.remote) await uploadBackup(zipPath, opts.remote);
		console.log(success(`✓ Backup saved: ${zipPath}`));
		console.log(info(`  Customers: ${manifest.customerCount}  Files: ${manifest.fileCount}  Size: ${(manifest.totalBytes / 1024 / 1024).toFixed(1)} MB`));
		if (!verified) console.log(info("  ⚠ Integrity check failed — backup may be incomplete"));
		return manifest;
	} catch (err) {
		console.error(error(`✗ Backup failed: ${err.message}`));
		process.exit(1);
	}
}
function verifyBackupFile(zipPath) {
	if (!fs.default.existsSync(zipPath)) return false;
	try {
		(0, child_process.execSync)(`unzip -t "${zipPath}"`, { stdio: "pipe" });
		return true;
	} catch {
		return false;
	}
}
async function runVerify(zipPath) {
	if (!fs.default.existsSync(zipPath)) {
		console.error(error(`✗ File not found: ${zipPath}`));
		process.exit(1);
	}
	console.log(info(`Verifying ${path.default.basename(zipPath)}...`));
	if (verifyBackupFile(zipPath)) {
		const size = fs.default.statSync(zipPath).size;
		const sha = sha256File(zipPath);
		console.log(success("✓ ZIP integrity OK"));
		console.log(info(`  Size: ${(size / 1024 / 1024).toFixed(1)} MB`));
		console.log(info(`  SHA-256: ${sha}`));
	} else {
		console.error(error("✗ Integrity check failed"));
		process.exit(1);
	}
}
async function uploadBackup(localPath, remote) {
	if (remote.startsWith("s3://")) try {
		(0, child_process.execSync)(`aws s3 cp "${localPath}" "${remote}${path.default.basename(localPath)}"`, { stdio: "pipe" });
		console.log(info(`  ✓ Uploaded to ${remote}${path.default.basename(localPath)}`));
	} catch (err) {
		console.error(error(`  ✗ S3 upload failed (install aws-cli or @aws-sdk/client-s3): ${err.message}`));
	}
	else if (remote.startsWith("rsync://")) {
		const dest = remote.replace("rsync://", "");
		try {
			(0, child_process.execSync)(`rsync -az "${localPath}" "${dest}"`, { stdio: "pipe" });
			console.log(info(`  ✓ Synced to ${dest}`));
		} catch (err) {
			console.error(error(`  ✗ rsync failed: ${err.message}`));
		}
	} else try {
		const destPath = path.default.join(remote, path.default.basename(localPath));
		fs.default.mkdirSync(remote, { recursive: true });
		fs.default.copyFileSync(localPath, destPath);
		console.log(info(`  ✓ Copied to ${destPath}`));
	} catch (err) {
		console.error(error(`  ✗ Copy failed: ${err.message}`));
	}
}
function listBackupsInDir(dir) {
	if (!fs.default.existsSync(dir)) return [];
	try {
		return fs.default.readdirSync(dir).filter((f) => f.match(/^dxcrm-backup-.*\.(zip|dxbak)$/)).map((f) => {
			const fullPath = path.default.join(dir, f);
			const stat = fs.default.statSync(fullPath);
			return {
				filename: f,
				path: fullPath,
				createdAt: stat.mtime.toISOString(),
				sizeBytes: stat.size,
				verified: false,
				encrypted: f.endsWith(".dxbak"),
				customerCount: 0,
				fileCount: 0
			};
		}).sort((a, b) => b.createdAt.localeCompare(a.createdAt));
	} catch {
		return [];
	}
}
async function runBackupSchedule(opts, dataDir) {
	const dir = dataDir ?? process.cwd();
	if (opts.clear) {
		const config = readAgenticConfig(dir);
		delete config.backupSchedule;
		writeAgenticConfig(dir, config);
		console.log(success("✓ Backup schedule cleared."));
		return;
	}
	if (!opts.every && !opts.status) {
		console.error(error("✗ --every is required (e.g. --every day)"));
		process.exit(1);
		return;
	}
	if (opts.every) {
		const keep = opts.keep ? parseInt(opts.keep, 10) : 7;
		const config = readAgenticConfig(dir);
		config.backupSchedule = {
			every: opts.every,
			keep,
			...opts.weekly ? { weekly: parseInt(opts.weekly, 10) } : {},
			...opts.monthly ? { monthly: parseInt(opts.monthly, 10) } : {},
			...opts.remote ? { remote: opts.remote } : {},
			lastBackup: null
		};
		writeAgenticConfig(dir, config);
		if (!opts.status) console.log(success(`✓ Backup schedule set: every ${opts.every}, keep ${keep} daily${opts.weekly ? ` / ${opts.weekly} weekly` : ""}${opts.monthly ? ` / ${opts.monthly} monthly` : ""}.`));
	}
	if (opts.status) {
		const sched = readAgenticConfig(dir).backupSchedule;
		if (!sched) console.log(info("No backup schedule configured."));
		else {
			console.log(bold("Backup Schedule:"));
			console.log(`  every:      ${sched.every}`);
			console.log(`  keep:       ${sched.keep} daily backups`);
			if (sched.weekly) console.log(`  weekly:     ${sched.weekly} weekly backups`);
			if (sched.monthly) console.log(`  monthly:    ${sched.monthly} monthly backups`);
			if (sched.remote) console.log(`  remote:     ${sched.remote}`);
			console.log(`  lastBackup: ${sched.lastBackup ?? "never"}`);
		}
	}
}
async function runRestore(zipPath, dataDir) {
	const dir = dataDir ?? process.cwd();
	try {
		(0, child_process.execSync)(`unzip -o "${path.default.resolve(zipPath)}" -d "${dir}"`, { cwd: dir });
		console.log(success("✓ Restore complete."));
	} catch (err) {
		console.error(error(`✗ Restore failed: ${err.message}`));
		process.exit(1);
	}
}
/**
* Restore-drill: verify a backup is actually restorable WITHOUT touching live
* data — checks integrity (unzip -t) and that the archive contains the expected
* top-level state (customers/, .agentic/). Returns a report for monitoring.
*/
async function runRestoreDrill(zipPath, opts = {}) {
	const resolved = path.default.resolve(zipPath);
	if (!fs.default.existsSync(resolved)) {
		if (!opts.silent) console.error(error(`✗ File not found: ${zipPath}`));
		return {
			ok: false,
			verified: false,
			hasCustomers: false,
			hasAgentic: false,
			reason: "not_found"
		};
	}
	const verified = verifyBackupFile(resolved);
	let hasCustomers = false;
	let hasAgentic = false;
	if (verified) try {
		const listing = (0, child_process.execSync)(`unzip -l "${resolved}"`, { stdio: "pipe" }).toString();
		hasCustomers = listing.includes("customers/");
		hasAgentic = listing.includes(".agentic/");
	} catch {}
	const ok = verified && hasCustomers;
	if (!opts.silent) if (ok) console.log(success(`✓ Restore drill OK — integrity verified; customers/${hasAgentic ? " + .agentic/" : ""} present`));
	else console.error(error(`✗ Restore drill failed (verified=${verified}, customers=${hasCustomers})`));
	return {
		ok,
		verified,
		hasCustomers,
		hasAgentic
	};
}
const scheduleSubCommand = new commander.Command("schedule").description("Configure automatic backup schedule").option("--every <interval>", "Backup interval (e.g. day)").option("--keep <n>", "Daily backups to keep (default: 7)").option("--weekly <n>", "Weekly backups to keep (e.g. 4)").option("--monthly <n>", "Monthly backups to keep (e.g. 12)").option("--remote <url>", "Remote destination (s3://, rsync://, or local path)").option("--status", "Show current schedule").option("--clear", "Remove backup schedule").action((opts) => runBackupSchedule(opts, process.env["DXCRM_DATA_DIR"] ?? process.cwd()));
const verifySubCommand = new commander.Command("verify").argument("<path>", "Path to backup zip").description("Verify backup integrity (SHA-256 + zip test)").action((zipPath) => runVerify(zipPath));
const drillSubCommand = new commander.Command("drill").argument("<path>", "Path to backup zip").description("Restore-drill: verify a backup is restorable without touching live data").action(async (zipPath) => {
	if (!(await runRestoreDrill(zipPath)).ok) process.exitCode = 1;
});
const listSubCommand = new commander.Command("list").description("List available backups").action(() => {
	const dir = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
	const entries = readBackupLog(dir);
	const fileEntries = listBackupsInDir(dir);
	const combined = entries.length > 0 ? entries : fileEntries;
	if (combined.length === 0) {
		console.log(info("No backups found."));
		return;
	}
	for (const e of combined) {
		const enc = e.encrypted ? " [encrypted]" : "";
		const ver = e.verified ? " ✓" : "";
		const mb = e.sizeBytes > 0 ? ` ${(e.sizeBytes / 1024 / 1024).toFixed(1)} MB` : "";
		console.log(`  ${bold(e.filename)}${enc}${ver}${mb}  ${e.createdAt.slice(0, 10)}`);
	}
});
const backupCommand = new commander.Command("backup").argument("[output]", "Output path for backup zip").description("Backup customers/ + .agentic/ directories").option("--encrypt", "Encrypt the backup (AES-256-GCM)").option("--remote <url>", "Also upload to remote (s3://, rsync://, or path)").action((output, opts) => {
	runBackup(output, process.env["DXCRM_DATA_DIR"] ?? process.cwd(), opts ?? {});
});
backupCommand.addCommand(scheduleSubCommand);
backupCommand.addCommand(verifySubCommand);
backupCommand.addCommand(drillSubCommand);
backupCommand.addCommand(listSubCommand);
new commander.Command("restore").argument("<path>", "Path to backup zip").description("Restore from backup zip").action((zipPath) => runRestore(zipPath, process.env["DXCRM_DATA_DIR"] ?? process.cwd()));
//#endregion
//#region src/fs/audit-log.ts
const AUDIT_LOG_PATH = ".agentic/audit.log";
function getActor() {
	const actor = process.env["DXCRM_ACTOR"];
	return actor && actor.trim().length > 0 ? actor.trim() : "system";
}
function writeAuditEntry(dataDir, entry) {
	const logPath = path.default.join(dataDir, AUDIT_LOG_PATH);
	const logDir = path.default.dirname(logPath);
	if (!fs.default.existsSync(logDir)) fs.default.mkdirSync(logDir, { recursive: true });
	const truncatedSummary = entry.summary.slice(0, 120);
	const line = `${entry.timestamp} | ${entry.actor} | ${entry.tool} | ${entry.slug} | ${truncatedSummary}\n`;
	fs.default.appendFileSync(logPath, line, "utf-8");
}
function readAuditLog(dataDir) {
	const logPath = path.default.join(dataDir, AUDIT_LOG_PATH);
	if (!fs.default.existsSync(logPath)) return [];
	const lines = fs.default.readFileSync(logPath, "utf-8").split("\n");
	const entries = [];
	for (const line of lines) {
		const trimmed = line.trim();
		if (!trimmed) continue;
		const parts = trimmed.split(" | ");
		if (parts.length < 5) continue;
		const [timestamp, actor, tool, slug, ...summaryParts] = parts;
		const summary = summaryParts.join(" | ");
		if (timestamp && actor && tool && slug) entries.push({
			timestamp,
			actor,
			tool,
			slug,
			summary: summary ?? ""
		});
	}
	return entries;
}
function filterAuditLog(entries, opts) {
	let filtered = entries;
	if (opts.slug !== void 0) filtered = filtered.filter((e) => e.slug === opts.slug);
	if (opts.actor !== void 0) filtered = filtered.filter((e) => e.actor === opts.actor);
	if (opts.limit !== void 0) filtered = filtered.slice(-opts.limit);
	return filtered;
}
//#endregion
//#region src/core/rbac.ts
const ALLOWED_TOOLS = {
	admin: [
		"log_interaction",
		"update_deal",
		"update_customer_facts",
		"export_customer",
		"pursue_goal",
		"register_push_subscription",
		"define_custom_object",
		"create_record"
	],
	manager: [
		"log_interaction",
		"update_deal",
		"pursue_goal",
		"create_record"
	],
	rep: [
		"log_interaction",
		"update_deal",
		"create_record"
	]
};
function rbacPath(dataDir) {
	return path.default.join(dataDir, ".agentic", "rbac.json");
}
function getRbacConfig(dataDir) {
	return readJsonFile(rbacPath(dataDir), { actors: {} });
}
function getRole(dataDir, actor) {
	const config = getRbacConfig(dataDir);
	return config.actors[actor] ?? config.default ?? "rep";
}
function canWrite(role, tool) {
	return ALLOWED_TOOLS[role]?.includes(tool) ?? false;
}
function assertCanWrite(role, tool, actor) {
	if (!canWrite(role, tool)) throw new Error(`Access denied: '${actor}' (role: ${role}) cannot use tool '${tool}'`);
}
function enforceRbac(dataDir, tool) {
	if (!fs.default.existsSync(rbacPath(dataDir))) return;
	const actor = process.env["DXCRM_ACTOR"] ?? "system";
	if (actor === "system") return;
	assertCanWrite(getRole(dataDir, actor), tool, actor);
}
function canSeeCustomer(dataDir, actor, slug) {
	if (!fs.default.existsSync(rbacPath(dataDir))) return true;
	if (actor === "system") return true;
	const config = getRbacConfig(dataDir);
	const role = config.actors[actor] ?? config.default ?? "rep";
	if (role === "admin" || role === "manager") return true;
	const owned = config.owned_customers;
	if (!owned) return false;
	return (owned[actor] ?? []).includes(slug);
}
/**
* Build a once-loaded predicate for which customers `actor` may see. Equivalent
* to calling canSeeCustomer per slug, but reads/parses rbac.json a single time
* (and uses O(1) Set membership) — for hot loops like list_customers.
*/
function customerVisibility(dataDir, actor) {
	if (!fs.default.existsSync(rbacPath(dataDir))) return () => true;
	if (actor === "system") return () => true;
	const config = getRbacConfig(dataDir);
	const role = config.actors[actor] ?? config.default ?? "rep";
	if (role === "admin" || role === "manager") return () => true;
	const owned = new Set(config.owned_customers?.[actor] ?? []);
	return (slug) => owned.has(slug);
}
//#endregion
//#region src/core/session-store.ts
let activeSession = null;
function setSession(s) {
	activeSession = s;
}
function getSession() {
	return activeSession;
}
function clearSession() {
	activeSession = null;
}
//#endregion
Object.defineProperty(exports, "MainFactsSchema", {
	enumerable: true,
	get: function() {
		return MainFactsSchema;
	}
});
Object.defineProperty(exports, "assertSafePathSegment", {
	enumerable: true,
	get: function() {
		return assertSafePathSegment;
	}
});
Object.defineProperty(exports, "assertSafeSlug", {
	enumerable: true,
	get: function() {
		return assertSafeSlug;
	}
});
Object.defineProperty(exports, "bold", {
	enumerable: true,
	get: function() {
		return bold;
	}
});
Object.defineProperty(exports, "canSeeCustomer", {
	enumerable: true,
	get: function() {
		return canSeeCustomer;
	}
});
Object.defineProperty(exports, "clearSession", {
	enumerable: true,
	get: function() {
		return clearSession;
	}
});
Object.defineProperty(exports, "customerExists", {
	enumerable: true,
	get: function() {
		return customerExists;
	}
});
Object.defineProperty(exports, "customerVisibility", {
	enumerable: true,
	get: function() {
		return customerVisibility;
	}
});
Object.defineProperty(exports, "enforceRbac", {
	enumerable: true,
	get: function() {
		return enforceRbac;
	}
});
Object.defineProperty(exports, "ensureCustomerDir", {
	enumerable: true,
	get: function() {
		return ensureCustomerDir;
	}
});
Object.defineProperty(exports, "error", {
	enumerable: true,
	get: function() {
		return error;
	}
});
Object.defineProperty(exports, "filterAuditLog", {
	enumerable: true,
	get: function() {
		return filterAuditLog;
	}
});
Object.defineProperty(exports, "getActor", {
	enumerable: true,
	get: function() {
		return getActor;
	}
});
Object.defineProperty(exports, "getRbacConfig", {
	enumerable: true,
	get: function() {
		return getRbacConfig;
	}
});
Object.defineProperty(exports, "getRole", {
	enumerable: true,
	get: function() {
		return getRole;
	}
});
Object.defineProperty(exports, "getSession", {
	enumerable: true,
	get: function() {
		return getSession;
	}
});
Object.defineProperty(exports, "info", {
	enumerable: true,
	get: function() {
		return info;
	}
});
Object.defineProperty(exports, "isSafePathSegment", {
	enumerable: true,
	get: function() {
		return isSafePathSegment;
	}
});
Object.defineProperty(exports, "listBackupsInDir", {
	enumerable: true,
	get: function() {
		return listBackupsInDir;
	}
});
Object.defineProperty(exports, "listCustomerSlugs", {
	enumerable: true,
	get: function() {
		return listCustomerSlugs;
	}
});
Object.defineProperty(exports, "readAuditLog", {
	enumerable: true,
	get: function() {
		return readAuditLog;
	}
});
Object.defineProperty(exports, "readBackupLog", {
	enumerable: true,
	get: function() {
		return readBackupLog;
	}
});
Object.defineProperty(exports, "readJsonArray", {
	enumerable: true,
	get: function() {
		return readJsonArray;
	}
});
Object.defineProperty(exports, "readJsonFile", {
	enumerable: true,
	get: function() {
		return readJsonFile;
	}
});
Object.defineProperty(exports, "readMainFacts", {
	enumerable: true,
	get: function() {
		return readMainFacts;
	}
});
Object.defineProperty(exports, "runBackup", {
	enumerable: true,
	get: function() {
		return runBackup;
	}
});
Object.defineProperty(exports, "setSession", {
	enumerable: true,
	get: function() {
		return setSession;
	}
});
Object.defineProperty(exports, "success", {
	enumerable: true,
	get: function() {
		return success;
	}
});
Object.defineProperty(exports, "warning", {
	enumerable: true,
	get: function() {
		return warning;
	}
});
Object.defineProperty(exports, "writeAuditEntry", {
	enumerable: true,
	get: function() {
		return writeAuditEntry;
	}
});
Object.defineProperty(exports, "writeJsonArray", {
	enumerable: true,
	get: function() {
		return writeJsonArray;
	}
});
Object.defineProperty(exports, "writeJsonFile", {
	enumerable: true,
	get: function() {
		return writeJsonFile;
	}
});
Object.defineProperty(exports, "writeMainFacts", {
	enumerable: true,
	get: function() {
		return writeMainFacts;
	}
});

//# sourceMappingURL=session-store-yfwnj0OC.cjs.map