import { i as writeJsonFile, n as readJsonFile } from "./json-store-WWsFzXub.js";
import path from "path";
import fs from "fs";
//#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.join(dataDir, ".agentic", "rbac.json");
}
function getRbacConfig(dataDir) {
	return readJsonFile(rbacPath(dataDir), { actors: {} });
}
function setActorRole(dataDir, actor, role) {
	const config = getRbacConfig(dataDir);
	config.actors[actor] = role;
	writeJsonFile(rbacPath(dataDir), config);
}
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.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.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.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);
}
/** Load the field-level ACL (field → allowed roles) from rbac.json. */
function loadFieldAcl(dataDir) {
	return getRbacConfig(dataDir).field_acl ?? {};
}
/** Whether a role may see a field given the ACL (fields not in the ACL are public). */
function canSeeField(field, role, acl) {
	const allowed = acl[field];
	if (!allowed) return true;
	return allowed.includes(role);
}
/** Return a copy of `values` with fields the role may not see removed. */
function redactFields(values, role, acl) {
	const out = {};
	for (const [k, v] of Object.entries(values)) if (canSeeField(k, role, acl)) out[k] = v;
	return out;
}
//#endregion
export { customerVisibility as a, getRole as c, setActorRole as d, canWrite as i, loadFieldAcl as l, canSeeCustomer as n, enforceRbac as o, canSeeField as r, getRbacConfig as s, assertCanWrite as t, redactFields as u };

//# sourceMappingURL=rbac-msmBc_tK.js.map