{"version":3,"sources":["../src/lib/schemas.ts","../src/lib/cache.ts","../src/lib/domain.ts","../src/lib/license-state.ts","../src/lib/resolve-api-base.ts","../src/lib/polar-client.ts","../src/lib/trial.ts"],"names":["PolarValidateResponseSchema","z","PolarActivateResponseSchema","LicenseCacheSchema","CACHE_PREFIX","CACHE_TTL_MS","hashKey","key","hash","i","readCache","domain","raw","json","parsed","clearCache","writeCache","state","entry","hasFreshCache","DEV_HOSTNAMES","DEV_SUFFIX","EPHEMERAL_HOST_PATTERNS","IP_HOST","getCurrentDomain","isDevEnvironment","isEphemeralHost","pattern","validateDomainAtRender","activationLabel","currentDomain","normalizeLicenseKey","createUnlicensedState","now","createDevBypassState","createPreviewBypassState","DEFAULT_API_BASE","readEnv","name","value","resolveApiBase","override","nextPublic","bare","PolarApiError","statusCode","message","PolarParseError","zodError","transformValidateResponse","transformActivateResponse","validateKey","organizationId","activationId","options","body","res","activateKey","label","deactivateKey","generateRenderKey","input","warnedDomains","warnActivationLimitReached","validateLicenseKey","orgId","normalizedKey","cached","response","serverValidatedAt","usage","activateResponse","activationError","overLimitState","error","getDaysLeft","config","trustedNow","elapsedMs","elapsedDays","remaining"],"mappings":"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","file":"headless.cjs","sourcesContent":["import { z } from 'zod'\n\n/**\n * Polar validate response schema — snake_case matching wire format.\n *\n * `.passthrough()` is load-bearing for forward-compat during the Polar →\n * tourkit-dash issuer migration (plan/15c §\"additive `tk_tier`\"). The\n * tourkit-dash issuer will eventually add fields like `tk_tier`,\n * `tk_issuer_id`, and `tk_claim_status`; v1.x SDKs must parse and ignore\n * them so customers on v1.x continue to function while v2.x readers pick up\n * the new semantics. The companion regression test\n * `schema-no-tier.regression.test.ts` pins that **Polar itself** still does\n * not emit `tier`; unknown additive fields from either issuer are allowed.\n */\nexport const PolarValidateResponseSchema = z.looseObject({\n  id: z.string(),\n  organization_id: z.string(),\n  status: z.enum(['granted', 'revoked', 'disabled']),\n  key: z.string(),\n  limit_activations: z.number().nullable(),\n  usage: z.number(),\n  validations: z.number(),\n  last_validated_at: z.string(),\n  expires_at: z.string().nullable(),\n  activation: z\n    .looseObject({\n      id: z.string(),\n      license_key_id: z.string(),\n      label: z.string(),\n      meta: z.record(z.string(), z.unknown()),\n      created_at: z.string(),\n      modified_at: z.string().nullable(),\n    })\n    .nullable(),\n})\n\n/**\n * Polar activate response schema — snake_case matching wire format.\n *\n * Same `.passthrough()` discipline as the validate response. The tourkit-dash\n * `/v1/license/activate` endpoint is wire-compatible with Polar's\n * `/customer-portal/license-keys/activate` per plan/15e §\"byte-equality\"; any\n * additive `tk_*` fields land transparently for v1.x readers.\n */\nexport const PolarActivateResponseSchema = z.looseObject({\n  id: z.string(),\n  license_key_id: z.string(),\n  label: z.string(),\n  meta: z.record(z.string(), z.unknown()),\n  created_at: z.string(),\n  modified_at: z.string().nullable(),\n  license_key: z.looseObject({\n    id: z.string(),\n    organization_id: z.string(),\n    status: z.enum(['granted', 'revoked', 'disabled']),\n    limit_activations: z.number().nullable(),\n    usage: z.number(),\n    limit_usage: z.number().nullable(),\n    validations: z.number(),\n    last_validated_at: z.string(),\n    expires_at: z.string().nullable(),\n  }),\n})\n\n/**\n * Cache schema — flat LicenseState shape.\n *\n * `keyHash` is optional for backward compatibility with v1.0.x cache entries\n * that predate the per-key hash. New entries always set it; readers ignore the\n * field when the caller does not pass a current `key` to compare against.\n */\nexport const LicenseCacheSchema = z.object({\n  state: z.object({\n    status: z.enum(['valid', 'invalid', 'expired', 'revoked', 'loading', 'error']),\n    tier: z.enum(['free', 'pro']),\n    activations: z.number(),\n    maxActivations: z.number(),\n    domain: z.string().nullable(),\n    expiresAt: z.string().nullable(),\n    validatedAt: z.number(),\n    /**\n     * Optional for backward compatibility with v1.0.x cache entries that\n     * predate the Polar server-anchor field. Readers parse cached states\n     * unchanged; writers added in Phase 8 always set it when Polar emits\n     * `last_validated_at`.\n     */\n    serverValidatedAt: z.number().nullable().optional(),\n    renderKey: z.string().optional(),\n  }),\n  cachedAt: z.number(),\n  domain: z.string(),\n  keyHash: z.string().optional(),\n})\n","import type { LicenseCache, LicenseState } from '../types'\nimport { LicenseCacheSchema } from './schemas'\n\nconst CACHE_PREFIX = 'tourkit:license:'\nconst CACHE_TTL_MS = 72 * 60 * 60 * 1000 // 72 hours\n\n// Deterministic short hash. Not a security primitive — used only to bind a\n// cache entry to the license key it was issued for, so switching `licenseKey`\n// in <LicenseProvider> does not return another key's cached state.\nfunction hashKey(key: string): string {\n  let hash = 0\n  for (let i = 0; i < key.length; i++) {\n    hash = ((hash << 5) - hash + key.charCodeAt(i)) | 0\n  }\n  return Math.abs(hash).toString(36)\n}\n\nexport function readCache(domain: string, key?: string): LicenseState | null {\n  if (typeof window === 'undefined') return null\n  try {\n    const raw = localStorage.getItem(`${CACHE_PREFIX}${domain}`)\n    if (!raw) return null\n    const json: unknown = JSON.parse(raw)\n    const parsed = LicenseCacheSchema.safeParse(json)\n    if (!parsed.success) {\n      clearCache(domain)\n      return null\n    }\n    if (Date.now() - parsed.data.cachedAt > CACHE_TTL_MS) {\n      clearCache(domain)\n      return null\n    }\n    if (\n      key !== undefined &&\n      parsed.data.keyHash !== undefined &&\n      parsed.data.keyHash !== hashKey(key)\n    ) {\n      clearCache(domain)\n      return null\n    }\n    return parsed.data.state as LicenseState\n  } catch {\n    clearCache(domain)\n    return null\n  }\n}\n\nexport function writeCache(domain: string, state: LicenseState, key?: string): void {\n  if (typeof window === 'undefined') return\n  try {\n    const entry: LicenseCache = {\n      state,\n      cachedAt: Date.now(),\n      domain,\n      ...(key !== undefined ? { keyHash: hashKey(key) } : {}),\n    }\n    localStorage.setItem(`${CACHE_PREFIX}${domain}`, JSON.stringify(entry))\n  } catch {\n    // localStorage quota exceeded — fail silently\n  }\n}\n\nexport function clearCache(domain: string): void {\n  if (typeof window === 'undefined') return\n  localStorage.removeItem(`${CACHE_PREFIX}${domain}`)\n}\n\n/**\n * Returns true if a non-expired, valid cache entry exists for this domain.\n * Pass `key` to also require the cached entry's keyHash to match the current\n * license key. Used by error-state handling: error + fresh cache = grace\n * period (licensed), error + no cache = unlicensed.\n */\nexport function hasFreshCache(domain: string, key?: string): boolean {\n  return readCache(domain, key) !== null\n}\n","const DEV_HOSTNAMES = ['localhost', '127.0.0.1']\nconst DEV_SUFFIX = '.local'\n\n/**\n * Throwaway / preview hostnames that change on every deploy. Activating these\n * would silently burn the customer's finite Polar activation slots — a single\n * busy Vercel/Netlify preview workflow can exhaust a 5-slot key in days. We\n * skip activation for them entirely (Pro stays unlocked, no watermark, no slot\n * consumed). Stable production hosts — including a bare `project.vercel.app` —\n * are deliberately NOT matched here, so real deployments still require a key.\n *\n * Patterns are intentionally narrow: they target the branch/hash/deploy-preview\n * segments that only ephemeral URLs carry, never the production alias.\n */\nconst EPHEMERAL_HOST_PATTERNS: RegExp[] = [\n  // Vercel previews: project-git-branch-team.vercel.app, project-<hash>-team.vercel.app\n  /-git-[^.]+\\.vercel\\.app$/i,\n  /-[a-z0-9]{9,}-[^.]+\\.vercel\\.app$/i,\n  // Netlify branch deploys / deploy previews: branch--site.netlify.app, deploy-preview-123--site.netlify.app\n  /--[^.]+\\.netlify\\.app$/i,\n  // Cloudflare Pages previews: <hash>.<project>.pages.dev\n  /^[a-z0-9]{8}\\.[^.]+\\.pages\\.dev$/i,\n  // Local tunnels used during dev/demo\n  /\\.ngrok(?:-free)?\\.app$/i,\n  /\\.ngrok\\.io$/i,\n  /\\.loca\\.lt$/i,\n  /\\.trycloudflare\\.com$/i,\n]\n\n// Bare IPv4 / IPv6 hosts are never a licensed production domain.\nconst IP_HOST = /^(?:\\d{1,3}\\.){3}\\d{1,3}$|^\\[?[0-9a-f]*:[0-9a-f:]+\\]?$/i\n\nexport function getCurrentDomain(): string | null {\n  if (typeof window === 'undefined') return null\n  return window.location.hostname\n}\n\nexport function isDevEnvironment(): boolean {\n  const domain = getCurrentDomain()\n  if (!domain) return false\n  return DEV_HOSTNAMES.includes(domain) || domain.endsWith(DEV_SUFFIX)\n}\n\n/**\n * True for ephemeral preview/tunnel hosts (see `EPHEMERAL_HOST_PATTERNS`) and\n * raw IP hosts. Callers treat these like dev: skip Polar, unlock Pro, consume\n * no activation slot. `isDevEnvironment()` hosts are excluded since they are\n * already handled by the dev bypass upstream.\n */\nexport function isEphemeralHost(domain: string | null = getCurrentDomain()): boolean {\n  if (!domain) return false\n  if (IP_HOST.test(domain)) return true\n  return EPHEMERAL_HOST_PATTERNS.some((pattern) => pattern.test(domain))\n}\n\n/**\n * Compares current hostname against the stored activation label.\n * Logs a console warning on mismatch. Soft enforcement only —\n * returns boolean but never blocks rendering.\n */\nexport function validateDomainAtRender(activationLabel: string): boolean {\n  const currentDomain = getCurrentDomain()\n  if (!currentDomain) return true // SSR — cannot check, assume ok\n  if (isDevEnvironment()) return true // dev — always pass\n\n  if (currentDomain !== activationLabel) {\n    console.warn(\n      `[tour-kit/license] Domain mismatch: license activated for \"${activationLabel}\" but running on \"${currentDomain}\". Components will render with a watermark. Activate this domain in your Polar dashboard or contact support.`\n    )\n    return false\n  }\n  return true\n}\n","import type { LicenseState } from '../types'\n\n/**\n * Trim a raw license key. Used everywhere a key is checked for presence,\n * compared, hashed for cache, or sent to Polar so that accidental whitespace\n * (env var with trailing newline, copy-pasted with spaces) is normalized\n * exactly once.\n */\nexport function normalizeLicenseKey(key: string): string {\n  return key.trim()\n}\n\n/**\n * True when the key has at least one non-whitespace character.\n *\n * Empty and whitespace-only keys are unlicensed on every host — including\n * localhost. The dev bypass only applies when a non-empty key is configured.\n */\nexport function hasLicenseKey(key: string): boolean {\n  return normalizeLicenseKey(key).length > 0\n}\n\n/**\n * Canonical unlicensed state. Returned whenever the configured key is missing\n * or blank. Kept as `status: 'invalid'` (instead of introducing a new `missing`\n * status) so downstream gating logic in `<LicenseGate>`, `<ProGate>`, and\n * `useLicenseGate()` keeps working without type churn.\n */\nexport function createUnlicensedState(now: number = Date.now()): LicenseState {\n  return {\n    status: 'invalid',\n    tier: 'free',\n    activations: 0,\n    maxActivations: 0,\n    domain: null,\n    expiresAt: null,\n    validatedAt: now,\n    serverValidatedAt: null,\n    renderKey: undefined,\n  }\n}\n\n/**\n * Canonical dev-bypass state. Returned on localhost / 127.0.0.1 / *.local when\n * a non-empty key is configured. Skips Polar so local dev does not consume\n * activation slots — but only when the developer has at least set a key, so a\n * missing env var still surfaces as an unlicensed watermark before deploy.\n */\nexport function createDevBypassState(now: number = Date.now()): LicenseState {\n  return {\n    status: 'valid',\n    tier: 'pro',\n    activations: 0,\n    maxActivations: 0,\n    domain: null,\n    expiresAt: null,\n    validatedAt: now,\n    serverValidatedAt: null,\n    renderKey: 'dev_bypass',\n  }\n}\n\n/**\n * Canonical preview-bypass state. Returned on ephemeral / preview hosts\n * (Vercel/Netlify/Cloudflare preview URLs, tunnels, raw IPs — see\n * `isEphemeralHost`). Like the dev bypass it unlocks Pro and skips Polar so a\n * throwaway deploy URL never consumes one of the key's finite activation slots.\n * A distinct `renderKey` keeps the debug panel and any anti-bypass consumer\n * able to tell a preview bypass apart from a localhost dev bypass.\n */\nexport function createPreviewBypassState(now: number = Date.now()): LicenseState {\n  return {\n    status: 'valid',\n    tier: 'pro',\n    activations: 0,\n    maxActivations: 0,\n    domain: null,\n    expiresAt: null,\n    validatedAt: now,\n    serverValidatedAt: null,\n    renderKey: 'preview_bypass',\n  }\n}\n","/**\n * Default issuer URL. Polar in v1.x; flips to tourkit-dash in v2.x at T+90\n * per plan/15m. v1.x customers point at tourkit-dash by overriding this\n * default — never by upgrading the SDK during the dual-run window.\n */\nexport const DEFAULT_API_BASE = 'https://api.polar.sh/v1/customer-portal/license-keys'\n\n/**\n * Reads `process.env.X` defensively for browsers without a bundler-injected\n * `process.env`. Returns `undefined` when the var is missing or the runtime\n * has no `process` global.\n */\nfunction readEnv(name: string): string | undefined {\n  if (typeof process === 'undefined') return undefined\n  const value = process.env?.[name]\n  return value && value.length > 0 ? value : undefined\n}\n\n/**\n * Resolve which issuer base URL a call should hit.\n *\n * Precedence (highest first):\n *   1. `override` passed by the caller (`options.apiBase` on `validateLicenseKey`,\n *      `validateKey`, `activateKey`, `deactivateKey`, or the `apiBase` prop on\n *      `<LicenseProvider>`).\n *   2. `process.env.NEXT_PUBLIC_TOUR_KIT_LICENSE_API_BASE` — Next.js client +\n *      server (the same prefix used by `NEXT_PUBLIC_TOUR_KIT_LICENSE_KEY` so\n *      customer apps configure both vars the same way).\n *   3. `process.env.TOUR_KIT_LICENSE_API_BASE` — server-side / Node /\n *      Vite-with-define / customers using a non-Next.js bundler that inlines\n *      bare env names.\n *   4. {@link DEFAULT_API_BASE}.\n *\n * The override mechanism is the load-bearing seam for the Polar → tourkit-dash\n * issuer migration (plan/15f). Without it a v1.x customer cannot point at the\n * cloud issuer until they upgrade to v2.x — which is the whole reason this\n * function exists.\n */\nexport function resolveApiBase(override?: string): string {\n  if (override && override.length > 0) return override\n  const nextPublic = readEnv('NEXT_PUBLIC_TOUR_KIT_LICENSE_API_BASE')\n  if (nextPublic) return nextPublic\n  const bare = readEnv('TOUR_KIT_LICENSE_API_BASE')\n  if (bare) return bare\n  return DEFAULT_API_BASE\n}\n","import type { ZodError } from 'zod'\nimport type { LicenseState, PolarActivateResponse, PolarValidateResponse } from '../types'\nimport { readCache, writeCache } from './cache'\nimport { getCurrentDomain, isDevEnvironment, isEphemeralHost } from './domain'\nimport {\n  createDevBypassState,\n  createPreviewBypassState,\n  createUnlicensedState,\n  normalizeLicenseKey,\n} from './license-state'\nimport { resolveApiBase } from './resolve-api-base'\nimport { PolarActivateResponseSchema, PolarValidateResponseSchema } from './schemas'\n\n/**\n * Options bag accepted by every low-level Polar call and by `validateLicenseKey`.\n *\n * `apiBase` is the load-bearing knob for the Polar → tourkit-dash issuer\n * migration (plan/15f). When omitted the call falls through `resolveApiBase()`\n * to the env-var chain and finally the Polar default.\n */\nexport type ValidateOptions = {\n  apiBase?: string\n}\n\n// ---------------------------------------------------------------------------\n// Error classes\n// ---------------------------------------------------------------------------\n\nexport class PolarApiError extends Error {\n  constructor(\n    public readonly statusCode: number,\n    message: string\n  ) {\n    super(message)\n    this.name = 'PolarApiError'\n  }\n}\n\nexport class PolarParseError extends Error {\n  constructor(public readonly zodError: ZodError) {\n    super('Failed to parse Polar API response')\n    this.name = 'PolarParseError'\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Snake-case → camelCase transforms\n// ---------------------------------------------------------------------------\n\nfunction transformValidateResponse(\n  raw: ReturnType<typeof PolarValidateResponseSchema.parse>\n): PolarValidateResponse {\n  return {\n    id: raw.id,\n    organizationId: raw.organization_id,\n    status: raw.status,\n    key: raw.key,\n    limitActivations: raw.limit_activations,\n    usage: raw.usage,\n    validations: raw.validations,\n    lastValidatedAt: raw.last_validated_at,\n    expiresAt: raw.expires_at,\n    activation: raw.activation\n      ? {\n          id: raw.activation.id,\n          licenseKeyId: raw.activation.license_key_id,\n          label: raw.activation.label,\n          meta: raw.activation.meta,\n          createdAt: raw.activation.created_at,\n          modifiedAt: raw.activation.modified_at,\n        }\n      : null,\n  }\n}\n\nfunction transformActivateResponse(\n  raw: ReturnType<typeof PolarActivateResponseSchema.parse>\n): PolarActivateResponse {\n  return {\n    id: raw.id,\n    licenseKeyId: raw.license_key_id,\n    label: raw.label,\n    meta: raw.meta,\n    createdAt: raw.created_at,\n    modifiedAt: raw.modified_at,\n    licenseKey: {\n      id: raw.license_key.id,\n      organizationId: raw.license_key.organization_id,\n      status: raw.license_key.status,\n      limitActivations: raw.license_key.limit_activations,\n      usage: raw.license_key.usage,\n      limitUsage: raw.license_key.limit_usage,\n      validations: raw.license_key.validations,\n      lastValidatedAt: raw.license_key.last_validated_at,\n      expiresAt: raw.license_key.expires_at,\n    },\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Low-level API functions\n// ---------------------------------------------------------------------------\n\nexport async function validateKey(\n  key: string,\n  organizationId: string,\n  activationId?: string,\n  options?: ValidateOptions\n): Promise<PolarValidateResponse> {\n  const body: Record<string, string> = {\n    key,\n    organization_id: organizationId,\n  }\n  if (activationId) {\n    body.activation_id = activationId\n  }\n\n  const res = await fetch(`${resolveApiBase(options?.apiBase)}/validate`, {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify(body),\n  })\n\n  if (!res.ok) {\n    throw new PolarApiError(res.status, await res.text())\n  }\n\n  const json: unknown = await res.json()\n  const parsed = PolarValidateResponseSchema.safeParse(json)\n  if (!parsed.success) {\n    throw new PolarParseError(parsed.error)\n  }\n\n  return transformValidateResponse(parsed.data)\n}\n\nexport async function activateKey(\n  key: string,\n  organizationId: string,\n  label: string,\n  options?: ValidateOptions\n): Promise<PolarActivateResponse> {\n  const res = await fetch(`${resolveApiBase(options?.apiBase)}/activate`, {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify({\n      key,\n      organization_id: organizationId,\n      label,\n    }),\n  })\n\n  if (!res.ok) {\n    throw new PolarApiError(res.status, await res.text())\n  }\n\n  const json: unknown = await res.json()\n  const parsed = PolarActivateResponseSchema.safeParse(json)\n  if (!parsed.success) {\n    throw new PolarParseError(parsed.error)\n  }\n\n  return transformActivateResponse(parsed.data)\n}\n\nexport async function deactivateKey(\n  key: string,\n  organizationId: string,\n  activationId: string,\n  options?: ValidateOptions\n): Promise<void> {\n  const res = await fetch(`${resolveApiBase(options?.apiBase)}/deactivate`, {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify({\n      key,\n      organization_id: organizationId,\n      activation_id: activationId,\n    }),\n  })\n\n  if (!res.ok) {\n    throw new PolarApiError(res.status, await res.text())\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction generateRenderKey(key: string, domain: string | null): string {\n  const input = key + (domain ?? '')\n  let hash = 0\n  for (let i = 0; i < input.length; i++) {\n    hash = ((hash << 5) - hash + input.charCodeAt(i)) | 0\n  }\n  return `lk_${Math.abs(hash).toString(36)}`\n}\n\n// Dedupe the over-limit warning so a re-validation storm does not spam the\n// console. One line per domain per session is enough to be actionable.\nconst warnedDomains = new Set<string>()\n\nfunction warnActivationLimitReached(domain: string): void {\n  if (warnedDomains.has(domain)) return\n  warnedDomains.add(domain)\n  console.warn(\n    `[tour-kit/license] License valid, but its activation limit is reached, so \"${domain}\" could not claim a slot. Tour Kit Pro stays unlocked here. Free a slot or raise the activation limit for this key in your Polar dashboard. Tip: preview/throwaway deploy URLs are skipped automatically and do not consume slots.`\n  )\n}\n\n// ---------------------------------------------------------------------------\n// Orchestrator — single public entry point\n// ---------------------------------------------------------------------------\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: orchestrator with multiple validation paths\nexport async function validateLicenseKey(\n  key: string,\n  organizationId?: string,\n  options?: ValidateOptions\n): Promise<LicenseState> {\n  const domain = getCurrentDomain()\n  const orgId = organizationId ?? ''\n  const now = Date.now()\n  const normalizedKey = normalizeLicenseKey(key)\n\n  // 0. Missing or whitespace-only key is unlicensed on every host — including\n  //    localhost. Must run before cache reads so an old valid cache entry\n  //    cannot mask an empty env var, and before the dev bypass so a developer\n  //    sees the same unlicensed watermark locally that production would show.\n  if (normalizedKey.length === 0) {\n    return createUnlicensedState(now)\n  }\n\n  // 1. Dev bypass — only for non-empty keys. We do not validate locally\n  //    because that would consume Polar activation slots during normal dev.\n  if (isDevEnvironment()) {\n    return createDevBypassState(now)\n  }\n\n  // 1b. Ephemeral / preview hosts (Vercel/Netlify/Cloudflare preview URLs,\n  //     tunnels, raw IPs). Skip Polar entirely so a throwaway deploy URL never\n  //     consumes one of the key's finite activation slots. Pro stays unlocked\n  //     (no watermark); stable production hosts fall through to validation.\n  if (domain && isEphemeralHost(domain)) {\n    return createPreviewBypassState(now)\n  }\n\n  // 2. Cache check (bound to current key — switching licenseKey invalidates)\n  if (domain) {\n    const cached = readCache(domain, normalizedKey)\n    if (cached) return cached\n  }\n\n  try {\n    // 3. Validate against the issuer (Polar by default; tourkit-dash when\n    //    `options.apiBase` or the TOUR_KIT_LICENSE_API_BASE env var overrides\n    //    the default — see plan/15f).\n    const response = await validateKey(normalizedKey, orgId, undefined, options)\n\n    // 4. Map Polar status to LicenseState\n    const serverValidatedAt = response.lastValidatedAt\n      ? Date.parse(response.lastValidatedAt) || null\n      : null\n\n    if (response.status === 'revoked' || response.status === 'disabled') {\n      const state: LicenseState = {\n        status: 'revoked',\n        tier: 'free',\n        activations: response.usage,\n        maxActivations: response.limitActivations ?? 0,\n        domain,\n        expiresAt: null,\n        validatedAt: now,\n        serverValidatedAt,\n        renderKey: undefined,\n      }\n      if (domain) writeCache(domain, state, normalizedKey)\n      return state\n    }\n\n    if (response.expiresAt && new Date(response.expiresAt) < new Date()) {\n      const state: LicenseState = {\n        status: 'expired',\n        tier: 'pro',\n        activations: response.usage,\n        maxActivations: response.limitActivations ?? 0,\n        domain,\n        expiresAt: response.expiresAt,\n        validatedAt: now,\n        serverValidatedAt,\n        renderKey: undefined,\n      }\n      if (domain) writeCache(domain, state, normalizedKey)\n      return state\n    }\n\n    // 5. Auto-activate if no activation for this domain\n    let activationLabel = response.activation?.label ?? null\n    let usage = response.usage\n\n    if (!response.activation && domain) {\n      try {\n        const activateResponse = await activateKey(normalizedKey, orgId, domain, options)\n        activationLabel = activateResponse.label\n        usage = activateResponse.licenseKey.usage\n      } catch (activationError) {\n        // 5a. Activation limit reached (403). The key itself is `granted` — the\n        //     customer paid; they just have more live domains than slots (very\n        //     common once Vercel/Netlify preview URLs pile up). Punishing a\n        //     paying customer's production site with the \"Unlicensed\" watermark\n        //     is a false positive, so treat this as a valid Pro license, warn\n        //     once, and let the over-activation surface server-side instead.\n        if (activationError instanceof PolarApiError && activationError.statusCode === 403) {\n          warnActivationLimitReached(domain)\n          const overLimitState: LicenseState = {\n            status: 'valid',\n            tier: 'pro',\n            activations: response.usage,\n            maxActivations: response.limitActivations ?? 0,\n            domain,\n            expiresAt: response.expiresAt,\n            validatedAt: now,\n            serverValidatedAt,\n            renderKey: generateRenderKey(normalizedKey, domain),\n          }\n          writeCache(domain, overLimitState, normalizedKey)\n          return overLimitState\n        }\n        throw activationError\n      }\n    }\n\n    // 6. Guard: if still no activation (SSR with no prior activation), return error\n    if (!activationLabel) {\n      return {\n        status: 'error',\n        tier: 'free',\n        activations: 0,\n        maxActivations: 0,\n        domain: null,\n        expiresAt: null,\n        validatedAt: now,\n        serverValidatedAt: null,\n        renderKey: undefined,\n      }\n    }\n\n    const state: LicenseState = {\n      status: 'valid',\n      tier: 'pro',\n      activations: usage,\n      maxActivations: response.limitActivations ?? 0,\n      domain: activationLabel,\n      expiresAt: response.expiresAt,\n      validatedAt: now,\n      serverValidatedAt,\n      renderKey: generateRenderKey(normalizedKey, activationLabel),\n    }\n    if (domain) writeCache(domain, state, normalizedKey)\n    return state\n  } catch (error) {\n    if (error instanceof PolarApiError && error.statusCode === 404) {\n      return {\n        status: 'invalid',\n        tier: 'free',\n        activations: 0,\n        maxActivations: 0,\n        domain: null,\n        expiresAt: null,\n        validatedAt: now,\n        serverValidatedAt: null,\n        renderKey: undefined,\n      }\n    }\n    if (error instanceof PolarApiError && error.statusCode === 403) {\n      return {\n        status: 'invalid',\n        tier: 'free',\n        activations: 0,\n        maxActivations: 0,\n        domain: null,\n        expiresAt: null,\n        validatedAt: now,\n        serverValidatedAt: null,\n        renderKey: undefined,\n      }\n    }\n    if (error instanceof PolarParseError) {\n      return {\n        status: 'error',\n        tier: 'free',\n        activations: 0,\n        maxActivations: 0,\n        domain: null,\n        expiresAt: null,\n        validatedAt: now,\n        serverValidatedAt: null,\n        renderKey: undefined,\n      }\n    }\n    return {\n      status: 'error',\n      tier: 'free',\n      activations: 0,\n      maxActivations: 0,\n      domain: null,\n      expiresAt: null,\n      validatedAt: now,\n      serverValidatedAt: null,\n      renderKey: undefined,\n    }\n  }\n}\n","/**\n * Consumer-supplied trial configuration. Passed to <LicenseProvider trialDays={14} />\n * along with the implicit `issuedAt` derived from the license's first validation\n * (or a future server-side field when Polar ships one).\n *\n * Polar's /v1/customer-portal/license-keys/validate endpoint does NOT emit a\n * `tier` field today (confirmed Phase 0 task 0.6, memory project_polar_api_findings.md\n * entry #187). Trial state is therefore CLIENT-DERIVED. If Polar adds server-side\n * trial signalling later, getDaysLeft will accept an optional server-provided\n * override (marked `FUTURE:` below) — additive, non-breaking.\n */\nexport interface TrialConfig {\n  /** Unix ms timestamp of when the trial started. Sourced from license issuance time. */\n  issuedAt: number\n  /** Length of the trial window in whole days. E.g. 14. */\n  trialDays: number\n  /** Local Date.now() timestamp captured when validation ran. */\n  validatedAt: number\n  /** Polar last_validated_at parsed to Unix ms. Null when unavailable. */\n  serverValidatedAt?: number | null\n}\n\n/**\n * Compute days remaining in the trial window. Uses Polar's server validation\n * timestamp plus local elapsed time when available, and falls back to `now`\n * when no server anchor exists. Clamps to [0, trialDays].\n *\n * The serverValidatedAt + (now - validatedAt) algebra absorbs client clock\n * skew: Polar gives the server anchor at validation time; the local clock only\n * contributes the (now - validatedAt) delta, which on a normal machine is the\n * real elapsed time and on a skewed machine is the same delta (skew cancels).\n *\n * @param config The trial config from <LicenseProvider>.\n * @param now Override for testing. Defaults to Date.now().\n * @returns Integer days remaining in [0, trialDays].\n */\nexport function getDaysLeft(config: TrialConfig, now: number = Date.now()): number {\n  const trustedNow =\n    config.serverValidatedAt && config.serverValidatedAt > 0\n      ? config.serverValidatedAt + Math.max(0, now - config.validatedAt)\n      : now\n  const elapsedMs = Math.max(0, trustedNow - config.issuedAt)\n  const elapsedDays = Math.floor(elapsedMs / 86_400_000)\n  const remaining = config.trialDays - elapsedDays\n  // FUTURE: if Polar adds `tier='trial'` to the validate response, accept an\n  // optional serverDaysLeft override here and return it when defined.\n  return Math.max(0, Math.min(config.trialDays, remaining))\n}\n"]}