@neetru/sdk 3.7.0 → 3.8.0

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.
Files changed (73) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +66 -1
  3. package/dist/ai.cjs +221 -177
  4. package/dist/ai.d.cts +1 -1
  5. package/dist/ai.d.ts +1 -1
  6. package/dist/ai.mjs +221 -177
  7. package/dist/auth.cjs +1227 -1064
  8. package/dist/auth.d.cts +1 -1
  9. package/dist/auth.d.ts +1 -1
  10. package/dist/auth.mjs +1224 -1061
  11. package/dist/catalog.cjs +164 -97
  12. package/dist/catalog.d.cts +1 -1
  13. package/dist/catalog.d.ts +1 -1
  14. package/dist/catalog.mjs +164 -97
  15. package/dist/checkout.cjs +182 -115
  16. package/dist/checkout.d.cts +1 -1
  17. package/dist/checkout.d.ts +1 -1
  18. package/dist/checkout.mjs +181 -114
  19. package/dist/db-react.d.cts +1 -1
  20. package/dist/db-react.d.ts +1 -1
  21. package/dist/db.cjs +370 -298
  22. package/dist/db.d.cts +1 -1
  23. package/dist/db.d.ts +1 -1
  24. package/dist/db.mjs +362 -290
  25. package/dist/entitlements.cjs +17 -10
  26. package/dist/entitlements.d.cts +1 -1
  27. package/dist/entitlements.d.ts +1 -1
  28. package/dist/entitlements.mjs +17 -10
  29. package/dist/errors.cjs +15 -8
  30. package/dist/errors.d.cts +24 -3
  31. package/dist/errors.d.ts +24 -3
  32. package/dist/errors.mjs +14 -7
  33. package/dist/firestore-compat.d.cts +1 -1
  34. package/dist/firestore-compat.d.ts +1 -1
  35. package/dist/index.cjs +1409 -1075
  36. package/dist/index.d.cts +177 -3
  37. package/dist/index.d.ts +177 -3
  38. package/dist/index.mjs +1544 -1217
  39. package/dist/mobile.cjs +400 -181
  40. package/dist/mobile.d.cts +59 -4
  41. package/dist/mobile.d.ts +59 -4
  42. package/dist/mobile.mjs +400 -181
  43. package/dist/mocks.cjs +9 -2
  44. package/dist/mocks.d.cts +1 -1
  45. package/dist/mocks.d.ts +1 -1
  46. package/dist/mocks.mjs +9 -2
  47. package/dist/notifications.cjs +197 -130
  48. package/dist/notifications.d.cts +1 -1
  49. package/dist/notifications.d.ts +1 -1
  50. package/dist/notifications.mjs +196 -129
  51. package/dist/react.cjs +303 -282
  52. package/dist/react.d.cts +1 -1
  53. package/dist/react.d.ts +1 -1
  54. package/dist/react.mjs +295 -274
  55. package/dist/support.cjs +299 -229
  56. package/dist/support.d.cts +8 -4
  57. package/dist/support.d.ts +8 -4
  58. package/dist/support.mjs +298 -228
  59. package/dist/telemetry.cjs +234 -167
  60. package/dist/telemetry.d.cts +1 -1
  61. package/dist/telemetry.d.ts +1 -1
  62. package/dist/telemetry.mjs +234 -167
  63. package/dist/{types-Bx4kTLmk.d.cts → types-D-9bjlM0.d.cts} +48 -1
  64. package/dist/{types-Dx0IrOSF.d.ts → types-bVztFQTI.d.ts} +48 -1
  65. package/dist/usage.cjs +183 -116
  66. package/dist/usage.d.cts +1 -1
  67. package/dist/usage.d.ts +1 -1
  68. package/dist/usage.mjs +183 -116
  69. package/dist/webhooks.cjs +215 -148
  70. package/dist/webhooks.d.cts +1 -1
  71. package/dist/webhooks.d.ts +1 -1
  72. package/dist/webhooks.mjs +212 -145
  73. package/package.json +2 -1
package/dist/index.d.cts CHANGED
@@ -1,7 +1,8 @@
1
1
  export { createNeetruClient, getServerNeetruClient } from './auth.cjs';
2
2
  export { NeetruAuthRequiredError, NeetruError, NeetruErrorCode } from './errors.cjs';
3
- export { A as AiChatChoice, a as AiChatMessage, b as AiChatOptions, c as AiChatResult, d as AiChatUsage, e as AiContentPart, f as AiImageUrlPart, g as AiNamespace, h as AiResponseFormat, i as AiStreamHandle, j as AiStreamMeta, k as AiTextPart, l as AuthNamespace, m as AuthStateListener, C as CatalogListOptions, n as CatalogListResponse, p as CheckoutIntentInfo, q as CheckoutIntentStatus, r as CheckoutNamespace, s as CheckoutStartInput, t as CheckoutStartResult, u as CheckoutTenantType, v as CompleteSignInResult, y as CreateTicketInput, D as DEFAULT_BASE_URL, z as DbBatchOp, B as DbChangeType, E as DbCollectionRef, F as DbDoc, G as DbDocRef, H as DbGetResult, I as DbListResult, J as DbNamespace, K as DbQuery, L as DbSqlLease, M as DbWhereFilter, O as EntitlementCheck, P as FieldSentinel, Q as IncrementSentinel, R as ListNotificationsOptions, S as MockCheckout, T as MockNotifications, U as MockWebhooks, V as NEETRU_SENTINEL_KEY, W as NeetruClient, X as NeetruClientConfig, Y as NeetruDb, _ as NeetruDbEngine, $ as NeetruDbError, a0 as NeetruDbErrorCode, a1 as NeetruDbOptions, a2 as NeetruDbTransport, a3 as NeetruEnv, a4 as NeetruSqlClient, a5 as NeetruUser, a6 as NotificationScopeOptions, a7 as NotificationsNamespace, a8 as Product, a9 as ProductNotification, aa as ProductNotificationSeverity, ab as ProductPlan, ac as ProductStatus, ae as RedirectCallbackResult, af as RegisterWebhookInput, ag as ResolvedConfig, ah as SendNotificationInput, ai as ServerTimestampSentinel, aj as SignInOptions, al as SupportNamespace, am as SupportSeverity, an as SupportStatus, ao as SupportTicket, ar as TelemetryEventAck, as as TelemetryEventInput, aw as UsageEventInput, ax as UsageNamespace, ay as UsageQuota, az as VerifyTokenOptions, aA as VerifyWebhookRequestOptions, aB as VerifyWebhookRequestResult, aC as WebhookEndpoint, aD as WebhookEvent, aE as WebhookScopeOptions, aF as WebhookTestResult, aG as WebhooksNamespace, aH as WithFieldSentinels, aJ as createAiNamespace, aK as createCheckoutNamespace, aL as createNeetruDb, aM as createNotificationsNamespace, aO as createWebhooksNamespace, aQ as increment, aR as isFieldSentinel, aS as isIncrementSentinel, aT as isServerTimestampSentinel, aU as serverTimestamp, aV as verifyWebhookRequest, aW as verifyWebhookSignature } from './types-Bx4kTLmk.cjs';
3
+ export { A as AiChatChoice, a as AiChatMessage, b as AiChatOptions, c as AiChatResult, d as AiChatUsage, e as AiContentPart, f as AiImageUrlPart, g as AiNamespace, h as AiResponseFormat, i as AiStreamHandle, j as AiStreamMeta, k as AiTextPart, l as AuthNamespace, m as AuthStateListener, C as CatalogListOptions, n as CatalogListResponse, p as CheckoutIntentInfo, q as CheckoutIntentStatus, r as CheckoutNamespace, s as CheckoutStartInput, t as CheckoutStartResult, u as CheckoutTenantType, v as CompleteSignInResult, y as CreateTicketInput, D as DEFAULT_BASE_URL, z as DbBatchOp, B as DbChangeType, E as DbCollectionRef, F as DbDoc, G as DbDocRef, H as DbGetResult, I as DbListResult, J as DbNamespace, K as DbQuery, L as DbSqlLease, M as DbWhereFilter, O as EndUserTokenProvider, P as EntitlementCheck, Q as FieldSentinel, R as IncrementSentinel, S as ListNotificationsOptions, T as MockCheckout, U as MockNotifications, V as MockWebhooks, W as NEETRU_SENTINEL_KEY, X as NeetruClient, Y as NeetruClientConfig, Z as NeetruDb, $ as NeetruDbEngine, a0 as NeetruDbError, a1 as NeetruDbErrorCode, a2 as NeetruDbOptions, a3 as NeetruDbTransport, a4 as NeetruEnv, a5 as NeetruSqlClient, a6 as NeetruUser, a7 as NotificationScopeOptions, a8 as NotificationsNamespace, a9 as Product, aa as ProductNotification, ab as ProductNotificationSeverity, ac as ProductPlan, ad as ProductStatus, af as RedirectCallbackResult, ag as RegisterWebhookInput, ah as ResolvedConfig, ai as SendNotificationInput, aj as ServerTimestampSentinel, ak as SignInOptions, am as SupportNamespace, an as SupportSeverity, ao as SupportStatus, ap as SupportTicket, as as TelemetryEventAck, at as TelemetryEventInput, ax as UsageEventInput, ay as UsageNamespace, az as UsageQuota, aA as VerifyTokenOptions, aB as VerifyWebhookRequestOptions, aC as VerifyWebhookRequestResult, aD as WebhookEndpoint, aE as WebhookEvent, aF as WebhookScopeOptions, aG as WebhookTestResult, aH as WebhooksNamespace, aI as WithFieldSentinels, aK as createAiNamespace, aL as createCheckoutNamespace, aM as createNeetruDb, aN as createNotificationsNamespace, aP as createWebhooksNamespace, aR as increment, aS as isFieldSentinel, aT as isIncrementSentinel, aU as isServerTimestampSentinel, aV as serverTimestamp, aW as verifyWebhookRequest, aX as verifyWebhookSignature } from './types-D-9bjlM0.cjs';
4
4
  export { DEV_FIXTURE_USER, MockAi, MockAuth, MockAuthOptions, MockDb, MockEntitlements, MockSupport, MockUsage } from './mocks.cjs';
5
+ import { JWTPayload } from 'jose';
5
6
  import 'drizzle-orm/node-postgres';
6
7
 
7
8
  /**
@@ -38,6 +39,179 @@ import 'drizzle-orm/node-postgres';
38
39
  */
39
40
  declare function checkCoreVersionCompat(coreVersion: string): void;
40
41
 
42
+ /**
43
+ * 3.8.0 — `verifyAccessToken`: validação SERVER-SIDE do access_token OIDC do
44
+ * usuário final, para a API do PRODUTO aceitar `Authorization: Bearer
45
+ * <access_token>` (app React Native / SPA) além do cookie de sessão.
46
+ *
47
+ * ## Fluxo canônico (decisão do dono, 2026-10-03)
48
+ *
49
+ * app/site ──Bearer access_token──▶ API do produto ──SDK + nrt_ (servidor)──▶ Core
50
+ *
51
+ * O app nunca carrega a chave `nrt_`. Ele faz login no auth.neetru.com (PKCE,
52
+ * client OIDC público do app) e manda o access_token pra API do produto, que
53
+ * valida aqui — sem ir ao Core por request.
54
+ *
55
+ * ## Formato real do token (conferido no Core, `src/lib/oidc/tokens.ts`)
56
+ *
57
+ * header: `{ alg: 'RS256', kid, typ: 'JWT' }`
58
+ * claims: `iss` = `https://auth.neetru.com` · `sub` = uid do usuário (ou
59
+ * `client:<client_id>` em client_credentials) · `aud` = `client_id`
60
+ * (string) · `client_id` · `scope` (string separada por espaço) ·
61
+ * `iat` · `exp` (15 min) · `jti`.
62
+ * JWKS: `https://auth.neetru.com/api/v1/oauth/.well-known/jwks`.
63
+ *
64
+ * O id_token usa a MESMA chave, `iss` e `aud` — o que o distingue é NÃO ter
65
+ * `jti`/`scope`/`client_id`. Por isso exigimos os três: um id_token (que vai
66
+ * para terceiros como prova de login) não serve de credencial de API.
67
+ *
68
+ * ## Revogação
69
+ *
70
+ * A validação é local (assinatura + claims), sem consulta ao Core. Um access
71
+ * token revogado continua aceito até expirar — no máximo 15 min (TTL do Core).
72
+ * Para encerrar a sessão de verdade, o app revoga o refresh_token no logout
73
+ * (o `@neetru/sdk/mobile` faz isso no `signOut`). O `/introspect` do Core é só
74
+ * para clients confidenciais do mesmo `client_id`, então não serve a uma API
75
+ * que aceita tokens de vários clients (web + iOS + Android).
76
+ */
77
+
78
+ /** Issuer canônico do Core em produção. */
79
+ declare const NEETRU_OIDC_ISSUER = "https://auth.neetru.com";
80
+ interface VerifyAccessTokenOptions {
81
+ /**
82
+ * `client_id` OIDC aceitos como `aud` — tipicamente o client web + o do app
83
+ * iOS + o do app Android DO MESMO PRODUTO. Obrigatório e não-vazio: sem isso
84
+ * um token emitido para o client de OUTRO produto passaria.
85
+ */
86
+ audience: string | readonly string[];
87
+ /** Escopos que o token TEM que ter (todos). Ex.: `['openid']`. Default: nenhum. */
88
+ requiredScopes?: readonly string[];
89
+ /** Issuer esperado. Default `https://auth.neetru.com`. Só mude para staging/emulador. */
90
+ issuer?: string;
91
+ /** URL do JWKS. Default `<issuer>/api/v1/oauth/.well-known/jwks`. */
92
+ jwksUrl?: string;
93
+ /** TTL da instância de JWKS cacheada. Default 1h. */
94
+ jwksCacheTtlMs?: number;
95
+ /** Tolerância de relógio para `exp`/`iat`/`nbf`, em segundos. Default 5, máx 60. */
96
+ clockToleranceSec?: number;
97
+ /**
98
+ * Aceitar token de máquina (`client_credentials`, `sub` = `client:<id>`).
99
+ * Default `false` — a API do produto quer um USUÁRIO.
100
+ */
101
+ allowClientCredentials?: boolean;
102
+ }
103
+ interface VerifiedAccessToken {
104
+ /** uid do usuário final (ou `client:<id>` se `allowClientCredentials`). */
105
+ sub: string;
106
+ /** `client_id` que pediu o token (web, iOS ou Android). */
107
+ clientId: string;
108
+ /** `aud` do token (= `clientId` no Core). */
109
+ audience: string;
110
+ /** Escopos concedidos. */
111
+ scopes: string[];
112
+ /** Id único do token (útil pra log/auditoria; NÃO é segredo). */
113
+ jti: string;
114
+ /** Emitido em (epoch s). */
115
+ issuedAt: number;
116
+ /** Expira em (epoch s). */
117
+ expiresAt: number;
118
+ /** `true` se é token de máquina (`client_credentials`). */
119
+ isClientCredentials: boolean;
120
+ /** Claims crus verificados. */
121
+ claims: JWTPayload;
122
+ }
123
+ /**
124
+ * Valida um access_token OIDC emitido pelo auth.neetru.com.
125
+ *
126
+ * Checa: assinatura RS256 contra o JWKS (cacheado) · `iss` · `exp` (com
127
+ * tolerância curta) · `aud ∈ audience` · formato de access token (`jti`,
128
+ * `scope`, `client_id` === `aud`) · usuário (não máquina) · `requiredScopes`.
129
+ *
130
+ * @throws {NeetruError} `invalid_config` (sem audience) · `token_expired` ·
131
+ * `token_invalid_signature` · `token_invalid_audience` · `token_invalid_issuer` ·
132
+ * `token_invalid` (não é access token / malformado / máquina) ·
133
+ * `insufficient_scope` (status 403).
134
+ */
135
+ declare function verifyAccessToken(token: string, options: VerifyAccessTokenOptions): Promise<VerifiedAccessToken>;
136
+ /** Qualquer coisa com headers: `Request` (fetch/Next), `Headers`, ou objeto Node (`req.headers`). */
137
+ type HeadersSource = Headers | {
138
+ headers: Headers | Record<string, string | string[] | undefined>;
139
+ } | Record<string, string | string[] | undefined>;
140
+ /**
141
+ * Extrai o token de `Authorization: Bearer <token>`. `null` se ausente ou se o
142
+ * esquema não for Bearer.
143
+ */
144
+ declare function readBearerToken(source: HeadersSource): string | null;
145
+ /** Lê um cookie pelo nome do header `Cookie`. */
146
+ declare function readCookie(source: HeadersSource, name: string): string | null;
147
+ interface AuthenticateProductRequestOptions<TSession> extends VerifyAccessTokenOptions {
148
+ /**
149
+ * Sessão por cookie do site (o caminho que o produto JÁ tem). Se a request
150
+ * não trouxer `Authorization: Bearer`, o helper lê o cookie `name` e chama
151
+ * `verify(valor)` — a validação do cookie continua sendo do produto.
152
+ */
153
+ cookie?: {
154
+ name: string;
155
+ verify: (value: string) => Promise<TSession | null> | TSession | null;
156
+ };
157
+ }
158
+ type ProductRequestAuth<TSession> = {
159
+ kind: 'access_token';
160
+ token: VerifiedAccessToken;
161
+ } | {
162
+ kind: 'cookie';
163
+ session: TSession;
164
+ };
165
+ /**
166
+ * Autentica uma request na API do produto aceitando `Authorization: Bearer
167
+ * <access_token>` (app/SPA) **ou** o cookie de sessão do site.
168
+ *
169
+ * - Bearer presente → valida com `verifyAccessToken`. Inválido → LANÇA (não cai
170
+ * pro cookie: credencial ruim explícita nunca é "rebaixada" em silêncio).
171
+ * - Sem Bearer e com `cookie` configurado → `cookie.verify(valor)`.
172
+ * - Nada válido → `null` (o produto responde 401).
173
+ *
174
+ * @example
175
+ * ```ts
176
+ * // app/api/v1/vendas/route.ts (Next.js, servidor)
177
+ * import { authenticateProductRequest, accessTokenErrorToHttp } from '@neetru/sdk';
178
+ * export async function GET(req: Request) {
179
+ * try {
180
+ * const auth = await authenticateProductRequest(req, {
181
+ * audience: [process.env.NEETRU_OIDC_CLIENT_ID_WEB!, process.env.NEETRU_OIDC_CLIENT_ID_IOS!,
182
+ * process.env.NEETRU_OIDC_CLIENT_ID_ANDROID!],
183
+ * requiredScopes: ['openid'],
184
+ * cookie: { name: 'session', verify: verifySessionCookie },
185
+ * });
186
+ * if (!auth) return Response.json({ error: 'unauthorized' }, { status: 401 });
187
+ * // ... usa o SDK com a chave (servidor) em nome de auth.token.sub
188
+ * } catch (err) {
189
+ * const r = accessTokenErrorToHttp(err);
190
+ * return Response.json(r.body, { status: r.status, headers: r.headers });
191
+ * }
192
+ * }
193
+ * ```
194
+ */
195
+ declare function authenticateProductRequest<TSession = unknown>(request: HeadersSource, options: AuthenticateProductRequestOptions<TSession>): Promise<ProductRequestAuth<TSession> | null>;
196
+ /**
197
+ * Converte um erro de `verifyAccessToken`/`authenticateProductRequest` na
198
+ * resposta HTTP padrão (RFC 6750 §3): 401 `invalid_token` ou 403
199
+ * `insufficient_scope`, com `WWW-Authenticate`. Erros que não são de token
200
+ * viram 500 genérico (sem vazar detalhe).
201
+ */
202
+ declare function accessTokenErrorToHttp(err: unknown): {
203
+ status: number;
204
+ headers: Record<string, string>;
205
+ body: {
206
+ error: string;
207
+ error_description: string;
208
+ };
209
+ };
210
+
211
+ type NonServerRuntime = 'browser' | 'react-native';
212
+ /** Detecta se o código está rodando fora de um servidor. `null` = servidor. */
213
+ declare function detectNonServerRuntime(): NonServerRuntime | null;
214
+
41
215
  /**
42
216
  * @neetru/sdk — biblioteca runtime para consumir o ecossistema Neetru.
43
217
  *
@@ -72,6 +246,6 @@ declare function checkCoreVersionCompat(coreVersion: string): void;
72
246
  */
73
247
 
74
248
  /** Versão do SDK — exportada explicitamente pra detecção em runtime. */
75
- declare const VERSION: "3.7.0";
249
+ declare const VERSION: "3.8.0";
76
250
 
77
- export { VERSION, checkCoreVersionCompat };
251
+ export { type AuthenticateProductRequestOptions, type HeadersSource, NEETRU_OIDC_ISSUER, type NonServerRuntime, type ProductRequestAuth, VERSION, type VerifiedAccessToken, type VerifyAccessTokenOptions, accessTokenErrorToHttp, authenticateProductRequest, checkCoreVersionCompat, detectNonServerRuntime, readBearerToken, readCookie, verifyAccessToken };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  export { createNeetruClient, getServerNeetruClient } from './auth.js';
2
2
  export { NeetruAuthRequiredError, NeetruError, NeetruErrorCode } from './errors.js';
3
- export { A as AiChatChoice, a as AiChatMessage, b as AiChatOptions, c as AiChatResult, d as AiChatUsage, e as AiContentPart, f as AiImageUrlPart, g as AiNamespace, h as AiResponseFormat, i as AiStreamHandle, j as AiStreamMeta, k as AiTextPart, l as AuthNamespace, m as AuthStateListener, C as CatalogListOptions, n as CatalogListResponse, p as CheckoutIntentInfo, q as CheckoutIntentStatus, r as CheckoutNamespace, s as CheckoutStartInput, t as CheckoutStartResult, u as CheckoutTenantType, v as CompleteSignInResult, y as CreateTicketInput, D as DEFAULT_BASE_URL, z as DbBatchOp, B as DbChangeType, E as DbCollectionRef, F as DbDoc, G as DbDocRef, H as DbGetResult, I as DbListResult, J as DbNamespace, K as DbQuery, L as DbSqlLease, M as DbWhereFilter, O as EntitlementCheck, P as FieldSentinel, Q as IncrementSentinel, R as ListNotificationsOptions, S as MockCheckout, T as MockNotifications, U as MockWebhooks, V as NEETRU_SENTINEL_KEY, W as NeetruClient, X as NeetruClientConfig, Y as NeetruDb, _ as NeetruDbEngine, $ as NeetruDbError, a0 as NeetruDbErrorCode, a1 as NeetruDbOptions, a2 as NeetruDbTransport, a3 as NeetruEnv, a4 as NeetruSqlClient, a5 as NeetruUser, a6 as NotificationScopeOptions, a7 as NotificationsNamespace, a8 as Product, a9 as ProductNotification, aa as ProductNotificationSeverity, ab as ProductPlan, ac as ProductStatus, ae as RedirectCallbackResult, af as RegisterWebhookInput, ag as ResolvedConfig, ah as SendNotificationInput, ai as ServerTimestampSentinel, aj as SignInOptions, al as SupportNamespace, am as SupportSeverity, an as SupportStatus, ao as SupportTicket, ar as TelemetryEventAck, as as TelemetryEventInput, aw as UsageEventInput, ax as UsageNamespace, ay as UsageQuota, az as VerifyTokenOptions, aA as VerifyWebhookRequestOptions, aB as VerifyWebhookRequestResult, aC as WebhookEndpoint, aD as WebhookEvent, aE as WebhookScopeOptions, aF as WebhookTestResult, aG as WebhooksNamespace, aH as WithFieldSentinels, aJ as createAiNamespace, aK as createCheckoutNamespace, aL as createNeetruDb, aM as createNotificationsNamespace, aO as createWebhooksNamespace, aQ as increment, aR as isFieldSentinel, aS as isIncrementSentinel, aT as isServerTimestampSentinel, aU as serverTimestamp, aV as verifyWebhookRequest, aW as verifyWebhookSignature } from './types-Dx0IrOSF.js';
3
+ export { A as AiChatChoice, a as AiChatMessage, b as AiChatOptions, c as AiChatResult, d as AiChatUsage, e as AiContentPart, f as AiImageUrlPart, g as AiNamespace, h as AiResponseFormat, i as AiStreamHandle, j as AiStreamMeta, k as AiTextPart, l as AuthNamespace, m as AuthStateListener, C as CatalogListOptions, n as CatalogListResponse, p as CheckoutIntentInfo, q as CheckoutIntentStatus, r as CheckoutNamespace, s as CheckoutStartInput, t as CheckoutStartResult, u as CheckoutTenantType, v as CompleteSignInResult, y as CreateTicketInput, D as DEFAULT_BASE_URL, z as DbBatchOp, B as DbChangeType, E as DbCollectionRef, F as DbDoc, G as DbDocRef, H as DbGetResult, I as DbListResult, J as DbNamespace, K as DbQuery, L as DbSqlLease, M as DbWhereFilter, O as EndUserTokenProvider, P as EntitlementCheck, Q as FieldSentinel, R as IncrementSentinel, S as ListNotificationsOptions, T as MockCheckout, U as MockNotifications, V as MockWebhooks, W as NEETRU_SENTINEL_KEY, X as NeetruClient, Y as NeetruClientConfig, Z as NeetruDb, $ as NeetruDbEngine, a0 as NeetruDbError, a1 as NeetruDbErrorCode, a2 as NeetruDbOptions, a3 as NeetruDbTransport, a4 as NeetruEnv, a5 as NeetruSqlClient, a6 as NeetruUser, a7 as NotificationScopeOptions, a8 as NotificationsNamespace, a9 as Product, aa as ProductNotification, ab as ProductNotificationSeverity, ac as ProductPlan, ad as ProductStatus, af as RedirectCallbackResult, ag as RegisterWebhookInput, ah as ResolvedConfig, ai as SendNotificationInput, aj as ServerTimestampSentinel, ak as SignInOptions, am as SupportNamespace, an as SupportSeverity, ao as SupportStatus, ap as SupportTicket, as as TelemetryEventAck, at as TelemetryEventInput, ax as UsageEventInput, ay as UsageNamespace, az as UsageQuota, aA as VerifyTokenOptions, aB as VerifyWebhookRequestOptions, aC as VerifyWebhookRequestResult, aD as WebhookEndpoint, aE as WebhookEvent, aF as WebhookScopeOptions, aG as WebhookTestResult, aH as WebhooksNamespace, aI as WithFieldSentinels, aK as createAiNamespace, aL as createCheckoutNamespace, aM as createNeetruDb, aN as createNotificationsNamespace, aP as createWebhooksNamespace, aR as increment, aS as isFieldSentinel, aT as isIncrementSentinel, aU as isServerTimestampSentinel, aV as serverTimestamp, aW as verifyWebhookRequest, aX as verifyWebhookSignature } from './types-bVztFQTI.js';
4
4
  export { DEV_FIXTURE_USER, MockAi, MockAuth, MockAuthOptions, MockDb, MockEntitlements, MockSupport, MockUsage } from './mocks.js';
5
+ import { JWTPayload } from 'jose';
5
6
  import 'drizzle-orm/node-postgres';
6
7
 
7
8
  /**
@@ -38,6 +39,179 @@ import 'drizzle-orm/node-postgres';
38
39
  */
39
40
  declare function checkCoreVersionCompat(coreVersion: string): void;
40
41
 
42
+ /**
43
+ * 3.8.0 — `verifyAccessToken`: validação SERVER-SIDE do access_token OIDC do
44
+ * usuário final, para a API do PRODUTO aceitar `Authorization: Bearer
45
+ * <access_token>` (app React Native / SPA) além do cookie de sessão.
46
+ *
47
+ * ## Fluxo canônico (decisão do dono, 2026-10-03)
48
+ *
49
+ * app/site ──Bearer access_token──▶ API do produto ──SDK + nrt_ (servidor)──▶ Core
50
+ *
51
+ * O app nunca carrega a chave `nrt_`. Ele faz login no auth.neetru.com (PKCE,
52
+ * client OIDC público do app) e manda o access_token pra API do produto, que
53
+ * valida aqui — sem ir ao Core por request.
54
+ *
55
+ * ## Formato real do token (conferido no Core, `src/lib/oidc/tokens.ts`)
56
+ *
57
+ * header: `{ alg: 'RS256', kid, typ: 'JWT' }`
58
+ * claims: `iss` = `https://auth.neetru.com` · `sub` = uid do usuário (ou
59
+ * `client:<client_id>` em client_credentials) · `aud` = `client_id`
60
+ * (string) · `client_id` · `scope` (string separada por espaço) ·
61
+ * `iat` · `exp` (15 min) · `jti`.
62
+ * JWKS: `https://auth.neetru.com/api/v1/oauth/.well-known/jwks`.
63
+ *
64
+ * O id_token usa a MESMA chave, `iss` e `aud` — o que o distingue é NÃO ter
65
+ * `jti`/`scope`/`client_id`. Por isso exigimos os três: um id_token (que vai
66
+ * para terceiros como prova de login) não serve de credencial de API.
67
+ *
68
+ * ## Revogação
69
+ *
70
+ * A validação é local (assinatura + claims), sem consulta ao Core. Um access
71
+ * token revogado continua aceito até expirar — no máximo 15 min (TTL do Core).
72
+ * Para encerrar a sessão de verdade, o app revoga o refresh_token no logout
73
+ * (o `@neetru/sdk/mobile` faz isso no `signOut`). O `/introspect` do Core é só
74
+ * para clients confidenciais do mesmo `client_id`, então não serve a uma API
75
+ * que aceita tokens de vários clients (web + iOS + Android).
76
+ */
77
+
78
+ /** Issuer canônico do Core em produção. */
79
+ declare const NEETRU_OIDC_ISSUER = "https://auth.neetru.com";
80
+ interface VerifyAccessTokenOptions {
81
+ /**
82
+ * `client_id` OIDC aceitos como `aud` — tipicamente o client web + o do app
83
+ * iOS + o do app Android DO MESMO PRODUTO. Obrigatório e não-vazio: sem isso
84
+ * um token emitido para o client de OUTRO produto passaria.
85
+ */
86
+ audience: string | readonly string[];
87
+ /** Escopos que o token TEM que ter (todos). Ex.: `['openid']`. Default: nenhum. */
88
+ requiredScopes?: readonly string[];
89
+ /** Issuer esperado. Default `https://auth.neetru.com`. Só mude para staging/emulador. */
90
+ issuer?: string;
91
+ /** URL do JWKS. Default `<issuer>/api/v1/oauth/.well-known/jwks`. */
92
+ jwksUrl?: string;
93
+ /** TTL da instância de JWKS cacheada. Default 1h. */
94
+ jwksCacheTtlMs?: number;
95
+ /** Tolerância de relógio para `exp`/`iat`/`nbf`, em segundos. Default 5, máx 60. */
96
+ clockToleranceSec?: number;
97
+ /**
98
+ * Aceitar token de máquina (`client_credentials`, `sub` = `client:<id>`).
99
+ * Default `false` — a API do produto quer um USUÁRIO.
100
+ */
101
+ allowClientCredentials?: boolean;
102
+ }
103
+ interface VerifiedAccessToken {
104
+ /** uid do usuário final (ou `client:<id>` se `allowClientCredentials`). */
105
+ sub: string;
106
+ /** `client_id` que pediu o token (web, iOS ou Android). */
107
+ clientId: string;
108
+ /** `aud` do token (= `clientId` no Core). */
109
+ audience: string;
110
+ /** Escopos concedidos. */
111
+ scopes: string[];
112
+ /** Id único do token (útil pra log/auditoria; NÃO é segredo). */
113
+ jti: string;
114
+ /** Emitido em (epoch s). */
115
+ issuedAt: number;
116
+ /** Expira em (epoch s). */
117
+ expiresAt: number;
118
+ /** `true` se é token de máquina (`client_credentials`). */
119
+ isClientCredentials: boolean;
120
+ /** Claims crus verificados. */
121
+ claims: JWTPayload;
122
+ }
123
+ /**
124
+ * Valida um access_token OIDC emitido pelo auth.neetru.com.
125
+ *
126
+ * Checa: assinatura RS256 contra o JWKS (cacheado) · `iss` · `exp` (com
127
+ * tolerância curta) · `aud ∈ audience` · formato de access token (`jti`,
128
+ * `scope`, `client_id` === `aud`) · usuário (não máquina) · `requiredScopes`.
129
+ *
130
+ * @throws {NeetruError} `invalid_config` (sem audience) · `token_expired` ·
131
+ * `token_invalid_signature` · `token_invalid_audience` · `token_invalid_issuer` ·
132
+ * `token_invalid` (não é access token / malformado / máquina) ·
133
+ * `insufficient_scope` (status 403).
134
+ */
135
+ declare function verifyAccessToken(token: string, options: VerifyAccessTokenOptions): Promise<VerifiedAccessToken>;
136
+ /** Qualquer coisa com headers: `Request` (fetch/Next), `Headers`, ou objeto Node (`req.headers`). */
137
+ type HeadersSource = Headers | {
138
+ headers: Headers | Record<string, string | string[] | undefined>;
139
+ } | Record<string, string | string[] | undefined>;
140
+ /**
141
+ * Extrai o token de `Authorization: Bearer <token>`. `null` se ausente ou se o
142
+ * esquema não for Bearer.
143
+ */
144
+ declare function readBearerToken(source: HeadersSource): string | null;
145
+ /** Lê um cookie pelo nome do header `Cookie`. */
146
+ declare function readCookie(source: HeadersSource, name: string): string | null;
147
+ interface AuthenticateProductRequestOptions<TSession> extends VerifyAccessTokenOptions {
148
+ /**
149
+ * Sessão por cookie do site (o caminho que o produto JÁ tem). Se a request
150
+ * não trouxer `Authorization: Bearer`, o helper lê o cookie `name` e chama
151
+ * `verify(valor)` — a validação do cookie continua sendo do produto.
152
+ */
153
+ cookie?: {
154
+ name: string;
155
+ verify: (value: string) => Promise<TSession | null> | TSession | null;
156
+ };
157
+ }
158
+ type ProductRequestAuth<TSession> = {
159
+ kind: 'access_token';
160
+ token: VerifiedAccessToken;
161
+ } | {
162
+ kind: 'cookie';
163
+ session: TSession;
164
+ };
165
+ /**
166
+ * Autentica uma request na API do produto aceitando `Authorization: Bearer
167
+ * <access_token>` (app/SPA) **ou** o cookie de sessão do site.
168
+ *
169
+ * - Bearer presente → valida com `verifyAccessToken`. Inválido → LANÇA (não cai
170
+ * pro cookie: credencial ruim explícita nunca é "rebaixada" em silêncio).
171
+ * - Sem Bearer e com `cookie` configurado → `cookie.verify(valor)`.
172
+ * - Nada válido → `null` (o produto responde 401).
173
+ *
174
+ * @example
175
+ * ```ts
176
+ * // app/api/v1/vendas/route.ts (Next.js, servidor)
177
+ * import { authenticateProductRequest, accessTokenErrorToHttp } from '@neetru/sdk';
178
+ * export async function GET(req: Request) {
179
+ * try {
180
+ * const auth = await authenticateProductRequest(req, {
181
+ * audience: [process.env.NEETRU_OIDC_CLIENT_ID_WEB!, process.env.NEETRU_OIDC_CLIENT_ID_IOS!,
182
+ * process.env.NEETRU_OIDC_CLIENT_ID_ANDROID!],
183
+ * requiredScopes: ['openid'],
184
+ * cookie: { name: 'session', verify: verifySessionCookie },
185
+ * });
186
+ * if (!auth) return Response.json({ error: 'unauthorized' }, { status: 401 });
187
+ * // ... usa o SDK com a chave (servidor) em nome de auth.token.sub
188
+ * } catch (err) {
189
+ * const r = accessTokenErrorToHttp(err);
190
+ * return Response.json(r.body, { status: r.status, headers: r.headers });
191
+ * }
192
+ * }
193
+ * ```
194
+ */
195
+ declare function authenticateProductRequest<TSession = unknown>(request: HeadersSource, options: AuthenticateProductRequestOptions<TSession>): Promise<ProductRequestAuth<TSession> | null>;
196
+ /**
197
+ * Converte um erro de `verifyAccessToken`/`authenticateProductRequest` na
198
+ * resposta HTTP padrão (RFC 6750 §3): 401 `invalid_token` ou 403
199
+ * `insufficient_scope`, com `WWW-Authenticate`. Erros que não são de token
200
+ * viram 500 genérico (sem vazar detalhe).
201
+ */
202
+ declare function accessTokenErrorToHttp(err: unknown): {
203
+ status: number;
204
+ headers: Record<string, string>;
205
+ body: {
206
+ error: string;
207
+ error_description: string;
208
+ };
209
+ };
210
+
211
+ type NonServerRuntime = 'browser' | 'react-native';
212
+ /** Detecta se o código está rodando fora de um servidor. `null` = servidor. */
213
+ declare function detectNonServerRuntime(): NonServerRuntime | null;
214
+
41
215
  /**
42
216
  * @neetru/sdk — biblioteca runtime para consumir o ecossistema Neetru.
43
217
  *
@@ -72,6 +246,6 @@ declare function checkCoreVersionCompat(coreVersion: string): void;
72
246
  */
73
247
 
74
248
  /** Versão do SDK — exportada explicitamente pra detecção em runtime. */
75
- declare const VERSION: "3.7.0";
249
+ declare const VERSION: "3.8.0";
76
250
 
77
- export { VERSION, checkCoreVersionCompat };
251
+ export { type AuthenticateProductRequestOptions, type HeadersSource, NEETRU_OIDC_ISSUER, type NonServerRuntime, type ProductRequestAuth, VERSION, type VerifiedAccessToken, type VerifyAccessTokenOptions, accessTokenErrorToHttp, authenticateProductRequest, checkCoreVersionCompat, detectNonServerRuntime, readBearerToken, readCookie, verifyAccessToken };