// src/routing/engine.ts
var DEFAULT_CATEGORIES = [
  "fact",
  "preference",
  "correction",
  "entity",
  "decision",
  "relationship",
  "principle",
  "commitment",
  "moment",
  "skill",
  "rule",
  "procedure",
  "reasoning_trace"
];
function normalizeNamespace(namespace) {
  return namespace.trim();
}
function isLikelyUnsafeRegex(pattern) {
  const value = pattern.trim();
  if (value.length === 0) return true;
  if (value.length > 120) return true;
  if (/\\[1-9]/.test(value)) return true;
  if (/\(\?<?[=!]/.test(value)) return true;
  if (/\((?:[^()\\]|\\.)*[+*](?:[^()\\]|\\.)*\)[+*{]/.test(value)) return true;
  if (/(^|[^\\])[()|]/.test(value)) return true;
  const quantifierCount = (value.match(/(^|[^\\])[*+?]/g)?.length ?? 0) + (value.match(/(^|[^\\])\{/g)?.length ?? 0);
  if (quantifierCount > 1) return true;
  return false;
}
function isSafeRouteNamespace(namespace) {
  const value = normalizeNamespace(namespace);
  if (value.length === 0) return false;
  if (value === ".") return false;
  if (value.includes("/") || value.includes("\\")) return false;
  if (value.includes("..")) return false;
  return /^[A-Za-z0-9._-]{1,64}$/.test(value);
}
function validateRouteTarget(target, options) {
  if (!target || typeof target !== "object") {
    return { ok: false, error: "target must be an object" };
  }
  const allowedCategories = new Set(options?.allowedCategories ?? DEFAULT_CATEGORIES);
  const allowedNamespaces = options?.allowedNamespaces ? new Set(options.allowedNamespaces.map((v) => v.trim()).filter((v) => v.length > 0)) : null;
  const normalized = {};
  if (typeof target.category === "string") {
    if (!allowedCategories.has(target.category)) {
      return { ok: false, error: `invalid category: ${target.category}` };
    }
    normalized.category = target.category;
  }
  if (typeof target.namespace === "string") {
    const namespace = normalizeNamespace(target.namespace);
    if (!isSafeRouteNamespace(namespace)) {
      return { ok: false, error: `invalid namespace: ${target.namespace}` };
    }
    if (allowedNamespaces && !allowedNamespaces.has(namespace)) {
      return { ok: false, error: `namespace not allowed: ${namespace}` };
    }
    normalized.namespace = namespace;
  }
  if (!normalized.category && !normalized.namespace) {
    return { ok: false, error: "target must include category or namespace" };
  }
  return { ok: true, target: normalized };
}
function doesRuleMatch(rule, text) {
  if (!rule || typeof rule !== "object") return false;
  if (rule.enabled === false) return false;
  if (typeof rule.pattern !== "string") return false;
  const pattern = rule.pattern.trim();
  if (pattern.length === 0) return false;
  if (rule.patternType === "keyword") {
    return text.toLowerCase().includes(pattern.toLowerCase());
  }
  if (rule.patternType !== "regex") {
    return false;
  }
  if (isLikelyUnsafeRegex(pattern)) {
    return false;
  }
  try {
    return new RegExp(pattern, "i").test(text);
  } catch {
    return false;
  }
}
function selectRouteRule(text, rules, options) {
  const ranked = rules.map((rule, index) => ({ rule, index })).sort((a, b) => {
    if (b.rule.priority !== a.rule.priority) return b.rule.priority - a.rule.priority;
    return a.index - b.index;
  });
  for (const entry of ranked) {
    if (!doesRuleMatch(entry.rule, text)) continue;
    const validation = validateRouteTarget(entry.rule.target, options);
    if (!validation.ok || !validation.target) continue;
    return {
      rule: entry.rule,
      target: validation.target
    };
  }
  return null;
}

export {
  isSafeRouteNamespace,
  validateRouteTarget,
  selectRouteRule
};
//# sourceMappingURL=chunk-2LGMW3DJ.js.map