import {
  authenticateToolRequest
} from "./chunk-RH74YJIK.js";
import {
  dispatchAppTool,
  outcomeStatus
} from "./chunk-PPSZNVKT.js";

// src/crypto/web-token.ts
function base64UrlEncode(bytes) {
  let bin = "";
  for (const b of bytes) bin += String.fromCharCode(b);
  return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}
function base64UrlEncodeText(text) {
  return base64UrlEncode(new TextEncoder().encode(text));
}
function base64UrlDecodeText(value) {
  const padded = value.replace(/-/g, "+").replace(/_/g, "/").padEnd(Math.ceil(value.length / 4) * 4, "=");
  const bin = atob(padded);
  const bytes = new Uint8Array(bin.length);
  for (let i = 0; i < bin.length; i += 1) bytes[i] = bin.charCodeAt(i);
  return new TextDecoder().decode(bytes);
}
async function hmacSha256Base64Url(message, secret) {
  const enc = new TextEncoder();
  const key = await crypto.subtle.importKey("raw", enc.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
  const sig = await crypto.subtle.sign("HMAC", key, enc.encode(message));
  return base64UrlEncode(new Uint8Array(sig));
}
function constantTimeEqual(a, b) {
  if (a.length !== b.length) return false;
  let diff = 0;
  for (let i = 0; i < a.length; i += 1) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
  return diff === 0;
}

// src/tools/capability.ts
async function createCapabilityToken(userId, opts) {
  const secret = opts.secret?.trim();
  if (!secret) return void 0;
  const prefix = opts.prefix ?? "cap_";
  return `${prefix}${await sign(userId, secret)}`;
}
async function verifyCapabilityToken(userId, token, opts) {
  const secret = opts.secret?.trim();
  const prefix = opts.prefix ?? "cap_";
  if (!secret || !token.startsWith(prefix)) return false;
  const expected = `${prefix}${await sign(userId, secret)}`;
  return constantTimeEqual(token, expected);
}
async function createExpiringCapabilityToken(subject, opts) {
  const secret = opts.secret?.trim();
  if (!secret) return void 0;
  if (!Number.isFinite(opts.expiresInMs) || opts.expiresInMs <= 0) throw new Error("expiresInMs must be a positive number");
  const prefix = opts.prefix ?? "cap_";
  const now = opts.now ?? Date.now;
  const payload = base64UrlEncodeText(JSON.stringify({ sub: subject, exp: now() + opts.expiresInMs, n: crypto.randomUUID() }));
  return `${prefix}${payload}.${await hmacSha256Base64Url(payload, secret)}`;
}
async function verifyExpiringCapabilityToken(subject, token, opts) {
  const secret = opts.secret?.trim();
  const prefix = opts.prefix ?? "cap_";
  if (!secret || !token.startsWith(prefix)) return false;
  const body = token.slice(prefix.length);
  const dot = body.lastIndexOf(".");
  if (dot <= 0 || dot === body.length - 1) return false;
  const payload = body.slice(0, dot);
  const sig = body.slice(dot + 1);
  if (!constantTimeEqual(sig, await hmacSha256Base64Url(payload, secret))) return false;
  let parsed;
  try {
    parsed = JSON.parse(base64UrlDecodeText(payload));
  } catch {
    return false;
  }
  if (parsed.sub !== subject) return false;
  if (typeof parsed.exp !== "number") return false;
  const now = opts.now ?? Date.now;
  return parsed.exp > now();
}
async function sign(userId, secret) {
  return hmacSha256Base64Url(`user:${userId}`, secret);
}

// src/tools/gating.ts
function resolveToolCapabilities(opts) {
  const { taxonomy, capabilities, enabled } = opts;
  if (enabled === void 0) {
    return {
      proposalTypes: [...taxonomy.proposalTypes],
      toolGroups: [...new Set(capabilities.flatMap((c) => c.toolGroups ?? []))]
    };
  }
  const base = new Set(
    opts.baseProposalTypes ?? capabilities.flatMap((c) => c.proposalTypes ?? [])
  );
  const domainTypes = taxonomy.proposalTypes.filter((t) => !base.has(t));
  const byId = new Map(capabilities.map((c) => [c.id, c]));
  const proposalTypes = /* @__PURE__ */ new Set();
  const toolGroups = /* @__PURE__ */ new Set();
  for (const id of enabled) {
    const cap = byId.get(id);
    if (!cap) continue;
    for (const t of cap.proposalTypes ?? []) {
      if (taxonomy.proposalTypes.includes(t)) proposalTypes.add(t);
    }
    if (cap.domainActions) for (const t of domainTypes) proposalTypes.add(t);
    for (const g of cap.toolGroups ?? []) toolGroups.add(g);
  }
  return { proposalTypes: [...proposalTypes], toolGroups: [...toolGroups] };
}
function restrictTaxonomy(taxonomy, allowed) {
  const allow = new Set(allowed);
  return {
    proposalTypes: taxonomy.proposalTypes.filter((t) => allow.has(t)),
    regulatedTypes: taxonomy.regulatedTypes.filter((t) => allow.has(t))
  };
}

// src/tools/http.ts
async function handleAppToolRequest(request, opts) {
  if (request.method !== "POST") return Response.json({ error: "Method not allowed" }, { status: 405 });
  const auth = await authenticateToolRequest(request, { verifyToken: opts.verifyToken, headerNames: opts.headerNames });
  if (!auth.ok) return auth.response;
  let body;
  try {
    body = await request.json();
  } catch {
    return Response.json({ error: "Invalid JSON" }, { status: 400 });
  }
  const args = body.args ?? body.arguments ?? body;
  const outcome = await dispatchAppTool(opts.tool, args, auth.ctx, opts);
  if (!outcome.ok) {
    return Response.json({ error: outcome.code, message: outcome.message }, { status: outcomeStatus(outcome) });
  }
  const payload = outcome.result;
  return Response.json({ ok: true, ...payload, ...opts.message ? { message: opts.message(outcome.result) } : {} });
}

export {
  base64UrlEncodeText,
  base64UrlDecodeText,
  hmacSha256Base64Url,
  constantTimeEqual,
  createCapabilityToken,
  verifyCapabilityToken,
  createExpiringCapabilityToken,
  verifyExpiringCapabilityToken,
  resolveToolCapabilities,
  restrictTaxonomy,
  handleAppToolRequest
};
//# sourceMappingURL=chunk-FDJ6JQCI.js.map