{"version":3,"sources":["../src/internal/api/auth.ts"],"sourcesContent":["/**\n * Authentication header assembly for LangWatch SDK clients.\n *\n * Supports two token families that share the same HTTP surface:\n *\n *   1. `sk-lw-{random}` — legacy project API keys. The token itself carries\n *      the project identity, so we emit both `Authorization: Bearer <token>`\n *      and `X-Auth-Token: <token>` for backwards compatibility.\n *\n *   2. `sk-lw-{lookupId}_{secret}` or `pat-lw-{lookupId}_{secret}` — API\n *      keys (user-scoped). Must be paired with a `projectId` so the server\n *      can resolve the correct role binding. When a `projectId` is available\n *      we encode both into `Authorization: Basic base64(projectId:token)`.\n */\n\n/** Old PAT prefix — still accepted by the server for backward compat. */\nconst LEGACY_PAT_PREFIX = \"pat-lw-\";\n\n/** Unified API key prefix — also used by legacy project keys. */\nconst API_KEY_PREFIX = \"sk-lw-\";\n\nexport interface LangWatchAuthHeadersInput {\n  /** API key token. May be empty; in that case no auth headers are emitted. */\n  apiKey: string;\n  /**\n   * Project identifier. Required for user-scoped API keys to resolve scope;\n   * optional for legacy project keys (the token already encodes project identity).\n   * Falls back to `LANGWATCH_PROJECT_ID` when omitted.\n   */\n  projectId?: string;\n}\n\nexport type LangWatchAuthHeaders = Record<string, string>;\n\n/**\n * Returns `true` when the supplied credential is a user-scoped API key\n * (as opposed to a legacy project key).\n *\n * Detection heuristics:\n *   - `pat-lw-*` → always a user-scoped key (old format)\n *   - `sk-lw-{chars}_{chars}` → user-scoped key (new format, has underscore)\n *   - `sk-lw-{chars}` (no underscore) → legacy project key\n */\nexport const isUserScopedApiKey = (token: string): boolean => {\n  if (token.startsWith(LEGACY_PAT_PREFIX)) return true;\n  if (token.startsWith(API_KEY_PREFIX)) {\n    const body = token.slice(API_KEY_PREFIX.length);\n    return body.includes(\"_\");\n  }\n  return false;\n};\n\n/** @deprecated Use `isUserScopedApiKey` instead. Kept for backward compat. */\nexport const isPersonalAccessToken = isUserScopedApiKey;\n\n/**\n * Builds the HTTP headers required to authenticate against the LangWatch\n * API using either a legacy project key or a user-scoped API key.\n */\nexport const buildAuthHeaders = ({\n  apiKey,\n  projectId,\n}: LangWatchAuthHeadersInput): LangWatchAuthHeaders => {\n  if (!apiKey) return {};\n\n  const resolvedProjectId =\n    projectId ?? process.env.LANGWATCH_PROJECT_ID ?? undefined;\n\n  if (isUserScopedApiKey(apiKey)) {\n    if (resolvedProjectId) {\n      // Basic Auth is the canonical carrier — the server extracts both\n      // the project and the token from one header.\n      const encoded = Buffer.from(\n        `${resolvedProjectId}:${apiKey}`,\n        \"utf-8\",\n      ).toString(\"base64\");\n      return { authorization: `Basic ${encoded}` };\n    }\n\n    // API key without a projectId: use Bearer and let the server reject\n    // unresolvable requests.\n    return {\n      authorization: `Bearer ${apiKey}`,\n      \"x-auth-token\": apiKey,\n    };\n  }\n\n  // Legacy sk-lw-* project key: preserve the dual-header shape.\n  return {\n    authorization: `Bearer ${apiKey}`,\n    \"x-auth-token\": apiKey,\n  };\n};\n"],"mappings":";AAgBA,IAAM,oBAAoB;AAG1B,IAAM,iBAAiB;AAwBhB,IAAM,qBAAqB,CAAC,UAA2B;AAC5D,MAAI,MAAM,WAAW,iBAAiB,EAAG,QAAO;AAChD,MAAI,MAAM,WAAW,cAAc,GAAG;AACpC,UAAM,OAAO,MAAM,MAAM,eAAe,MAAM;AAC9C,WAAO,KAAK,SAAS,GAAG;AAAA,EAC1B;AACA,SAAO;AACT;AAGO,IAAM,wBAAwB;AAM9B,IAAM,mBAAmB,CAAC;AAAA,EAC/B;AAAA,EACA;AACF,MAAuD;AA9DvD;AA+DE,MAAI,CAAC,OAAQ,QAAO,CAAC;AAErB,QAAM,qBACJ,qCAAa,QAAQ,IAAI,yBAAzB,YAAiD;AAEnD,MAAI,mBAAmB,MAAM,GAAG;AAC9B,QAAI,mBAAmB;AAGrB,YAAM,UAAU,OAAO;AAAA,QACrB,GAAG,iBAAiB,IAAI,MAAM;AAAA,QAC9B;AAAA,MACF,EAAE,SAAS,QAAQ;AACnB,aAAO,EAAE,eAAe,SAAS,OAAO,GAAG;AAAA,IAC7C;AAIA,WAAO;AAAA,MACL,eAAe,UAAU,MAAM;AAAA,MAC/B,gBAAgB;AAAA,IAClB;AAAA,EACF;AAGA,SAAO;AAAA,IACL,eAAe,UAAU,MAAM;AAAA,IAC/B,gBAAgB;AAAA,EAClB;AACF;","names":[]}