import { r as writeJsonArray, t as readJsonArray } from "./json-store-WWsFzXub.js";
import path from "path";
import { createHash, randomBytes, timingSafeEqual } from "crypto";
//#region src/mcp/auth.ts
function tokensPath(dataDir) {
	return path.join(dataDir, ".agentic", "mcp-tokens.json");
}
/** SHA-256 hex of a token. Only hashes are ever persisted. */
function hashToken(token) {
	return createHash("sha256").update(token).digest("hex");
}
function loadMcpTokens(dataDir) {
	return readJsonArray(tokensPath(dataDir), "tokens");
}
/**
* Whether the HTTP MCP endpoint must require a bearer token.
* - `DXCRM_MCP_AUTH=required` forces auth on (even with no tokens yet).
* - `DXCRM_MCP_AUTH=off` forces it off.
* - Otherwise: on as soon as at least one token is configured (opt-in by
*   provisioning a token; stays open for local/firewalled dev by default).
*/
function isAuthRequired(dataDir) {
	const mode = process.env["DXCRM_MCP_AUTH"];
	if (mode === "required") return true;
	if (mode === "off") return false;
	return loadMcpTokens(dataDir).length > 0;
}
/** Validate an `Authorization: Bearer <token>` header against stored hashes. */
function verifyBearer(authHeader, dataDir) {
	if (!authHeader || !authHeader.startsWith("Bearer ")) return { ok: false };
	const token = authHeader.slice(7).trim();
	if (!token) return { ok: false };
	const candidate = hashToken(token);
	const candidateBuf = Buffer.from(candidate, "hex");
	for (const rec of loadMcpTokens(dataDir)) {
		if (rec.hash.length !== candidate.length) continue;
		let recBuf;
		try {
			recBuf = Buffer.from(rec.hash, "hex");
		} catch {
			continue;
		}
		if (recBuf.length === candidateBuf.length && timingSafeEqual(recBuf, candidateBuf)) return {
			ok: true,
			actor: rec.actor,
			role: rec.role
		};
	}
	return { ok: false };
}
/**
* Mint a new token: generates a random secret, persists only its hash mapped
* to an actor/role, and returns the plaintext ONCE (never stored).
*/
function createMcpToken(dataDir, actor, role, label) {
	const token = randomBytes(24).toString("base64url");
	const records = loadMcpTokens(dataDir);
	records.push({
		hash: hashToken(token),
		actor,
		role,
		...label ? { label } : {},
		createdAt: (/* @__PURE__ */ new Date()).toISOString()
	});
	writeJsonArray(tokensPath(dataDir), "tokens", records);
	return token;
}
/** RFC 9728 OAuth 2.0 Protected Resource Metadata document. */
function protectedResourceMetadata(resourceUrl) {
	return {
		resource: resourceUrl,
		authorization_servers: [],
		bearer_methods_supported: ["header"],
		scopes_supported: ["crm:read", "crm:write"]
	};
}
/** Value for the `WWW-Authenticate` header on a 401 (RFC 9728 §5.1). */
function wwwAuthenticateHeader(metadataUrl) {
	return `Bearer resource_metadata="${metadataUrl}"`;
}
//#endregion
export { protectedResourceMetadata as a, loadMcpTokens as i, hashToken as n, verifyBearer as o, isAuthRequired as r, wwwAuthenticateHeader as s, createMcpToken as t };

//# sourceMappingURL=auth-DDXZTwS0.js.map