@neetru/sdk 3.1.1 → 3.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -5
- package/dist/auth.cjs +255 -18
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +1 -1
- package/dist/auth.d.ts +1 -1
- package/dist/auth.mjs +255 -18
- package/dist/auth.mjs.map +1 -1
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +1 -1
- package/dist/catalog.d.ts +1 -1
- package/dist/catalog.mjs.map +1 -1
- package/dist/checkout.cjs +22 -7
- package/dist/checkout.cjs.map +1 -1
- package/dist/checkout.d.cts +1 -1
- package/dist/checkout.d.ts +1 -1
- package/dist/checkout.mjs +22 -7
- package/dist/checkout.mjs.map +1 -1
- package/dist/db-react.d.cts +1 -1
- package/dist/db-react.d.ts +1 -1
- package/dist/db.cjs +59 -3
- package/dist/db.cjs.map +1 -1
- package/dist/db.d.cts +1 -1
- package/dist/db.d.ts +1 -1
- package/dist/db.mjs +59 -3
- package/dist/db.mjs.map +1 -1
- package/dist/entitlements.cjs.map +1 -1
- package/dist/entitlements.d.cts +1 -1
- package/dist/entitlements.d.ts +1 -1
- package/dist/entitlements.mjs.map +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.cts +11 -6
- package/dist/errors.d.ts +11 -6
- package/dist/errors.mjs.map +1 -1
- package/dist/firestore-compat.cjs +15 -2
- package/dist/firestore-compat.cjs.map +1 -1
- package/dist/firestore-compat.d.cts +1 -1
- package/dist/firestore-compat.d.ts +1 -1
- package/dist/firestore-compat.mjs +15 -2
- package/dist/firestore-compat.mjs.map +1 -1
- package/dist/index.cjs +267 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +267 -22
- package/dist/index.mjs.map +1 -1
- package/dist/mocks.cjs +25 -0
- package/dist/mocks.cjs.map +1 -1
- package/dist/mocks.d.cts +18 -1
- package/dist/mocks.d.ts +18 -1
- package/dist/mocks.mjs +25 -0
- package/dist/mocks.mjs.map +1 -1
- package/dist/notifications.cjs.map +1 -1
- package/dist/notifications.d.cts +1 -1
- package/dist/notifications.d.ts +1 -1
- package/dist/notifications.mjs.map +1 -1
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.mjs.map +1 -1
- package/dist/support.cjs.map +1 -1
- package/dist/support.d.cts +1 -1
- package/dist/support.d.ts +1 -1
- package/dist/support.mjs.map +1 -1
- package/dist/telemetry.cjs +2 -1
- package/dist/telemetry.cjs.map +1 -1
- package/dist/telemetry.d.cts +1 -1
- package/dist/telemetry.d.ts +1 -1
- package/dist/telemetry.mjs +2 -1
- package/dist/telemetry.mjs.map +1 -1
- package/dist/{types-B3XFHD4A.d.ts → types-CRIIjqzC.d.ts} +105 -12
- package/dist/{types-DePdSU3P.d.cts → types-DvMdYbfV.d.cts} +105 -12
- package/dist/usage.cjs.map +1 -1
- package/dist/usage.d.cts +1 -1
- package/dist/usage.d.ts +1 -1
- package/dist/usage.mjs.map +1 -1
- package/dist/webhooks.cjs +11 -3
- package/dist/webhooks.cjs.map +1 -1
- package/dist/webhooks.d.cts +1 -1
- package/dist/webhooks.d.ts +1 -1
- package/dist/webhooks.mjs +11 -3
- package/dist/webhooks.mjs.map +1 -1
- package/package.json +1 -1
package/dist/webhooks.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/idempotency.ts","../src/http.ts","../src/validators.ts","../src/webhooks.ts"],"names":["err","message"],"mappings":"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","file":"webhooks.cjs","sourcesContent":["/**\r\n * Erros tipados do SDK.\r\n *\r\n * Todo erro lançado pelo SDK estende `NeetruError` — caller pode discriminar\r\n * por `.code` (string estável) sem parsing de message.\r\n */\r\n\r\n/** Códigos de erro estáveis do SDK. Adicionar aqui requer minor bump. */\r\nexport type NeetruErrorCode =\r\n | 'invalid_config'\r\n | 'missing_api_key'\r\n | 'unauthorized'\r\n | 'forbidden'\r\n | 'not_found'\r\n | 'rate_limited'\r\n | 'validation_failed'\r\n | 'network_error'\r\n | 'invalid_response'\r\n | 'server_error'\r\n | 'token_expired'\r\n | 'token_invalid_signature'\r\n | 'token_invalid_audience'\r\n | 'token_invalid_issuer'\r\n /** 3.0: runtime não expõe API necessária (ex: WebCrypto ausente). */\r\n | 'runtime_unsupported'\r\n /** HTTP 409 — colisão de idempotência ou conflito de recurso. */\r\n | 'conflict'\r\n | 'unknown';\r\n\r\n/**\r\n * Erro tipado padrão do SDK. Sempre lançado em vez de Error genérico.\r\n *\r\n * @example\r\n * ```ts\r\n * try { await client.catalog.list(); }\r\n * catch (e) {\r\n * if (e instanceof NeetruError && e.code === 'rate_limited') retry();\r\n * }\r\n * ```\r\n */\r\nexport class NeetruError extends Error {\r\n public readonly code: NeetruErrorCode | string;\r\n public readonly status?: number;\r\n public readonly requestId?: string;\r\n\r\n constructor(\r\n code: NeetruErrorCode | string,\r\n message: string,\r\n status?: number,\r\n requestId?: string,\r\n ) {\r\n super(message);\r\n this.name = 'NeetruError';\r\n this.code = code;\r\n this.status = status;\r\n this.requestId = requestId;\r\n // Preserva o prototype chain ao herdar de Error (downlevel quirk de TS).\r\n Object.setPrototypeOf(this, NeetruError.prototype);\r\n }\r\n}\r\n","/**\n * Idempotency-Key helper — gera UUID v4 cripto-seguro para identificar\n * mutations não-idempotentes (`usage.report`, `support.createTicket`,\n * `notifications.send`, `webhooks.test`).\n *\n * Estratégia 3.0:\n * - SDK gera UUID v4 por chamada via `randomUUID()` (WebCrypto.subtle não\n * necessário aqui — `crypto.randomUUID()` está em Node 14.17+ e em todos\n * os browsers/Edge runtimes modernos).\n * - Header `Idempotency-Key: <uuid>` é injetado pelo `httpRequest` quando\n * `opts.idempotencyKey === true` OU caller passa explicit `opts.idempotencyKeyValue`.\n * - Core dedup em coleção `usage_idempotency_keys/{key}` TTL 24h (vide\n * `docs/CORE_CHANGES_REQUIRED.md` §2). Se Core ainda não dedupa, o header\n * é benign (ignorado).\n *\n * Defesa em camadas: combinado com `retries: 0` em POSTs (vide http.ts), o\n * risco de double-write em transientes vai pra zero.\n */\nimport { NeetruError } from './errors';\n\n/**\n * Gera UUID v4 criptograficamente seguro. Universal: Node 14.17+, browsers\n * modernos, Edge runtimes (Workers/Vercel Edge/Cloudflare).\n *\n * Fallback puro-JS removido em 3.0 — `crypto.randomUUID()` é ubíquo desde\n * 2022. Se runtime não tem, lança `NeetruError('runtime_unsupported')`\n * (consumer deve polyfillar).\n *\n * **L-01 fix (Opus review 2026-05-27):** antes lançava `Error` cru, que\n * não era pego por `catch (err) { if (err instanceof NeetruError) ... }`\n * dos consumers. Agora throw canonical.\n *\n * @throws NeetruError('runtime_unsupported') se `crypto.randomUUID` não disponível.\n */\nexport function generateIdempotencyKey(): string {\n // WebCrypto (browser/Edge) e Node 14.17+ expõem `crypto.randomUUID()`.\n // Node anterior precisa de `node:crypto` mas SDK 3.0 exige Node ≥20 (vide engines).\n const cryptoObj: { randomUUID?: () => string } | undefined =\n typeof globalThis !== 'undefined' && 'crypto' in globalThis\n ? (globalThis as { crypto?: { randomUUID?: () => string } }).crypto\n : undefined;\n if (cryptoObj && typeof cryptoObj.randomUUID === 'function') {\n return cryptoObj.randomUUID();\n }\n throw new NeetruError(\n 'runtime_unsupported',\n 'crypto.randomUUID not available in this runtime. SDK 3.0 requires Node ≥20 or modern browser/Edge.',\n );\n}\n\n/** Regex UUID v4 — validação para uso interno. */\nexport const UUID_V4_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n","/**\r\n * HTTP transport interno do SDK.\r\n *\r\n * Responsabilidades:\r\n * - Construir URL absoluta a partir de `baseUrl` + path\r\n * - Injetar Bearer token quando `requireAuth=true`\r\n * - Mapear status HTTP → `NeetruError` com `code` estável\r\n * - Parse defensivo de JSON (não lança em body vazio em 204)\r\n * - Retry/backoff exponencial em `rate_limited` (429), `server_error` (5xx)\r\n * e `network_error` (timeout/falha de rede). Honra `Retry-After` quando\r\n * presente.\r\n * - **Captura `X-Neetru-Version`** das respostas e emite `console.warn` quando\r\n * o Core está abaixo da versão mínima para a major do SDK.\r\n *\r\n * Política de retries (mudança breaking 3.0):\r\n * - GET/HEAD: default 2 retries (3 tentativas total) — idempotente, seguro.\r\n * - POST/PUT/PATCH/DELETE: default **0 retries** — mutations podem duplicar\r\n * side effects (ex: `usage.report` incrementa contador). Caller pode\r\n * reativar passando `retries: N` explicitamente ou usar `Idempotency-Key`\r\n * header (gerado automaticamente se `opts.idempotencyKey=true`).\r\n *\r\n * Idempotency-Key (3.0):\r\n * - `opts.idempotencyKey === true` → SDK gera UUID v4 e injeta header.\r\n * - `opts.idempotencyKey === 'uuid-string'` → usa o valor passado.\r\n * - Caller mantém retentos client-side se quiser; Core dedup serverside\r\n * (vide `docs/CORE_CHANGES_REQUIRED.md` §2).\r\n */\r\nimport { NeetruError, type NeetruErrorCode } from './errors';\r\nimport { generateIdempotencyKey } from './idempotency';\r\nimport type { ResolvedConfig } from './types';\r\n\r\n// ─── Compat Matrix SDK↔Core ──────────────────────────────────────────────────\r\n\r\n/**\r\n * Matriz de compatibilidade SDK major → versão mínima do Core.\r\n *\r\n * Formato do Core: CalVer `YYYY.MM.patch+revision` (ex: `2026.05.1+neetru-core-00096-79t`).\r\n * A comparação é feita apenas nas partes `YYYY.MM.patch` (prefixo antes de `+`).\r\n *\r\n * Quando o Core reporta `X-Neetru-Version` abaixo do mínimo para a SDK major\r\n * corrente, o SDK emite `console.warn` uma única vez por sessão de processo.\r\n *\r\n * Atualize esta tabela a cada major de SDK.\r\n */\r\nconst COMPAT_MATRIX: Record<number, string> = {\r\n // SDK major 3.x requer Core ≥ 2026.05.1 (suporte a X-Neetru-Version header,\r\n // runTransaction write-after-read, verifyWebhookRequest, webhooks 3.0+)\r\n 3: '2026.05.1',\r\n};\r\n\r\n/** CalVer sem sufixo `+revision`. Ex: `2026.05.1+abc` → `2026.05.1`. */\r\nfunction stripRevision(v: string): string {\r\n return v.split('+')[0] ?? v;\r\n}\r\n\r\n/**\r\n * Compara dois CalVer (`YYYY.MM.patch`). Retorna negativo se `a < b`,\r\n * positivo se `a > b`, 0 se iguais. Partes não numéricas tratadas como 0.\r\n */\r\nfunction compareCalVer(a: string, b: string): number {\r\n const partsA = stripRevision(a).split('.').map(Number);\r\n const partsB = stripRevision(b).split('.').map(Number);\r\n const len = Math.max(partsA.length, partsB.length);\r\n for (let i = 0; i < len; i++) {\r\n const pa = partsA[i] ?? 0;\r\n const pb = partsB[i] ?? 0;\r\n if (pa !== pb) return pa - pb;\r\n }\r\n return 0;\r\n}\r\n\r\n/** Lê a SDK major a partir da string `VERSION` exportada de `./index`. Fallback 3. */\r\nfunction getSdkMajor(): number {\r\n try {\r\n // Importação estática não disponível aqui (evita ciclo). Usa variável injetada\r\n // em tempo de build pela tsup via `define`. Fallback para 3 (current major).\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const ver = (globalThis as any).__NEETRU_SDK_VERSION__ as string | undefined;\r\n if (ver) return parseInt(ver.split('.')[0] ?? '3', 10);\r\n } catch {\r\n // ignore\r\n }\r\n return 3;\r\n}\r\n\r\n/** Aviso emitido no máximo uma vez por major detectada pra não spammar logs. */\r\nconst _warnedCoreTooOld = new Set<string>();\r\n\r\n/**\r\n * Verifica se a versão do Core (`X-Neetru-Version`) é compatível com a SDK major.\r\n * Emite `console.warn` quando incompatível (uma vez por processo por versão detectada).\r\n */\r\nexport function checkCoreVersionCompat(coreVersion: string): void {\r\n if (!coreVersion) return;\r\n const sdkMajor = getSdkMajor();\r\n const minCore = COMPAT_MATRIX[sdkMajor];\r\n if (!minCore) return; // sem restrição para esta major\r\n const stripped = stripRevision(coreVersion);\r\n if (compareCalVer(stripped, minCore) < 0) {\r\n const key = `${sdkMajor}:${stripped}`;\r\n if (!_warnedCoreTooOld.has(key)) {\r\n _warnedCoreTooOld.add(key);\r\n console.warn(\r\n `[Neetru SDK] Atenção: Core versão \"${coreVersion}\" é anterior ao mínimo recomendado` +\r\n ` \"${minCore}\" para SDK major ${sdkMajor}. Alguns recursos podem não funcionar` +\r\n ` corretamente. Atualize o Core para a versão mais recente.`,\r\n );\r\n }\r\n }\r\n}\r\n\r\n/** Opções da request HTTP. */\r\nexport interface HttpRequestOptions {\r\n method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\r\n /** Path relativo (ex: `/api/v1/cli/catalog`). Concatenado a `baseUrl`. */\r\n path: string;\r\n /** Query string params (chave → valor primitivo). Valores `undefined` ignorados. */\r\n query?: Record<string, string | number | boolean | undefined>;\r\n /** Body JSON-serializável. Ignorado em GET/DELETE. */\r\n body?: unknown;\r\n /**\r\n * Se true, injeta `Authorization: Bearer <apiKey>`. Lança `missing_api_key`\r\n * se config.apiKey ausente. Default false.\r\n */\r\n requireAuth?: boolean;\r\n /** Cabeçalhos extras. */\r\n headers?: Record<string, string>;\r\n /**\r\n * Número de retries em códigos transientes (`rate_limited`, `server_error`,\r\n * `network_error`).\r\n *\r\n * Default (3.0):\r\n * - GET/HEAD: 2 (= 3 tentativas total) — idempotente, seguro.\r\n * - POST/PUT/PATCH/DELETE: 0 — mutations podem duplicar side effects.\r\n *\r\n * Caller pode reativar passando explicitamente: `retries: 2`.\r\n */\r\n retries?: number;\r\n /**\r\n * Injeta `Idempotency-Key` header pra dedup serverside (3.0):\r\n * - `true` → SDK gera UUID v4 cripto-seguro automaticamente.\r\n * - string → usa o valor passado (deve ser UUID v4).\r\n * - `undefined`/`false` → sem header.\r\n */\r\n idempotencyKey?: boolean | string;\r\n}\r\n\r\nconst DEFAULT_RETRIES_READ = 2;\r\nconst DEFAULT_RETRIES_WRITE = 0;\r\nconst READ_METHODS = new Set(['GET', 'HEAD']);\r\nconst RETRYABLE_CODES = new Set<NeetruErrorCode>([\r\n 'rate_limited',\r\n 'server_error',\r\n 'network_error',\r\n]);\r\n\r\n/** Backoff exponencial com jitter ±20%. attempt: 0=primeira, 1=primeiro retry, ... */\r\nfunction backoffMs(attempt: number): number {\r\n const base = 200 * Math.pow(4, attempt); // 200ms, 800ms, 3.2s, ...\r\n const jitter = base * 0.2 * (Math.random() * 2 - 1);\r\n return Math.max(50, Math.round(base + jitter));\r\n}\r\n\r\n/**\r\n * Honra `Retry-After` header (segundos ou HTTP-date). Retorna ms ou null se\r\n * inválido. RFC 9110 §10.2.3.\r\n *\r\n * Bug fix: sem teto, um servidor hostil/mal-configurado poderia retornar\r\n * `Retry-After: 86400` (24h) ou uma HTTP-date anos no futuro, pendurando o\r\n * processo indefinidamente. Aplica teto de MAX_RETRY_AFTER_MS em ambos os caminhos.\r\n */\r\nconst MAX_RETRY_AFTER_MS = 60_000; // 60s — teto razoável para retry automático\r\n\r\nfunction parseRetryAfter(value: string | null): number | null {\r\n if (!value) return null;\r\n const secs = Number(value);\r\n if (Number.isFinite(secs) && secs >= 0) return Math.min(Math.round(secs * 1000), MAX_RETRY_AFTER_MS);\r\n const dateMs = Date.parse(value);\r\n if (Number.isFinite(dateMs)) {\r\n const delta = dateMs - Date.now();\r\n if (delta > 0) return Math.min(delta, MAX_RETRY_AFTER_MS);\r\n }\r\n return null;\r\n}\r\n\r\nfunction sleep(ms: number): Promise<void> {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n}\r\n\r\n/** Mapeamento status → code estável do NeetruError. */\r\nfunction statusToCode(status: number): NeetruErrorCode {\r\n if (status === 401) return 'unauthorized';\r\n if (status === 403) return 'forbidden';\r\n if (status === 404) return 'not_found';\r\n if (status === 409) return 'conflict'; // Bug fix: 409 vira 'conflict' (não 'unknown')\r\n if (status === 422 || status === 400) return 'validation_failed';\r\n if (status === 429) return 'rate_limited';\r\n if (status >= 500) return 'server_error';\r\n return 'unknown';\r\n}\r\n\r\nfunction buildUrl(baseUrl: string, path: string, query?: HttpRequestOptions['query']): string {\r\n // Trim trailing slash em base e leading em path pra evitar `//`.\r\n const base = baseUrl.replace(/\\/+$/, '');\r\n const p = path.startsWith('/') ? path : `/${path}`;\r\n const url = new URL(`${base}${p}`);\r\n if (query) {\r\n for (const [k, v] of Object.entries(query)) {\r\n if (v === undefined) continue;\r\n url.searchParams.set(k, String(v));\r\n }\r\n }\r\n return url.toString();\r\n}\r\n\r\n/** Parse JSON defensivo — retorna `undefined` em body vazio. */\r\nasync function safeJson(res: Response): Promise<unknown> {\r\n const text = await res.text();\r\n if (!text) return undefined;\r\n try {\r\n return JSON.parse(text);\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\n/**\r\n * Executa request HTTP. Em sucesso retorna body parseado; em erro lança\r\n * `NeetruError` com `code` derivado do status. Aplica retry/backoff\r\n * automático em códigos transientes (rate_limited/server_error/network_error)\r\n * conforme `opts.retries` (default 2 = 3 tentativas).\r\n */\r\nexport async function httpRequest<T>(\r\n config: ResolvedConfig,\r\n opts: HttpRequestOptions,\r\n): Promise<T> {\r\n const method = opts.method ?? 'GET';\r\n const url = buildUrl(config.baseUrl, opts.path, opts.query);\r\n // Default por método: reads tentam 2x, writes 0x. Caller override sempre vence.\r\n const defaultRetries = READ_METHODS.has(method)\r\n ? DEFAULT_RETRIES_READ\r\n : DEFAULT_RETRIES_WRITE;\r\n const maxRetries = opts.retries ?? defaultRetries;\r\n\r\n const headers: Record<string, string> = {\r\n accept: 'application/json',\r\n ...opts.headers,\r\n };\r\n\r\n if (opts.requireAuth) {\r\n if (!config.apiKey) {\r\n throw new NeetruError(\r\n 'missing_api_key',\r\n 'This operation requires an apiKey. Pass it to createNeetruClient({ apiKey }) or set NEETRU_API_KEY env var.',\r\n );\r\n }\r\n headers.authorization = `Bearer ${config.apiKey}`;\r\n }\r\n\r\n // Idempotency-Key: gerado por chamada se solicitado. UUID v4 cripto-seguro.\r\n if (opts.idempotencyKey) {\r\n const key =\r\n typeof opts.idempotencyKey === 'string'\r\n ? opts.idempotencyKey\r\n : generateIdempotencyKey();\r\n headers['idempotency-key'] = key;\r\n }\r\n\r\n // Body só é serializado uma vez — reusado entre tentativas.\r\n const bodyString =\r\n opts.body !== undefined && method !== 'GET' && method !== 'DELETE'\r\n ? JSON.stringify(opts.body)\r\n : undefined;\r\n if (bodyString !== undefined) {\r\n headers['content-type'] = 'application/json';\r\n }\r\n\r\n let lastError: NeetruError | null = null;\r\n\r\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\r\n const init: RequestInit = { method, headers };\r\n if (bodyString !== undefined) init.body = bodyString;\r\n // BUG-020 fix (2026-05-13): timeout default 30s. AbortSignal.timeout\r\n // requer Node 18+ ou browsers recentes.\r\n init.signal = AbortSignal.timeout(30_000);\r\n\r\n let res: Response;\r\n try {\r\n res = await config.fetch(url, init);\r\n } catch (err) {\r\n const message =\r\n err instanceof DOMException && err.name === 'TimeoutError'\r\n ? 'Network error: timeout after 30s'\r\n : `Network error: ${err instanceof Error ? err.message : 'fetch failed'}`;\r\n lastError = new NeetruError('network_error', message);\r\n if (attempt < maxRetries) {\r\n await sleep(backoffMs(attempt));\r\n continue;\r\n }\r\n throw lastError;\r\n }\r\n\r\n const requestId =\r\n res.headers.get('x-request-id') ?? res.headers.get('x-correlation-id') ?? undefined;\r\n\r\n if (res.ok) {\r\n // Captura X-Neetru-Version e verifica compat com a SDK major.\r\n const coreVersion = res.headers.get('x-neetru-version');\r\n if (coreVersion) checkCoreVersionCompat(coreVersion);\r\n const parsed = await safeJson(res);\r\n return parsed as T;\r\n }\r\n\r\n const body = (await safeJson(res)) as\r\n | { error?: { code?: string; message?: string } | string }\r\n | undefined;\r\n let code: string = statusToCode(res.status);\r\n let message = `HTTP ${res.status}`;\r\n if (body && typeof body === 'object' && 'error' in body) {\r\n const errField = body.error;\r\n if (typeof errField === 'string') {\r\n message = errField;\r\n } else if (errField && typeof errField === 'object') {\r\n if (typeof errField.code === 'string') code = errField.code;\r\n if (typeof errField.message === 'string') message = errField.message;\r\n }\r\n }\r\n const err = new NeetruError(code, message, res.status, requestId);\r\n lastError = err;\r\n\r\n const isRetryable = RETRYABLE_CODES.has(code as NeetruErrorCode);\r\n if (isRetryable && attempt < maxRetries) {\r\n const retryAfter = parseRetryAfter(res.headers.get('retry-after'));\r\n const delay = retryAfter ?? backoffMs(attempt);\r\n await sleep(delay);\r\n continue;\r\n }\r\n throw err;\r\n }\r\n\r\n // Unreachable — loop sempre retorna ou lança. Safety net.\r\n throw lastError ?? new NeetruError('unknown', 'unexpected httpRequest exit');\r\n}\r\n","/**\n * Validators centralizados pra inputs do SDK que precisam casar com\n * regex do Core.\n *\n * **M-03 fix (Opus review 2026-05-27):** o Core rejeita productId que\n * não bate `/^[a-z0-9][a-z0-9_-]{0,62}$/` com 400 `validation_failed`.\n * O SDK não pré-validava — consumer recebia erro só em runtime de\n * produção, depois do round-trip de rede. Agora SDK throws localmente\n * antes do fetch.\n */\nimport { NeetruError } from './errors';\n\n/**\n * Regex canonical de IDs no Neetru Core (productId, tenantId, etc).\n * Espelha `SDK_ID_RE` em `neetru_core/src/lib/schemas/sdk.ts`.\n */\nexport const SDK_ID_RE = /^[a-z0-9][a-z0-9_-]{0,62}$/;\n\n/**\n * Throws `NeetruError('validation_failed')` se `value` não bater no\n * formato canonical.\n *\n * @example\n * ```ts\n * assertValidSdkId('productId', 'gestovendas'); // ok\n * assertValidSdkId('productId', 'GestoVendas'); // throws\n * ```\n */\nexport function assertValidSdkId(field: string, value: string): void {\n if (typeof value !== 'string' || !SDK_ID_RE.test(value)) {\n throw new NeetruError(\n 'validation_failed',\n `${field} must match ${SDK_ID_RE.source} (lowercase alphanumeric, _, -; first char must be alphanumeric; max 63 chars)`,\n );\n }\n}\n","/**\r\n * Webhooks namespace (v1.2) — produtos SaaS registram endpoints HTTP no Core\r\n * pra receber notificações de eventos.\r\n *\r\n * Casos típicos:\r\n * - `subscription.activated` quando cliente conclui checkout\r\n * - `subscription.cancelled` / `subscription.payment_failed`\r\n * - `usage.quota_exceeded` quando produto bate teto mensal\r\n * - `account.suspended` quando staff Neetru suspende uma conta\r\n *\r\n * Pull-vs-push: o SDK existente é pull-only (`getQuota`, etc). Webhooks\r\n * fecham o gap pra eventos assíncronos sem o produto precisar fazer polling.\r\n *\r\n * Segurança:\r\n * - Endpoint do produto recebe HMAC SHA-256 em header `X-Neetru-Signature`\r\n * usando `secret` opcional do registro. Sem `secret`, header ausente —\r\n * produto deve usar HTTPS + IP allowlist.\r\n * - Replay protection: header `X-Neetru-Timestamp` (ms) — produto deve\r\n * rejeitar > 5min de skew.\r\n * - Retry: Core retenta 3x com backoff exponencial (1s, 5s, 25s) se 5xx\r\n * ou timeout. Após 3 falhas → marca endpoint `degraded` por 1h.\r\n *\r\n * Endpoints REST (em prod):\r\n * - `POST /api/sdk/v1/webhooks` — registra novo endpoint\r\n * - `GET /api/sdk/v1/webhooks` — lista endpoints do produto\r\n * - `DELETE /api/sdk/v1/webhooks/{id}` — remove endpoint\r\n * - `POST /api/sdk/v1/webhooks/{id}/test` — dispara evento de teste\r\n *\r\n * Mock em `NEETRU_ENV=dev`: tudo in-memory, sem rede.\r\n */\r\nimport { NeetruError } from './errors';\r\nimport { httpRequest } from './http';\r\nimport { assertValidSdkId } from './validators';\r\nimport type { ResolvedConfig } from './types';\r\n\r\n/** Eventos Neetru que produtos podem assinar. Lista expansível por minor bump. */\r\nexport type WebhookEvent =\r\n | 'subscription.activated'\r\n | 'subscription.cancelled'\r\n | 'subscription.payment_failed'\r\n | 'subscription.trial_ending'\r\n | 'usage.quota_exceeded'\r\n | 'account.suspended'\r\n | 'account.reactivated'\r\n | 'support.ticket_replied';\r\n\r\nexport interface WebhookEndpoint {\r\n id: string;\r\n url: string;\r\n events: WebhookEvent[];\r\n /** Quando true, `X-Neetru-Signature` é enviado em cada dispatch. */\r\n hasSecret: boolean;\r\n status: 'active' | 'degraded' | 'disabled';\r\n /** ISO timestamp do último dispatch bem-sucedido. */\r\n lastDeliveryAt?: string;\r\n /** Quantos dispatches falharam consecutivos (resetado em sucesso). */\r\n consecutiveFailures?: number;\r\n createdAt: string;\r\n}\r\n\r\nexport interface RegisterWebhookInput {\r\n /**\r\n * **3.0 (breaking):** `productId` é obrigatório no body. Se ausente,\r\n * SDK tenta resolver do `config.productId` (default no `createNeetruClient`);\r\n * lança `validation_failed` se ambos faltarem.\r\n */\r\n productId?: string;\r\n url: string;\r\n events: WebhookEvent[];\r\n /**\r\n * Secret pra HMAC SHA-256 (mín 16 chars). Recomendado.\r\n * Quando ausente, dispatches vão sem assinatura — produto deve ter\r\n * IP allowlist ou outra defesa.\r\n */\r\n secret?: string;\r\n}\r\n\r\nexport interface WebhookTestResult {\r\n ok: boolean;\r\n statusCode?: number;\r\n durationMs?: number;\r\n error?: string;\r\n}\r\n\r\n/**\r\n * 3.0: opções de scoping — todos os verbos exigem `productId` (default do\r\n * `config.productId` se ausente).\r\n */\r\nexport interface WebhookScopeOptions {\r\n productId?: string;\r\n}\r\n\r\nexport interface WebhooksNamespace {\r\n /** Registra um novo endpoint. */\r\n register(input: RegisterWebhookInput): Promise<WebhookEndpoint>;\r\n /** Lista endpoints registrados pelo produto. */\r\n list(options?: WebhookScopeOptions): Promise<WebhookEndpoint[]>;\r\n /** Remove um endpoint. */\r\n unregister(id: string, options?: WebhookScopeOptions): Promise<{ ok: true }>;\r\n /** Dispara evento de teste pra validar conectividade. */\r\n test(id: string, options?: WebhookScopeOptions): Promise<WebhookTestResult>;\r\n}\r\n\r\n/**\r\n * Verifica assinatura HMAC SHA-256 de payload de webhook recebido pelo\r\n * produto consumer. **3.0**: Universal (browser/Node/Edge) via WebCrypto.subtle.\r\n *\r\n * Constant-time compare via byte-level XOR accumulator (não usa\r\n * `timingSafeEqual` do Node porque WebCrypto não tem equivalente direto).\r\n *\r\n * @param payload Corpo cru da request (string ou Uint8Array). NÃO use o objeto\r\n * parseado — JSON.stringify pode diferir do que foi assinado.\r\n * @param signature Header `X-Neetru-Signature` recebido (formato `sha256=<hex>`).\r\n * @param secret Secret registrado em `webhooks.register({ secret })`.\r\n * @returns Promise<boolean> — true se assinatura confere, false caso contrário.\r\n *\r\n * @example\r\n * ```ts\r\n * // Next.js Route Handler (Edge ou Node runtime — funciona em ambos)\r\n * export async function POST(req: Request) {\r\n * const raw = await req.text();\r\n * const sig = req.headers.get('X-Neetru-Signature');\r\n * const ok = await verifyWebhookSignature(raw, sig, process.env.NEETRU_WEBHOOK_SECRET!);\r\n * if (!ok) return new Response('unauthorized', { status: 401 });\r\n * const event = JSON.parse(raw);\r\n * // ... handle event\r\n * return Response.json({ ok: true });\r\n * }\r\n * ```\r\n *\r\n * @throws NeetruError('runtime_unsupported') se runtime não expõe WebCrypto.\r\n * Não retorna `false` silencioso — caller precisa distinguir \"assinatura\r\n * inválida\" (return false) de \"ambiente não suporta\" (throw).\r\n */\r\nexport async function verifyWebhookSignature(\r\n payload: string | Uint8Array,\r\n signature: string | null | undefined,\r\n secret: string,\r\n): Promise<boolean> {\r\n if (!signature || !secret) return false;\r\n // Aceita \"sha256=<hex>\" ou \"<hex>\" cru.\r\n const sigHex = signature.startsWith('sha256=') ? signature.slice(7) : signature;\r\n if (!/^[0-9a-f]+$/i.test(sigHex)) return false;\r\n\r\n // WebCrypto disponível em Node ≥20, browsers modernos, Edge runtimes.\r\n const subtle: SubtleCrypto | undefined =\r\n typeof globalThis !== 'undefined' && 'crypto' in globalThis\r\n ? (globalThis as { crypto?: { subtle?: SubtleCrypto } }).crypto?.subtle\r\n : undefined;\r\n if (!subtle) {\r\n throw new NeetruError(\r\n 'runtime_unsupported',\r\n 'verifyWebhookSignature requires globalThis.crypto.subtle (Node ≥20, modern browser, or Edge runtime).',\r\n );\r\n }\r\n\r\n const encoder = new TextEncoder();\r\n const keyBytes = encoder.encode(secret);\r\n // TextEncoder.encode retorna Uint8Array<ArrayBuffer>; payload Uint8Array\r\n // pode vir como Uint8Array<ArrayBufferLike> (SharedArrayBuffer compat). Cast\r\n // explicit pra ArrayBuffer view — Web Crypto aceita ambos em runtime.\r\n const payloadBytes: Uint8Array =\r\n typeof payload === 'string' ? encoder.encode(payload) : payload;\r\n\r\n const key = await subtle.importKey(\r\n 'raw',\r\n keyBytes as BufferSource,\r\n { name: 'HMAC', hash: 'SHA-256' },\r\n false,\r\n ['sign'],\r\n );\r\n const macBuffer = await subtle.sign(\r\n 'HMAC',\r\n key,\r\n payloadBytes as BufferSource,\r\n );\r\n const macBytes = new Uint8Array(macBuffer);\r\n\r\n // Decode hex signature em bytes.\r\n const sigBytes = hexToBytes(sigHex.toLowerCase());\r\n if (!sigBytes || sigBytes.length !== macBytes.length) return false;\r\n\r\n // Constant-time compare via XOR accumulator.\r\n let diff = 0;\r\n for (let i = 0; i < macBytes.length; i++) {\r\n diff |= macBytes[i] ^ sigBytes[i];\r\n }\r\n return diff === 0;\r\n}\r\n\r\n// ─── verifyWebhookRequest — assinatura + replay protection ─────────────────\r\n\r\n/**\r\n * Opções de `verifyWebhookRequest`.\r\n */\r\nexport interface VerifyWebhookRequestOptions {\r\n /**\r\n * Janela de tolerância em milliseconds para o skew de timestamp.\r\n * Default: 300_000 (5 minutos), conforme documentado na spec de webhooks.\r\n * Valores menores aumentam a proteção contra replay; valores maiores acomodam\r\n * clocks com drift. Não use valores acima de 600_000 (10 min).\r\n */\r\n toleranceMs?: number;\r\n}\r\n\r\n/**\r\n * Resultado de `verifyWebhookRequest`.\r\n */\r\nexport type VerifyWebhookRequestResult =\r\n | { ok: true }\r\n | { ok: false; reason: 'invalid_signature' | 'timestamp_missing' | 'timestamp_expired' | 'runtime_unsupported' };\r\n\r\n/**\r\n * Helper server-only que combina:\r\n * 1. Verificação de assinatura HMAC-SHA256 (`X-Neetru-Signature`)\r\n * 2. **Replay-protection** via skew de timestamp (`X-Neetru-Timestamp`)\r\n *\r\n * Rejeita o request se o timestamp estiver fora da janela `toleranceMs`\r\n * (default ±5 min). Isso fecha a janela de replay onde um atacante captura\r\n * um request válido e o re-envia mais tarde.\r\n *\r\n * **Use este helper em vez de `verifyWebhookSignature` diretamente** — ele\r\n * é a forma correta de validar um webhook Neetru em produção.\r\n *\r\n * @param payload Corpo cru da request (string ou Uint8Array).\r\n * @param headers Headers do request (pode ser um `Headers` Web API ou\r\n * `Record<string, string | undefined>`). Lidos: `X-Neetru-Signature` e\r\n * `X-Neetru-Timestamp`.\r\n * @param secret Secret registrado em `webhooks.register({ secret })`.\r\n * @param options Opções adicionais (ex: `toleranceMs`).\r\n * @returns `{ ok: true }` ou `{ ok: false, reason }` — nunca lança, a menos\r\n * que o runtime não suporte WebCrypto (então propaga `NeetruError('runtime_unsupported')`).\r\n *\r\n * @example\r\n * ```ts\r\n * // Next.js Route Handler\r\n * export async function POST(req: Request) {\r\n * const raw = await req.text();\r\n * const result = await verifyWebhookRequest(raw, req.headers, process.env.NEETRU_WEBHOOK_SECRET!);\r\n * if (!result.ok) {\r\n * console.warn('Webhook rejeitado:', result.reason);\r\n * return new Response('unauthorized', { status: 401 });\r\n * }\r\n * const event = JSON.parse(raw);\r\n * // ... handle event\r\n * return Response.json({ ok: true });\r\n * }\r\n * ```\r\n */\r\nexport async function verifyWebhookRequest(\r\n payload: string | Uint8Array,\r\n headers: Headers | Record<string, string | undefined>,\r\n secret: string,\r\n options: VerifyWebhookRequestOptions = {},\r\n): Promise<VerifyWebhookRequestResult> {\r\n const toleranceMs = options.toleranceMs ?? 300_000; // 5 minutos\r\n\r\n // Lê os headers de forma compatível com Web API Headers e Record<string, string>\r\n const getHeader = (name: string): string | null | undefined => {\r\n if (typeof (headers as Headers).get === 'function') {\r\n return (headers as Headers).get(name);\r\n }\r\n const rec = headers as Record<string, string | undefined>;\r\n // Normaliza pra lowercase pra lidar com variações de casing\r\n const lower = name.toLowerCase();\r\n for (const key of Object.keys(rec)) {\r\n if (key.toLowerCase() === lower) return rec[key] ?? null;\r\n }\r\n return null;\r\n };\r\n\r\n // 1. Verifica skew de timestamp ANTES da criptografia (fail-fast barato)\r\n // getHeader já normaliza lowercase (Record) e Headers.get é case-insensitive — redundância removida\r\n const tsHeader = getHeader('x-neetru-timestamp');\r\n if (!tsHeader) {\r\n return { ok: false, reason: 'timestamp_missing' };\r\n }\r\n const tsMs = Number(tsHeader);\r\n if (!Number.isFinite(tsMs)) {\r\n return { ok: false, reason: 'timestamp_missing' };\r\n }\r\n const skewMs = Math.abs(Date.now() - tsMs);\r\n if (skewMs > toleranceMs) {\r\n return { ok: false, reason: 'timestamp_expired' };\r\n }\r\n\r\n // 2. Verifica assinatura HMAC-SHA256 (WebCrypto — pode lançar runtime_unsupported)\r\n const sig = getHeader('x-neetru-signature');\r\n const valid = await verifyWebhookSignature(payload, sig, secret);\r\n if (!valid) {\r\n return { ok: false, reason: 'invalid_signature' };\r\n }\r\n\r\n return { ok: true };\r\n}\r\n\r\n/** Hex → bytes. Retorna null em input com tamanho ímpar/inválido. */\r\nfunction hexToBytes(hex: string): Uint8Array | null {\r\n if (hex.length % 2 !== 0) return null;\r\n const bytes = new Uint8Array(hex.length / 2);\r\n for (let i = 0; i < bytes.length; i++) {\r\n const high = parseInt(hex[i * 2], 16);\r\n const low = parseInt(hex[i * 2 + 1], 16);\r\n if (Number.isNaN(high) || Number.isNaN(low)) return null;\r\n bytes[i] = (high << 4) | low;\r\n }\r\n return bytes;\r\n}\r\n\r\n// ─── HTTP impl ──────────────────────────────────────────────────────────────\r\n\r\nconst VALID_EVENTS: readonly WebhookEvent[] = [\r\n 'subscription.activated',\r\n 'subscription.cancelled',\r\n 'subscription.payment_failed',\r\n 'subscription.trial_ending',\r\n 'usage.quota_exceeded',\r\n 'account.suspended',\r\n 'account.reactivated',\r\n 'support.ticket_replied',\r\n];\r\n\r\nfunction toEndpoint(raw: unknown): WebhookEndpoint {\r\n if (!raw || typeof raw !== 'object') {\r\n throw new NeetruError('invalid_response', 'Webhook response is not an object');\r\n }\r\n const r = raw as Record<string, unknown>;\r\n if (typeof r.id !== 'string') {\r\n throw new NeetruError('invalid_response', 'Webhook missing id');\r\n }\r\n return {\r\n id: r.id,\r\n url: typeof r.url === 'string' ? r.url : '',\r\n events: Array.isArray(r.events)\r\n ? (r.events as unknown[]).filter((e): e is WebhookEvent =>\r\n VALID_EVENTS.includes(e as WebhookEvent),\r\n )\r\n : [],\r\n hasSecret: r.hasSecret === true,\r\n status:\r\n r.status === 'active' || r.status === 'degraded' || r.status === 'disabled'\r\n ? r.status\r\n : 'active',\r\n lastDeliveryAt: typeof r.lastDeliveryAt === 'string' ? r.lastDeliveryAt : undefined,\r\n consecutiveFailures:\r\n typeof r.consecutiveFailures === 'number' ? r.consecutiveFailures : undefined,\r\n createdAt: typeof r.createdAt === 'string' ? r.createdAt : new Date().toISOString(),\r\n };\r\n}\r\n\r\nfunction validateInput(input: RegisterWebhookInput): void {\r\n if (!input.url || typeof input.url !== 'string') {\r\n throw new NeetruError('validation_failed', 'url é obrigatória');\r\n }\r\n try {\r\n const parsed = new URL(input.url);\r\n if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {\r\n throw new Error('invalid protocol');\r\n }\r\n // Em prod, http: é warning (não bloqueia) — testes locais podem usar\r\n } catch {\r\n throw new NeetruError('validation_failed', `url inválida: ${input.url}`);\r\n }\r\n if (!Array.isArray(input.events) || input.events.length === 0) {\r\n throw new NeetruError('validation_failed', 'events deve ter pelo menos 1 evento');\r\n }\r\n for (const ev of input.events) {\r\n if (!VALID_EVENTS.includes(ev)) {\r\n throw new NeetruError('validation_failed', `evento desconhecido: ${ev}`);\r\n }\r\n }\r\n if (input.secret !== undefined && input.secret.length < 16) {\r\n throw new NeetruError('validation_failed', 'secret deve ter ≥16 chars (recomendado 32+)');\r\n }\r\n}\r\n\r\n/** Resolve productId: option explícito > input.productId > config.productId.\r\n *\r\n * **M-03 fix (Opus review 2026-05-27):** valida client-side contra `SDK_ID_RE`\r\n * antes de mandar pro Core — evita 400 silencioso em produção. */\r\nfunction resolveProductId(\r\n config: ResolvedConfig,\r\n ...candidates: Array<string | undefined>\r\n): string {\r\n for (const c of candidates) {\r\n if (typeof c === 'string' && c.length > 0) {\r\n assertValidSdkId('productId', c);\r\n return c;\r\n }\r\n }\r\n if (config.productId) {\r\n assertValidSdkId('productId', config.productId);\r\n return config.productId;\r\n }\r\n throw new NeetruError(\r\n 'validation_failed',\r\n 'productId required (pass to options/input or set on createNeetruClient)',\r\n );\r\n}\r\n\r\nexport function createWebhooksNamespace(config: ResolvedConfig): WebhooksNamespace {\r\n return {\r\n async register(input) {\r\n validateInput(input);\r\n const productId = resolveProductId(config, input.productId);\r\n const raw = await httpRequest<unknown>(config, {\r\n method: 'POST',\r\n path: '/api/sdk/v1/webhooks',\r\n body: {\r\n productId,\r\n url: input.url,\r\n events: input.events,\r\n ...(input.secret ? { secret: input.secret } : {}),\r\n },\r\n requireAuth: true,\r\n });\r\n return toEndpoint(raw);\r\n },\r\n async list(options) {\r\n const productId = resolveProductId(config, options?.productId);\r\n const raw = await httpRequest<{ endpoints?: unknown[] }>(config, {\r\n method: 'GET',\r\n path: '/api/sdk/v1/webhooks',\r\n query: { productId },\r\n requireAuth: true,\r\n });\r\n const list = Array.isArray(raw?.endpoints) ? raw.endpoints : [];\r\n return list.map(toEndpoint);\r\n },\r\n async unregister(id, options) {\r\n if (!id) throw new NeetruError('validation_failed', 'id obrigatório');\r\n const productId = resolveProductId(config, options?.productId);\r\n await httpRequest<unknown>(config, {\r\n method: 'DELETE',\r\n path: `/api/sdk/v1/webhooks/${encodeURIComponent(id)}`,\r\n query: { productId },\r\n requireAuth: true,\r\n });\r\n return { ok: true };\r\n },\r\n async test(id, options) {\r\n if (!id) throw new NeetruError('validation_failed', 'id obrigatório');\r\n const productId = resolveProductId(config, options?.productId);\r\n const raw = await httpRequest<unknown>(config, {\r\n method: 'POST',\r\n path: `/api/sdk/v1/webhooks/${encodeURIComponent(id)}/test`,\r\n query: { productId },\r\n requireAuth: true,\r\n idempotencyKey: true,\r\n });\r\n if (!raw || typeof raw !== 'object') {\r\n return { ok: false, error: 'invalid response' };\r\n }\r\n const r = raw as Record<string, unknown>;\r\n return {\r\n ok: r.ok === true,\r\n statusCode: typeof r.statusCode === 'number' ? r.statusCode : undefined,\r\n durationMs: typeof r.durationMs === 'number' ? r.durationMs : undefined,\r\n error: typeof r.error === 'string' ? r.error : undefined,\r\n };\r\n },\r\n };\r\n}\r\n\r\n// ─── Mock impl (dev / tests) ────────────────────────────────────────────────\r\n\r\nexport class MockWebhooks implements WebhooksNamespace {\r\n private endpoints = new Map<string, WebhookEndpoint>();\r\n private nextId = 1;\r\n\r\n async register(input: RegisterWebhookInput): Promise<WebhookEndpoint> {\r\n validateInput(input);\r\n const id = `mock_wh_${this.nextId++}`;\r\n const endpoint: WebhookEndpoint = {\r\n id,\r\n url: input.url,\r\n events: input.events,\r\n hasSecret: !!input.secret,\r\n status: 'active',\r\n createdAt: new Date().toISOString(),\r\n };\r\n this.endpoints.set(id, endpoint);\r\n return endpoint;\r\n }\r\n\r\n async list(_options?: WebhookScopeOptions): Promise<WebhookEndpoint[]> {\r\n return [...this.endpoints.values()];\r\n }\r\n\r\n async unregister(id: string, _options?: WebhookScopeOptions): Promise<{ ok: true }> {\r\n if (!this.endpoints.has(id)) {\r\n throw new NeetruError('not_found', `Webhook ${id} não encontrado`);\r\n }\r\n this.endpoints.delete(id);\r\n return { ok: true };\r\n }\r\n\r\n async test(id: string, _options?: WebhookScopeOptions): Promise<WebhookTestResult> {\r\n if (!this.endpoints.has(id)) {\r\n throw new NeetruError('not_found', `Webhook ${id} não encontrado`);\r\n }\r\n return { ok: true, statusCode: 200, durationMs: 42 };\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/idempotency.ts","../src/http.ts","../src/validators.ts","../src/webhooks.ts"],"names":["err","message"],"mappings":"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","file":"webhooks.cjs","sourcesContent":["/**\r\n * Erros tipados do SDK.\r\n *\r\n * Todo erro lançado pelo SDK estende `NeetruError` — caller pode discriminar\r\n * por `.code` (string estável) sem parsing de message.\r\n */\r\n\r\n/** Códigos de erro estáveis do SDK. Adicionar aqui requer minor bump. */\r\nexport type NeetruErrorCode =\r\n | 'invalid_config'\r\n | 'missing_api_key'\r\n | 'unauthorized'\r\n | 'forbidden'\r\n | 'not_found'\r\n | 'rate_limited'\r\n | 'validation_failed'\r\n | 'network_error'\r\n | 'invalid_response'\r\n | 'server_error'\r\n | 'token_expired'\r\n | 'token_invalid_signature'\r\n | 'token_invalid_audience'\r\n | 'token_invalid_issuer'\r\n /** 3.0: runtime não expõe API necessária (ex: WebCrypto ausente). */\r\n | 'runtime_unsupported'\r\n /**\r\n * 3.1.3 (bug_c1c96a00): o `state` retornado pelo IdP no callback OIDC não bate com o gerado em\r\n * `signIn` (CSRF). Também usado quando não há transação OIDC pendente.\r\n */\r\n | 'oidc_state_mismatch'\r\n /** HTTP 409 — colisão de idempotência ou conflito de recurso. */\r\n | 'conflict'\r\n | 'unknown';\r\n\r\n/**\r\n * Erro tipado padrão do SDK. Sempre lançado em vez de Error genérico.\r\n *\r\n * @example\r\n * ```ts\r\n * try { await client.catalog.list(); }\r\n * catch (e) {\r\n * if (e instanceof NeetruError && e.code === 'rate_limited') retry();\r\n * }\r\n * ```\r\n */\r\nexport class NeetruError extends Error {\r\n public readonly code: NeetruErrorCode | string;\r\n public readonly status?: number;\r\n public readonly requestId?: string;\r\n\r\n constructor(\r\n code: NeetruErrorCode | string,\r\n message: string,\r\n status?: number,\r\n requestId?: string,\r\n ) {\r\n super(message);\r\n this.name = 'NeetruError';\r\n this.code = code;\r\n this.status = status;\r\n this.requestId = requestId;\r\n // Preserva o prototype chain ao herdar de Error (downlevel quirk de TS).\r\n Object.setPrototypeOf(this, NeetruError.prototype);\r\n }\r\n}\r\n","/**\n * Idempotency-Key helper — gera UUID v4 cripto-seguro para identificar\n * mutations não-idempotentes (`usage.report`, `support.createTicket`,\n * `notifications.send`, `webhooks.test`).\n *\n * Estratégia 3.0:\n * - SDK gera UUID v4 por chamada via `randomUUID()` (WebCrypto.subtle não\n * necessário aqui — `crypto.randomUUID()` está em Node 14.17+ e em todos\n * os browsers/Edge runtimes modernos).\n * - Header `Idempotency-Key: <uuid>` é injetado pelo `httpRequest` quando\n * `opts.idempotencyKey === true` OU caller passa explicit `opts.idempotencyKeyValue`.\n * - Core dedup em coleção `usage_idempotency_keys/{key}` TTL 24h (vide\n * `docs/CORE_CHANGES_REQUIRED.md` §2). Se Core ainda não dedupa, o header\n * é benign (ignorado).\n *\n * Defesa em camadas: combinado com `retries: 0` em POSTs (vide http.ts), o\n * risco de double-write em transientes vai pra zero.\n */\nimport { NeetruError } from './errors';\n\n/**\n * Gera UUID v4 criptograficamente seguro. Universal: Node 14.17+, browsers\n * modernos, Edge runtimes (Workers/Vercel Edge/Cloudflare).\n *\n * Fallback puro-JS removido em 3.0 — `crypto.randomUUID()` é ubíquo desde\n * 2022. Se runtime não tem, lança `NeetruError('runtime_unsupported')`\n * (consumer deve polyfillar).\n *\n * **L-01 fix (Opus review 2026-05-27):** antes lançava `Error` cru, que\n * não era pego por `catch (err) { if (err instanceof NeetruError) ... }`\n * dos consumers. Agora throw canonical.\n *\n * @throws NeetruError('runtime_unsupported') se `crypto.randomUUID` não disponível.\n */\nexport function generateIdempotencyKey(): string {\n // WebCrypto (browser/Edge) e Node 14.17+ expõem `crypto.randomUUID()`.\n // Node anterior precisa de `node:crypto` mas SDK 3.0 exige Node ≥20 (vide engines).\n const cryptoObj: { randomUUID?: () => string } | undefined =\n typeof globalThis !== 'undefined' && 'crypto' in globalThis\n ? (globalThis as { crypto?: { randomUUID?: () => string } }).crypto\n : undefined;\n if (cryptoObj && typeof cryptoObj.randomUUID === 'function') {\n return cryptoObj.randomUUID();\n }\n throw new NeetruError(\n 'runtime_unsupported',\n 'crypto.randomUUID not available in this runtime. SDK 3.0 requires Node ≥20 or modern browser/Edge.',\n );\n}\n\n/** Regex UUID v4 — validação para uso interno. */\nexport const UUID_V4_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n","/**\r\n * HTTP transport interno do SDK.\r\n *\r\n * Responsabilidades:\r\n * - Construir URL absoluta a partir de `baseUrl` + path\r\n * - Injetar Bearer token quando `requireAuth=true`\r\n * - Mapear status HTTP → `NeetruError` com `code` estável\r\n * - Parse defensivo de JSON (não lança em body vazio em 204)\r\n * - Retry/backoff exponencial em `rate_limited` (429), `server_error` (5xx)\r\n * e `network_error` (timeout/falha de rede). Honra `Retry-After` quando\r\n * presente.\r\n * - **Captura `X-Neetru-Version`** das respostas e emite `console.warn` quando\r\n * o Core está abaixo da versão mínima para a major do SDK.\r\n *\r\n * Política de retries (mudança breaking 3.0):\r\n * - GET/HEAD: default 2 retries (3 tentativas total) — idempotente, seguro.\r\n * - POST/PUT/PATCH/DELETE: default **0 retries** — mutations podem duplicar\r\n * side effects (ex: `usage.report` incrementa contador). Caller pode\r\n * reativar passando `retries: N` explicitamente ou usar `Idempotency-Key`\r\n * header (gerado automaticamente se `opts.idempotencyKey=true`).\r\n *\r\n * Idempotency-Key (3.0):\r\n * - `opts.idempotencyKey === true` → SDK gera UUID v4 e injeta header.\r\n * - `opts.idempotencyKey === 'uuid-string'` → usa o valor passado.\r\n * - Caller mantém retentos client-side se quiser; Core dedup serverside\r\n * (vide `docs/CORE_CHANGES_REQUIRED.md` §2).\r\n */\r\nimport { NeetruError, type NeetruErrorCode } from './errors';\r\nimport { generateIdempotencyKey } from './idempotency';\r\nimport type { ResolvedConfig } from './types';\r\n\r\n// ─── Compat Matrix SDK↔Core ──────────────────────────────────────────────────\r\n\r\n/**\r\n * Matriz de compatibilidade SDK major → versão mínima do Core.\r\n *\r\n * Formato do Core: CalVer `YYYY.MM.patch+revision` (ex: `2026.05.1+neetru-core-00096-79t`).\r\n * A comparação é feita apenas nas partes `YYYY.MM.patch` (prefixo antes de `+`).\r\n *\r\n * Quando o Core reporta `X-Neetru-Version` abaixo do mínimo para a SDK major\r\n * corrente, o SDK emite `console.warn` uma única vez por sessão de processo.\r\n *\r\n * Atualize esta tabela a cada major de SDK.\r\n */\r\nconst COMPAT_MATRIX: Record<number, string> = {\r\n // SDK major 3.x requer Core ≥ 2026.05.1 (suporte a X-Neetru-Version header,\r\n // runTransaction write-after-read, verifyWebhookRequest, webhooks 3.0+)\r\n 3: '2026.05.1',\r\n};\r\n\r\n/** CalVer sem sufixo `+revision`. Ex: `2026.05.1+abc` → `2026.05.1`. */\r\nfunction stripRevision(v: string): string {\r\n return v.split('+')[0] ?? v;\r\n}\r\n\r\n/**\r\n * Compara dois CalVer (`YYYY.MM.patch`). Retorna negativo se `a < b`,\r\n * positivo se `a > b`, 0 se iguais. Partes não numéricas tratadas como 0.\r\n */\r\nfunction compareCalVer(a: string, b: string): number {\r\n const partsA = stripRevision(a).split('.').map(Number);\r\n const partsB = stripRevision(b).split('.').map(Number);\r\n const len = Math.max(partsA.length, partsB.length);\r\n for (let i = 0; i < len; i++) {\r\n const pa = partsA[i] ?? 0;\r\n const pb = partsB[i] ?? 0;\r\n if (pa !== pb) return pa - pb;\r\n }\r\n return 0;\r\n}\r\n\r\n/** Lê a SDK major a partir da string `VERSION` exportada de `./index`. Fallback 3. */\r\nfunction getSdkMajor(): number {\r\n try {\r\n // Importação estática não disponível aqui (evita ciclo). Usa variável injetada\r\n // em tempo de build pela tsup via `define`. Fallback para 3 (current major).\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const ver = (globalThis as any).__NEETRU_SDK_VERSION__ as string | undefined;\r\n if (ver) return parseInt(ver.split('.')[0] ?? '3', 10);\r\n } catch {\r\n // ignore\r\n }\r\n return 3;\r\n}\r\n\r\n/** Aviso emitido no máximo uma vez por major detectada pra não spammar logs. */\r\nconst _warnedCoreTooOld = new Set<string>();\r\n\r\n/**\r\n * Verifica se a versão do Core (`X-Neetru-Version`) é compatível com a SDK major.\r\n * Emite `console.warn` quando incompatível (uma vez por processo por versão detectada).\r\n */\r\nexport function checkCoreVersionCompat(coreVersion: string): void {\r\n if (!coreVersion) return;\r\n const sdkMajor = getSdkMajor();\r\n const minCore = COMPAT_MATRIX[sdkMajor];\r\n if (!minCore) return; // sem restrição para esta major\r\n const stripped = stripRevision(coreVersion);\r\n if (compareCalVer(stripped, minCore) < 0) {\r\n const key = `${sdkMajor}:${stripped}`;\r\n if (!_warnedCoreTooOld.has(key)) {\r\n _warnedCoreTooOld.add(key);\r\n console.warn(\r\n `[Neetru SDK] Atenção: Core versão \"${coreVersion}\" é anterior ao mínimo recomendado` +\r\n ` \"${minCore}\" para SDK major ${sdkMajor}. Alguns recursos podem não funcionar` +\r\n ` corretamente. Atualize o Core para a versão mais recente.`,\r\n );\r\n }\r\n }\r\n}\r\n\r\n/** Opções da request HTTP. */\r\nexport interface HttpRequestOptions {\r\n method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\r\n /** Path relativo (ex: `/api/v1/cli/catalog`). Concatenado a `baseUrl`. */\r\n path: string;\r\n /** Query string params (chave → valor primitivo). Valores `undefined` ignorados. */\r\n query?: Record<string, string | number | boolean | undefined>;\r\n /** Body JSON-serializável. Ignorado em GET/DELETE. */\r\n body?: unknown;\r\n /**\r\n * Se true, injeta `Authorization: Bearer <apiKey>`. Lança `missing_api_key`\r\n * se config.apiKey ausente. Default false.\r\n */\r\n requireAuth?: boolean;\r\n /** Cabeçalhos extras. */\r\n headers?: Record<string, string>;\r\n /**\r\n * Número de retries em códigos transientes (`rate_limited`, `server_error`,\r\n * `network_error`).\r\n *\r\n * Default (3.0):\r\n * - GET/HEAD: 2 (= 3 tentativas total) — idempotente, seguro.\r\n * - POST/PUT/PATCH/DELETE: 0 — mutations podem duplicar side effects.\r\n *\r\n * Caller pode reativar passando explicitamente: `retries: 2`.\r\n */\r\n retries?: number;\r\n /**\r\n * Injeta `Idempotency-Key` header pra dedup serverside (3.0):\r\n * - `true` → SDK gera UUID v4 cripto-seguro automaticamente.\r\n * - string → usa o valor passado (deve ser UUID v4).\r\n * - `undefined`/`false` → sem header.\r\n */\r\n idempotencyKey?: boolean | string;\r\n}\r\n\r\nconst DEFAULT_RETRIES_READ = 2;\r\nconst DEFAULT_RETRIES_WRITE = 0;\r\nconst READ_METHODS = new Set(['GET', 'HEAD']);\r\nconst RETRYABLE_CODES = new Set<NeetruErrorCode>([\r\n 'rate_limited',\r\n 'server_error',\r\n 'network_error',\r\n]);\r\n\r\n/** Backoff exponencial com jitter ±20%. attempt: 0=primeira, 1=primeiro retry, ... */\r\nfunction backoffMs(attempt: number): number {\r\n const base = 200 * Math.pow(4, attempt); // 200ms, 800ms, 3.2s, ...\r\n const jitter = base * 0.2 * (Math.random() * 2 - 1);\r\n return Math.max(50, Math.round(base + jitter));\r\n}\r\n\r\n/**\r\n * Honra `Retry-After` header (segundos ou HTTP-date). Retorna ms ou null se\r\n * inválido. RFC 9110 §10.2.3.\r\n *\r\n * Bug fix: sem teto, um servidor hostil/mal-configurado poderia retornar\r\n * `Retry-After: 86400` (24h) ou uma HTTP-date anos no futuro, pendurando o\r\n * processo indefinidamente. Aplica teto de MAX_RETRY_AFTER_MS em ambos os caminhos.\r\n */\r\nconst MAX_RETRY_AFTER_MS = 60_000; // 60s — teto razoável para retry automático\r\n\r\nfunction parseRetryAfter(value: string | null): number | null {\r\n if (!value) return null;\r\n const secs = Number(value);\r\n if (Number.isFinite(secs) && secs >= 0) return Math.min(Math.round(secs * 1000), MAX_RETRY_AFTER_MS);\r\n const dateMs = Date.parse(value);\r\n if (Number.isFinite(dateMs)) {\r\n const delta = dateMs - Date.now();\r\n if (delta > 0) return Math.min(delta, MAX_RETRY_AFTER_MS);\r\n }\r\n return null;\r\n}\r\n\r\nfunction sleep(ms: number): Promise<void> {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n}\r\n\r\n/** Mapeamento status → code estável do NeetruError. */\r\nfunction statusToCode(status: number): NeetruErrorCode {\r\n if (status === 401) return 'unauthorized';\r\n if (status === 403) return 'forbidden';\r\n if (status === 404) return 'not_found';\r\n if (status === 409) return 'conflict'; // Bug fix: 409 vira 'conflict' (não 'unknown')\r\n if (status === 422 || status === 400) return 'validation_failed';\r\n if (status === 429) return 'rate_limited';\r\n if (status >= 500) return 'server_error';\r\n return 'unknown';\r\n}\r\n\r\nfunction buildUrl(baseUrl: string, path: string, query?: HttpRequestOptions['query']): string {\r\n // Trim trailing slash em base e leading em path pra evitar `//`.\r\n const base = baseUrl.replace(/\\/+$/, '');\r\n const p = path.startsWith('/') ? path : `/${path}`;\r\n const url = new URL(`${base}${p}`);\r\n if (query) {\r\n for (const [k, v] of Object.entries(query)) {\r\n if (v === undefined) continue;\r\n url.searchParams.set(k, String(v));\r\n }\r\n }\r\n return url.toString();\r\n}\r\n\r\n/** Parse JSON defensivo — retorna `undefined` em body vazio. */\r\nasync function safeJson(res: Response): Promise<unknown> {\r\n const text = await res.text();\r\n if (!text) return undefined;\r\n try {\r\n return JSON.parse(text);\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\n/**\r\n * Executa request HTTP. Em sucesso retorna body parseado; em erro lança\r\n * `NeetruError` com `code` derivado do status. Aplica retry/backoff\r\n * automático em códigos transientes (rate_limited/server_error/network_error)\r\n * conforme `opts.retries` (default 2 = 3 tentativas).\r\n */\r\nexport async function httpRequest<T>(\r\n config: ResolvedConfig,\r\n opts: HttpRequestOptions,\r\n): Promise<T> {\r\n const method = opts.method ?? 'GET';\r\n const url = buildUrl(config.baseUrl, opts.path, opts.query);\r\n // Default por método: reads tentam 2x, writes 0x. Caller override sempre vence.\r\n const defaultRetries = READ_METHODS.has(method)\r\n ? DEFAULT_RETRIES_READ\r\n : DEFAULT_RETRIES_WRITE;\r\n const maxRetries = opts.retries ?? defaultRetries;\r\n\r\n const headers: Record<string, string> = {\r\n accept: 'application/json',\r\n ...opts.headers,\r\n };\r\n\r\n if (opts.requireAuth) {\r\n if (!config.apiKey) {\r\n throw new NeetruError(\r\n 'missing_api_key',\r\n 'This operation requires an apiKey. Pass it to createNeetruClient({ apiKey }) or set NEETRU_API_KEY env var.',\r\n );\r\n }\r\n headers.authorization = `Bearer ${config.apiKey}`;\r\n }\r\n\r\n // Idempotency-Key: gerado por chamada se solicitado. UUID v4 cripto-seguro.\r\n if (opts.idempotencyKey) {\r\n const key =\r\n typeof opts.idempotencyKey === 'string'\r\n ? opts.idempotencyKey\r\n : generateIdempotencyKey();\r\n headers['idempotency-key'] = key;\r\n }\r\n\r\n // Body só é serializado uma vez — reusado entre tentativas.\r\n const bodyString =\r\n opts.body !== undefined && method !== 'GET' && method !== 'DELETE'\r\n ? JSON.stringify(opts.body)\r\n : undefined;\r\n if (bodyString !== undefined) {\r\n headers['content-type'] = 'application/json';\r\n }\r\n\r\n let lastError: NeetruError | null = null;\r\n\r\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\r\n const init: RequestInit = { method, headers };\r\n if (bodyString !== undefined) init.body = bodyString;\r\n // BUG-020 fix (2026-05-13): timeout default 30s. AbortSignal.timeout\r\n // requer Node 18+ ou browsers recentes.\r\n init.signal = AbortSignal.timeout(30_000);\r\n\r\n let res: Response;\r\n try {\r\n res = await config.fetch(url, init);\r\n } catch (err) {\r\n const message =\r\n err instanceof DOMException && err.name === 'TimeoutError'\r\n ? 'Network error: timeout after 30s'\r\n : `Network error: ${err instanceof Error ? err.message : 'fetch failed'}`;\r\n lastError = new NeetruError('network_error', message);\r\n if (attempt < maxRetries) {\r\n await sleep(backoffMs(attempt));\r\n continue;\r\n }\r\n throw lastError;\r\n }\r\n\r\n const requestId =\r\n res.headers.get('x-request-id') ?? res.headers.get('x-correlation-id') ?? undefined;\r\n\r\n if (res.ok) {\r\n // Captura X-Neetru-Version e verifica compat com a SDK major.\r\n const coreVersion = res.headers.get('x-neetru-version');\r\n if (coreVersion) checkCoreVersionCompat(coreVersion);\r\n const parsed = await safeJson(res);\r\n return parsed as T;\r\n }\r\n\r\n const body = (await safeJson(res)) as\r\n | { error?: { code?: string; message?: string } | string }\r\n | undefined;\r\n let code: string = statusToCode(res.status);\r\n let message = `HTTP ${res.status}`;\r\n if (body && typeof body === 'object' && 'error' in body) {\r\n const errField = body.error;\r\n if (typeof errField === 'string') {\r\n message = errField;\r\n } else if (errField && typeof errField === 'object') {\r\n if (typeof errField.code === 'string') code = errField.code;\r\n if (typeof errField.message === 'string') message = errField.message;\r\n }\r\n }\r\n const err = new NeetruError(code, message, res.status, requestId);\r\n lastError = err;\r\n\r\n const isRetryable = RETRYABLE_CODES.has(code as NeetruErrorCode);\r\n if (isRetryable && attempt < maxRetries) {\r\n const retryAfter = parseRetryAfter(res.headers.get('retry-after'));\r\n const delay = retryAfter ?? backoffMs(attempt);\r\n await sleep(delay);\r\n continue;\r\n }\r\n throw err;\r\n }\r\n\r\n // Unreachable — loop sempre retorna ou lança. Safety net.\r\n throw lastError ?? new NeetruError('unknown', 'unexpected httpRequest exit');\r\n}\r\n","/**\n * Validators centralizados pra inputs do SDK que precisam casar com\n * regex do Core.\n *\n * **M-03 fix (Opus review 2026-05-27):** o Core rejeita productId que\n * não bate `/^[a-z0-9][a-z0-9_-]{0,62}$/` com 400 `validation_failed`.\n * O SDK não pré-validava — consumer recebia erro só em runtime de\n * produção, depois do round-trip de rede. Agora SDK throws localmente\n * antes do fetch.\n */\nimport { NeetruError } from './errors';\n\n/**\n * Regex canonical de IDs no Neetru Core (productId, tenantId, etc).\n * Espelha `SDK_ID_RE` em `neetru_core/src/lib/schemas/sdk.ts`.\n */\nexport const SDK_ID_RE = /^[a-z0-9][a-z0-9_-]{0,62}$/;\n\n/**\n * Throws `NeetruError('validation_failed')` se `value` não bater no\n * formato canonical.\n *\n * @example\n * ```ts\n * assertValidSdkId('productId', 'gestovendas'); // ok\n * assertValidSdkId('productId', 'GestoVendas'); // throws\n * ```\n */\nexport function assertValidSdkId(field: string, value: string): void {\n if (typeof value !== 'string' || !SDK_ID_RE.test(value)) {\n throw new NeetruError(\n 'validation_failed',\n `${field} must match ${SDK_ID_RE.source} (lowercase alphanumeric, _, -; first char must be alphanumeric; max 63 chars)`,\n );\n }\n}\n","/**\r\n * Webhooks namespace (v1.2) — produtos SaaS registram endpoints HTTP no Core\r\n * pra receber notificações de eventos.\r\n *\r\n * Casos típicos:\r\n * - `subscription.activated` quando cliente conclui checkout\r\n * - `subscription.cancelled` / `subscription.payment_failed`\r\n * - `usage.quota_exceeded` quando produto bate teto mensal\r\n * - `account.suspended` quando staff Neetru suspende uma conta\r\n *\r\n * Pull-vs-push: o SDK existente é pull-only (`getQuota`, etc). Webhooks\r\n * fecham o gap pra eventos assíncronos sem o produto precisar fazer polling.\r\n *\r\n * Segurança:\r\n * - Endpoint do produto recebe HMAC SHA-256 em header `X-Neetru-Signature`\r\n * usando `secret` opcional do registro. Sem `secret`, header ausente —\r\n * produto deve usar HTTPS + IP allowlist.\r\n * - Replay protection: header `X-Neetru-Timestamp` (ms) — produto deve\r\n * rejeitar > 5min de skew.\r\n * - Retry: Core retenta 3x com backoff exponencial (1s, 5s, 25s) se 5xx\r\n * ou timeout. Após 3 falhas → marca endpoint `degraded` por 1h.\r\n *\r\n * Endpoints REST (em prod):\r\n * - `POST /api/sdk/v1/webhooks` — registra novo endpoint\r\n * - `GET /api/sdk/v1/webhooks` — lista endpoints do produto\r\n * - `DELETE /api/sdk/v1/webhooks/{id}` — remove endpoint\r\n * - `POST /api/sdk/v1/webhooks/{id}/test` — dispara evento de teste\r\n *\r\n * Mock em `NEETRU_ENV=dev`: tudo in-memory, sem rede.\r\n */\r\nimport { NeetruError } from './errors';\r\nimport { httpRequest } from './http';\r\nimport { assertValidSdkId } from './validators';\r\nimport type { ResolvedConfig } from './types';\r\n\r\n/** Eventos Neetru que produtos podem assinar. Lista expansível por minor bump. */\r\nexport type WebhookEvent =\r\n | 'subscription.activated'\r\n | 'subscription.cancelled'\r\n | 'subscription.payment_failed'\r\n | 'subscription.trial_ending'\r\n | 'usage.quota_exceeded'\r\n | 'account.suspended'\r\n | 'account.reactivated'\r\n | 'support.ticket_replied';\r\n\r\nexport interface WebhookEndpoint {\r\n id: string;\r\n url: string;\r\n events: WebhookEvent[];\r\n /** Quando true, `X-Neetru-Signature` é enviado em cada dispatch. */\r\n hasSecret: boolean;\r\n status: 'active' | 'degraded' | 'disabled';\r\n /** ISO timestamp do último dispatch bem-sucedido. */\r\n lastDeliveryAt?: string;\r\n /** Quantos dispatches falharam consecutivos (resetado em sucesso). */\r\n consecutiveFailures?: number;\r\n createdAt: string;\r\n}\r\n\r\nexport interface RegisterWebhookInput {\r\n /**\r\n * **3.0 (breaking):** `productId` é obrigatório no body. Se ausente,\r\n * SDK tenta resolver do `config.productId` (default no `createNeetruClient`);\r\n * lança `validation_failed` se ambos faltarem.\r\n */\r\n productId?: string;\r\n url: string;\r\n events: WebhookEvent[];\r\n /**\r\n * Secret pra HMAC SHA-256 (mín 16 chars). Recomendado.\r\n * Quando ausente, dispatches vão sem assinatura — produto deve ter\r\n * IP allowlist ou outra defesa.\r\n */\r\n secret?: string;\r\n}\r\n\r\nexport interface WebhookTestResult {\r\n ok: boolean;\r\n statusCode?: number;\r\n durationMs?: number;\r\n error?: string;\r\n}\r\n\r\n/**\r\n * 3.0: opções de scoping — todos os verbos exigem `productId` (default do\r\n * `config.productId` se ausente).\r\n */\r\nexport interface WebhookScopeOptions {\r\n productId?: string;\r\n}\r\n\r\nexport interface WebhooksNamespace {\r\n /** Registra um novo endpoint. */\r\n register(input: RegisterWebhookInput): Promise<WebhookEndpoint>;\r\n /** Lista endpoints registrados pelo produto. */\r\n list(options?: WebhookScopeOptions): Promise<WebhookEndpoint[]>;\r\n /** Remove um endpoint. */\r\n unregister(id: string, options?: WebhookScopeOptions): Promise<{ ok: true }>;\r\n /** Dispara evento de teste pra validar conectividade. */\r\n test(id: string, options?: WebhookScopeOptions): Promise<WebhookTestResult>;\r\n}\r\n\r\n/**\r\n * Verifica assinatura HMAC SHA-256 de payload de webhook recebido pelo\r\n * produto consumer. **3.0**: Universal (browser/Node/Edge) via WebCrypto.subtle.\r\n *\r\n * Constant-time compare via byte-level XOR accumulator (não usa\r\n * `timingSafeEqual` do Node porque WebCrypto não tem equivalente direto).\r\n *\r\n * **3.1.3 (auditoria 2026-06-10)**: o Core assina HMAC sobre\r\n * `` `${timestamp}.${rawBody}` `` (vide `computeWebhookSignature` em\r\n * `functions/src/lib/webhook-delivery-core.ts`) — o `timestamp` é o valor do\r\n * header `X-Neetru-Timestamp`. Passe-o no 4º parâmetro; sem ele o HMAC é\r\n * computado só sobre o body e NUNCA confere com entregas reais do Core.\r\n * Prefira `verifyWebhookRequest`, que lê os headers e já faz tudo.\r\n *\r\n * @param payload Corpo cru da request (string ou Uint8Array). NÃO use o objeto\r\n * parseado — JSON.stringify pode diferir do que foi assinado.\r\n * @param signature Header `X-Neetru-Signature` recebido (formato `sha256=<hex>`).\r\n * @param secret Secret registrado em `webhooks.register({ secret })`.\r\n * @param timestamp Valor do header `X-Neetru-Timestamp` (ms epoch). Quando\r\n * presente, o HMAC cobre `` `${timestamp}.${payload}` ``\r\n * (esquema canônico do Core — replay protection embutida).\r\n * @returns Promise<boolean> — true se assinatura confere, false caso contrário.\r\n *\r\n * @example\r\n * ```ts\r\n * // Next.js Route Handler (Edge ou Node runtime — funciona em ambos)\r\n * export async function POST(req: Request) {\r\n * const raw = await req.text();\r\n * const sig = req.headers.get('X-Neetru-Signature');\r\n * const ts = req.headers.get('X-Neetru-Timestamp');\r\n * const ok = await verifyWebhookSignature(raw, sig, process.env.NEETRU_WEBHOOK_SECRET!, ts ?? undefined);\r\n * if (!ok) return new Response('unauthorized', { status: 401 });\r\n * const event = JSON.parse(raw);\r\n * // ... handle event\r\n * return Response.json({ ok: true });\r\n * }\r\n * ```\r\n *\r\n * @throws NeetruError('runtime_unsupported') se runtime não expõe WebCrypto.\r\n * Não retorna `false` silencioso — caller precisa distinguir \"assinatura\r\n * inválida\" (return false) de \"ambiente não suporta\" (throw).\r\n */\r\nexport async function verifyWebhookSignature(\r\n payload: string | Uint8Array,\r\n signature: string | null | undefined,\r\n secret: string,\r\n timestamp?: string | number,\r\n): Promise<boolean> {\r\n if (!signature || !secret) return false;\r\n // Aceita \"sha256=<hex>\" ou \"<hex>\" cru.\r\n const sigHex = signature.startsWith('sha256=') ? signature.slice(7) : signature;\r\n if (!/^[0-9a-f]+$/i.test(sigHex)) return false;\r\n\r\n // WebCrypto disponível em Node ≥20, browsers modernos, Edge runtimes.\r\n const subtle: SubtleCrypto | undefined =\r\n typeof globalThis !== 'undefined' && 'crypto' in globalThis\r\n ? (globalThis as { crypto?: { subtle?: SubtleCrypto } }).crypto?.subtle\r\n : undefined;\r\n if (!subtle) {\r\n throw new NeetruError(\r\n 'runtime_unsupported',\r\n 'verifyWebhookSignature requires globalThis.crypto.subtle (Node ≥20, modern browser, or Edge runtime).',\r\n );\r\n }\r\n\r\n const encoder = new TextEncoder();\r\n const keyBytes = encoder.encode(secret);\r\n // TextEncoder.encode retorna Uint8Array<ArrayBuffer>; payload Uint8Array\r\n // pode vir como Uint8Array<ArrayBufferLike> (SharedArrayBuffer compat). Cast\r\n // explicit pra ArrayBuffer view — Web Crypto aceita ambos em runtime.\r\n const rawBytes: Uint8Array =\r\n typeof payload === 'string' ? encoder.encode(payload) : payload;\r\n // Esquema canônico do Core: HMAC(`${timestamp}.${rawBody}`). Sem timestamp,\r\n // assina só o body (compat com verificações custom fora do fluxo Core).\r\n let payloadBytes: Uint8Array = rawBytes;\r\n if (timestamp !== undefined) {\r\n const prefix = encoder.encode(`${timestamp}.`);\r\n const merged = new Uint8Array(prefix.length + rawBytes.length);\r\n merged.set(prefix, 0);\r\n merged.set(rawBytes, prefix.length);\r\n payloadBytes = merged;\r\n }\r\n\r\n const key = await subtle.importKey(\r\n 'raw',\r\n keyBytes as BufferSource,\r\n { name: 'HMAC', hash: 'SHA-256' },\r\n false,\r\n ['sign'],\r\n );\r\n const macBuffer = await subtle.sign(\r\n 'HMAC',\r\n key,\r\n payloadBytes as BufferSource,\r\n );\r\n const macBytes = new Uint8Array(macBuffer);\r\n\r\n // Decode hex signature em bytes.\r\n const sigBytes = hexToBytes(sigHex.toLowerCase());\r\n if (!sigBytes || sigBytes.length !== macBytes.length) return false;\r\n\r\n // Constant-time compare via XOR accumulator.\r\n let diff = 0;\r\n for (let i = 0; i < macBytes.length; i++) {\r\n diff |= macBytes[i] ^ sigBytes[i];\r\n }\r\n return diff === 0;\r\n}\r\n\r\n// ─── verifyWebhookRequest — assinatura + replay protection ─────────────────\r\n\r\n/**\r\n * Opções de `verifyWebhookRequest`.\r\n */\r\nexport interface VerifyWebhookRequestOptions {\r\n /**\r\n * Janela de tolerância em milliseconds para o skew de timestamp.\r\n * Default: 300_000 (5 minutos), conforme documentado na spec de webhooks.\r\n * Valores menores aumentam a proteção contra replay; valores maiores acomodam\r\n * clocks com drift. Não use valores acima de 600_000 (10 min).\r\n */\r\n toleranceMs?: number;\r\n}\r\n\r\n/**\r\n * Resultado de `verifyWebhookRequest`.\r\n */\r\nexport type VerifyWebhookRequestResult =\r\n | { ok: true }\r\n | { ok: false; reason: 'invalid_signature' | 'timestamp_missing' | 'timestamp_expired' | 'runtime_unsupported' };\r\n\r\n/**\r\n * Helper server-only que combina:\r\n * 1. Verificação de assinatura HMAC-SHA256 (`X-Neetru-Signature`)\r\n * 2. **Replay-protection** via skew de timestamp (`X-Neetru-Timestamp`)\r\n *\r\n * Rejeita o request se o timestamp estiver fora da janela `toleranceMs`\r\n * (default ±5 min). Isso fecha a janela de replay onde um atacante captura\r\n * um request válido e o re-envia mais tarde.\r\n *\r\n * **Use este helper em vez de `verifyWebhookSignature` diretamente** — ele\r\n * é a forma correta de validar um webhook Neetru em produção.\r\n *\r\n * @param payload Corpo cru da request (string ou Uint8Array).\r\n * @param headers Headers do request (pode ser um `Headers` Web API ou\r\n * `Record<string, string | undefined>`). Lidos: `X-Neetru-Signature` e\r\n * `X-Neetru-Timestamp`.\r\n * @param secret Secret registrado em `webhooks.register({ secret })`.\r\n * @param options Opções adicionais (ex: `toleranceMs`).\r\n * @returns `{ ok: true }` ou `{ ok: false, reason }` — nunca lança, a menos\r\n * que o runtime não suporte WebCrypto (então propaga `NeetruError('runtime_unsupported')`).\r\n *\r\n * @example\r\n * ```ts\r\n * // Next.js Route Handler\r\n * export async function POST(req: Request) {\r\n * const raw = await req.text();\r\n * const result = await verifyWebhookRequest(raw, req.headers, process.env.NEETRU_WEBHOOK_SECRET!);\r\n * if (!result.ok) {\r\n * console.warn('Webhook rejeitado:', result.reason);\r\n * return new Response('unauthorized', { status: 401 });\r\n * }\r\n * const event = JSON.parse(raw);\r\n * // ... handle event\r\n * return Response.json({ ok: true });\r\n * }\r\n * ```\r\n */\r\nexport async function verifyWebhookRequest(\r\n payload: string | Uint8Array,\r\n headers: Headers | Record<string, string | undefined>,\r\n secret: string,\r\n options: VerifyWebhookRequestOptions = {},\r\n): Promise<VerifyWebhookRequestResult> {\r\n const toleranceMs = options.toleranceMs ?? 300_000; // 5 minutos\r\n\r\n // Lê os headers de forma compatível com Web API Headers e Record<string, string>\r\n const getHeader = (name: string): string | null | undefined => {\r\n if (typeof (headers as Headers).get === 'function') {\r\n return (headers as Headers).get(name);\r\n }\r\n const rec = headers as Record<string, string | undefined>;\r\n // Normaliza pra lowercase pra lidar com variações de casing\r\n const lower = name.toLowerCase();\r\n for (const key of Object.keys(rec)) {\r\n if (key.toLowerCase() === lower) return rec[key] ?? null;\r\n }\r\n return null;\r\n };\r\n\r\n // 1. Verifica skew de timestamp ANTES da criptografia (fail-fast barato)\r\n // getHeader já normaliza lowercase (Record) e Headers.get é case-insensitive — redundância removida\r\n const tsHeader = getHeader('x-neetru-timestamp');\r\n if (!tsHeader) {\r\n return { ok: false, reason: 'timestamp_missing' };\r\n }\r\n const tsMs = Number(tsHeader);\r\n if (!Number.isFinite(tsMs)) {\r\n return { ok: false, reason: 'timestamp_missing' };\r\n }\r\n const skewMs = Math.abs(Date.now() - tsMs);\r\n if (skewMs > toleranceMs) {\r\n return { ok: false, reason: 'timestamp_expired' };\r\n }\r\n\r\n // 2. Verifica assinatura HMAC-SHA256 (WebCrypto — pode lançar runtime_unsupported).\r\n // 3.1.3 fix (auditoria 2026-06-10): o HMAC do Core cobre `${timestamp}.${rawBody}`\r\n // — antes verificávamos só o body, então TODA entrega legítima falhava aqui.\r\n const sig = getHeader('x-neetru-signature');\r\n const valid = await verifyWebhookSignature(payload, sig, secret, tsHeader);\r\n if (!valid) {\r\n return { ok: false, reason: 'invalid_signature' };\r\n }\r\n\r\n return { ok: true };\r\n}\r\n\r\n/** Hex → bytes. Retorna null em input com tamanho ímpar/inválido. */\r\nfunction hexToBytes(hex: string): Uint8Array | null {\r\n if (hex.length % 2 !== 0) return null;\r\n const bytes = new Uint8Array(hex.length / 2);\r\n for (let i = 0; i < bytes.length; i++) {\r\n const high = parseInt(hex[i * 2], 16);\r\n const low = parseInt(hex[i * 2 + 1], 16);\r\n if (Number.isNaN(high) || Number.isNaN(low)) return null;\r\n bytes[i] = (high << 4) | low;\r\n }\r\n return bytes;\r\n}\r\n\r\n// ─── HTTP impl ──────────────────────────────────────────────────────────────\r\n\r\nconst VALID_EVENTS: readonly WebhookEvent[] = [\r\n 'subscription.activated',\r\n 'subscription.cancelled',\r\n 'subscription.payment_failed',\r\n 'subscription.trial_ending',\r\n 'usage.quota_exceeded',\r\n 'account.suspended',\r\n 'account.reactivated',\r\n 'support.ticket_replied',\r\n];\r\n\r\nfunction toEndpoint(raw: unknown): WebhookEndpoint {\r\n if (!raw || typeof raw !== 'object') {\r\n throw new NeetruError('invalid_response', 'Webhook response is not an object');\r\n }\r\n const r = raw as Record<string, unknown>;\r\n if (typeof r.id !== 'string') {\r\n throw new NeetruError('invalid_response', 'Webhook missing id');\r\n }\r\n return {\r\n id: r.id,\r\n url: typeof r.url === 'string' ? r.url : '',\r\n events: Array.isArray(r.events)\r\n ? (r.events as unknown[]).filter((e): e is WebhookEvent =>\r\n VALID_EVENTS.includes(e as WebhookEvent),\r\n )\r\n : [],\r\n hasSecret: r.hasSecret === true,\r\n status:\r\n r.status === 'active' || r.status === 'degraded' || r.status === 'disabled'\r\n ? r.status\r\n : 'active',\r\n lastDeliveryAt: typeof r.lastDeliveryAt === 'string' ? r.lastDeliveryAt : undefined,\r\n consecutiveFailures:\r\n typeof r.consecutiveFailures === 'number' ? r.consecutiveFailures : undefined,\r\n createdAt: typeof r.createdAt === 'string' ? r.createdAt : new Date().toISOString(),\r\n };\r\n}\r\n\r\nfunction validateInput(input: RegisterWebhookInput): void {\r\n if (!input.url || typeof input.url !== 'string') {\r\n throw new NeetruError('validation_failed', 'url é obrigatória');\r\n }\r\n try {\r\n const parsed = new URL(input.url);\r\n if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {\r\n throw new Error('invalid protocol');\r\n }\r\n // Em prod, http: é warning (não bloqueia) — testes locais podem usar\r\n } catch {\r\n throw new NeetruError('validation_failed', `url inválida: ${input.url}`);\r\n }\r\n if (!Array.isArray(input.events) || input.events.length === 0) {\r\n throw new NeetruError('validation_failed', 'events deve ter pelo menos 1 evento');\r\n }\r\n for (const ev of input.events) {\r\n if (!VALID_EVENTS.includes(ev)) {\r\n throw new NeetruError('validation_failed', `evento desconhecido: ${ev}`);\r\n }\r\n }\r\n if (input.secret !== undefined && input.secret.length < 16) {\r\n throw new NeetruError('validation_failed', 'secret deve ter ≥16 chars (recomendado 32+)');\r\n }\r\n}\r\n\r\n/** Resolve productId: option explícito > input.productId > config.productId.\r\n *\r\n * **M-03 fix (Opus review 2026-05-27):** valida client-side contra `SDK_ID_RE`\r\n * antes de mandar pro Core — evita 400 silencioso em produção. */\r\nfunction resolveProductId(\r\n config: ResolvedConfig,\r\n ...candidates: Array<string | undefined>\r\n): string {\r\n for (const c of candidates) {\r\n if (typeof c === 'string' && c.length > 0) {\r\n assertValidSdkId('productId', c);\r\n return c;\r\n }\r\n }\r\n if (config.productId) {\r\n assertValidSdkId('productId', config.productId);\r\n return config.productId;\r\n }\r\n throw new NeetruError(\r\n 'validation_failed',\r\n 'productId required (pass to options/input or set on createNeetruClient)',\r\n );\r\n}\r\n\r\nexport function createWebhooksNamespace(config: ResolvedConfig): WebhooksNamespace {\r\n return {\r\n async register(input) {\r\n validateInput(input);\r\n const productId = resolveProductId(config, input.productId);\r\n const raw = await httpRequest<unknown>(config, {\r\n method: 'POST',\r\n path: '/api/sdk/v1/webhooks',\r\n body: {\r\n productId,\r\n url: input.url,\r\n events: input.events,\r\n ...(input.secret ? { secret: input.secret } : {}),\r\n },\r\n requireAuth: true,\r\n });\r\n return toEndpoint(raw);\r\n },\r\n async list(options) {\r\n const productId = resolveProductId(config, options?.productId);\r\n const raw = await httpRequest<{ endpoints?: unknown[] }>(config, {\r\n method: 'GET',\r\n path: '/api/sdk/v1/webhooks',\r\n query: { productId },\r\n requireAuth: true,\r\n });\r\n const list = Array.isArray(raw?.endpoints) ? raw.endpoints : [];\r\n return list.map(toEndpoint);\r\n },\r\n async unregister(id, options) {\r\n if (!id) throw new NeetruError('validation_failed', 'id obrigatório');\r\n const productId = resolveProductId(config, options?.productId);\r\n await httpRequest<unknown>(config, {\r\n method: 'DELETE',\r\n path: `/api/sdk/v1/webhooks/${encodeURIComponent(id)}`,\r\n query: { productId },\r\n requireAuth: true,\r\n });\r\n return { ok: true };\r\n },\r\n async test(id, options) {\r\n if (!id) throw new NeetruError('validation_failed', 'id obrigatório');\r\n const productId = resolveProductId(config, options?.productId);\r\n const raw = await httpRequest<unknown>(config, {\r\n method: 'POST',\r\n path: `/api/sdk/v1/webhooks/${encodeURIComponent(id)}/test`,\r\n query: { productId },\r\n requireAuth: true,\r\n idempotencyKey: true,\r\n });\r\n if (!raw || typeof raw !== 'object') {\r\n return { ok: false, error: 'invalid response' };\r\n }\r\n const r = raw as Record<string, unknown>;\r\n return {\r\n ok: r.ok === true,\r\n statusCode: typeof r.statusCode === 'number' ? r.statusCode : undefined,\r\n durationMs: typeof r.durationMs === 'number' ? r.durationMs : undefined,\r\n error: typeof r.error === 'string' ? r.error : undefined,\r\n };\r\n },\r\n };\r\n}\r\n\r\n// ─── Mock impl (dev / tests) ────────────────────────────────────────────────\r\n\r\nexport class MockWebhooks implements WebhooksNamespace {\r\n private endpoints = new Map<string, WebhookEndpoint>();\r\n private nextId = 1;\r\n\r\n async register(input: RegisterWebhookInput): Promise<WebhookEndpoint> {\r\n validateInput(input);\r\n const id = `mock_wh_${this.nextId++}`;\r\n const endpoint: WebhookEndpoint = {\r\n id,\r\n url: input.url,\r\n events: input.events,\r\n hasSecret: !!input.secret,\r\n status: 'active',\r\n createdAt: new Date().toISOString(),\r\n };\r\n this.endpoints.set(id, endpoint);\r\n return endpoint;\r\n }\r\n\r\n async list(_options?: WebhookScopeOptions): Promise<WebhookEndpoint[]> {\r\n return [...this.endpoints.values()];\r\n }\r\n\r\n async unregister(id: string, _options?: WebhookScopeOptions): Promise<{ ok: true }> {\r\n if (!this.endpoints.has(id)) {\r\n throw new NeetruError('not_found', `Webhook ${id} não encontrado`);\r\n }\r\n this.endpoints.delete(id);\r\n return { ok: true };\r\n }\r\n\r\n async test(id: string, _options?: WebhookScopeOptions): Promise<WebhookTestResult> {\r\n if (!this.endpoints.has(id)) {\r\n throw new NeetruError('not_found', `Webhook ${id} não encontrado`);\r\n }\r\n return { ok: true, statusCode: 200, durationMs: 42 };\r\n }\r\n}\r\n"]}
|
package/dist/webhooks.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { z as MockWebhooks, a2 as RegisterWebhookInput, am as VerifyWebhookRequestOptions, an as VerifyWebhookRequestResult, ao as WebhookEndpoint, ap as WebhookEvent, aq as WebhookScopeOptions, ar as WebhookTestResult, as as WebhooksNamespace, ay as createWebhooksNamespace, aF as verifyWebhookRequest, aG as verifyWebhookSignature } from './types-DvMdYbfV.cjs';
|
|
2
2
|
import 'drizzle-orm/node-postgres';
|
|
3
3
|
import './errors.cjs';
|
package/dist/webhooks.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { z as MockWebhooks, a2 as RegisterWebhookInput, am as VerifyWebhookRequestOptions, an as VerifyWebhookRequestResult, ao as WebhookEndpoint, ap as WebhookEvent, aq as WebhookScopeOptions, ar as WebhookTestResult, as as WebhooksNamespace, ay as createWebhooksNamespace, aF as verifyWebhookRequest, aG as verifyWebhookSignature } from './types-CRIIjqzC.js';
|
|
2
2
|
import 'drizzle-orm/node-postgres';
|
|
3
3
|
import './errors.js';
|
package/dist/webhooks.mjs
CHANGED
|
@@ -217,7 +217,7 @@ function assertValidSdkId(field, value) {
|
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
// src/webhooks.ts
|
|
220
|
-
async function verifyWebhookSignature(payload, signature, secret) {
|
|
220
|
+
async function verifyWebhookSignature(payload, signature, secret, timestamp) {
|
|
221
221
|
if (!signature || !secret) return false;
|
|
222
222
|
const sigHex = signature.startsWith("sha256=") ? signature.slice(7) : signature;
|
|
223
223
|
if (!/^[0-9a-f]+$/i.test(sigHex)) return false;
|
|
@@ -230,7 +230,15 @@ async function verifyWebhookSignature(payload, signature, secret) {
|
|
|
230
230
|
}
|
|
231
231
|
const encoder = new TextEncoder();
|
|
232
232
|
const keyBytes = encoder.encode(secret);
|
|
233
|
-
const
|
|
233
|
+
const rawBytes = typeof payload === "string" ? encoder.encode(payload) : payload;
|
|
234
|
+
let payloadBytes = rawBytes;
|
|
235
|
+
if (timestamp !== void 0) {
|
|
236
|
+
const prefix = encoder.encode(`${timestamp}.`);
|
|
237
|
+
const merged = new Uint8Array(prefix.length + rawBytes.length);
|
|
238
|
+
merged.set(prefix, 0);
|
|
239
|
+
merged.set(rawBytes, prefix.length);
|
|
240
|
+
payloadBytes = merged;
|
|
241
|
+
}
|
|
234
242
|
const key = await subtle.importKey(
|
|
235
243
|
"raw",
|
|
236
244
|
keyBytes,
|
|
@@ -278,7 +286,7 @@ async function verifyWebhookRequest(payload, headers, secret, options = {}) {
|
|
|
278
286
|
return { ok: false, reason: "timestamp_expired" };
|
|
279
287
|
}
|
|
280
288
|
const sig = getHeader("x-neetru-signature");
|
|
281
|
-
const valid = await verifyWebhookSignature(payload, sig, secret);
|
|
289
|
+
const valid = await verifyWebhookSignature(payload, sig, secret, tsHeader);
|
|
282
290
|
if (!valid) {
|
|
283
291
|
return { ok: false, reason: "invalid_signature" };
|
|
284
292
|
}
|