@neetru/sdk 3.8.1 → 3.9.1

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 (71) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +14 -1
  3. package/dist/ai.cjs +1 -1
  4. package/dist/ai.d.cts +1 -1
  5. package/dist/ai.d.ts +1 -1
  6. package/dist/ai.mjs +1 -1
  7. package/dist/auth.cjs +844 -803
  8. package/dist/auth.d.cts +1 -1
  9. package/dist/auth.d.ts +1 -1
  10. package/dist/auth.mjs +841 -800
  11. package/dist/build-guard.cjs +186 -82
  12. package/dist/build-guard.d.cts +53 -1
  13. package/dist/build-guard.d.ts +53 -1
  14. package/dist/build-guard.mjs +175 -74
  15. package/dist/catalog.cjs +1 -1
  16. package/dist/catalog.d.cts +1 -1
  17. package/dist/catalog.d.ts +1 -1
  18. package/dist/catalog.mjs +1 -1
  19. package/dist/checkout.cjs +62 -49
  20. package/dist/checkout.d.cts +1 -1
  21. package/dist/checkout.d.ts +1 -1
  22. package/dist/checkout.mjs +62 -49
  23. package/dist/db-react.d.cts +1 -1
  24. package/dist/db-react.d.ts +1 -1
  25. package/dist/db.cjs +200 -187
  26. package/dist/db.d.cts +1 -1
  27. package/dist/db.d.ts +1 -1
  28. package/dist/db.mjs +193 -180
  29. package/dist/entitlements.d.cts +1 -1
  30. package/dist/entitlements.d.ts +1 -1
  31. package/dist/firestore-compat.d.cts +1 -1
  32. package/dist/firestore-compat.d.ts +1 -1
  33. package/dist/index.cjs +880 -839
  34. package/dist/index.d.cts +2 -2
  35. package/dist/index.d.ts +2 -2
  36. package/dist/index.mjs +847 -806
  37. package/dist/mobile.cjs +328 -276
  38. package/dist/mobile.d.cts +12 -2
  39. package/dist/mobile.d.ts +12 -2
  40. package/dist/mobile.mjs +328 -276
  41. package/dist/mocks.cjs +5 -5
  42. package/dist/mocks.d.cts +2 -2
  43. package/dist/mocks.d.ts +2 -2
  44. package/dist/mocks.mjs +4 -4
  45. package/dist/notifications.cjs +1 -1
  46. package/dist/notifications.d.cts +1 -1
  47. package/dist/notifications.d.ts +1 -1
  48. package/dist/notifications.mjs +1 -1
  49. package/dist/react.cjs +119 -119
  50. package/dist/react.d.cts +8 -2
  51. package/dist/react.d.ts +8 -2
  52. package/dist/react.mjs +119 -119
  53. package/dist/support.cjs +1 -1
  54. package/dist/support.d.cts +1 -1
  55. package/dist/support.d.ts +1 -1
  56. package/dist/support.mjs +1 -1
  57. package/dist/telemetry.cjs +62 -49
  58. package/dist/telemetry.d.cts +1 -1
  59. package/dist/telemetry.d.ts +1 -1
  60. package/dist/telemetry.mjs +62 -49
  61. package/dist/{types-yv3EDKg2.d.cts → types-Bl_4HROd.d.cts} +62 -3
  62. package/dist/{types-BYPk_3HR.d.ts → types-Bqnsqvow.d.ts} +62 -3
  63. package/dist/usage.cjs +1 -1
  64. package/dist/usage.d.cts +1 -1
  65. package/dist/usage.d.ts +1 -1
  66. package/dist/usage.mjs +1 -1
  67. package/dist/webhooks.cjs +1 -1
  68. package/dist/webhooks.d.cts +1 -1
  69. package/dist/webhooks.d.ts +1 -1
  70. package/dist/webhooks.mjs +1 -1
  71. package/package.json +9 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,52 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [3.9.1] — 2026-10-26 (o build barra a CSP que deixa o App Router em branco)
11
+
12
+ > **Por que PATCH.** É conserto de defeito (bug_0d2e0087). Atenção: o `next build` de um app com App Router passa a **falhar** quando a CSP do `headers()` bloqueia os scripts inline do Next (sem nonce, sem `'strict-dynamic'` e sem `'unsafe-inline'`). Essa CSP já deixava a página em branco no ar; agora o defeito aparece no build. As funções exportadas novas (`findCspInlineScriptBlocks`, `assertNeetruCspAllowsAppRouterScripts`, `hasNextAppRouter`) só somam.
13
+
14
+ ### Corrigido
15
+
16
+ - **Deploy com sucesso e página em branco: uma CSP do `next.config` derrubava o App Router e nada no build percebia** (bug_0d2e0087c53945d4a8bc89eb6e3c379a, caso Zelo 2026-10-22). O `headers()` mandava `Content-Security-Policy: ... script-src 'self' ...`, sem `'unsafe-inline'` e sem nonce. O App Router põe `<script>` embutidos em toda página (`self.__next_f.push`, o payload do React Server Components). O navegador bloqueia esses scripts, a hidratação falha na raiz e o React desmonta a árvore. O servidor respondia 200 com o HTML inteiro, a sonda de saúde passava e o deploy ficava `success`.
17
+ - `withNeetruBuildGuard` agora embrulha o `headers()` do produto. Em app com App Router (pasta `app/` ou `src/app/`, a mesma regra do `findPagesDir` do Next), o `next build` **falha** quando alguma `Content-Security-Policy` bloqueia script embutido. A mensagem, em português, diz qual regra (`source`) e a linha a trocar (`troque: script-src 'self'` / `por: script-src 'self' 'unsafe-inline'`).
18
+ - Diretiva efetiva na ordem da CSP: `script-src-elem` → `script-src` → `default-src`. Passa com nonce, com `'strict-dynamic'` ou com `'unsafe-inline'`. `'unsafe-inline'` com hash `'sha…-'` ao lado **não** passa, porque o navegador ignora o `'unsafe-inline'` nesse caso.
19
+ - Não afeta: Pages Router puro, `Content-Security-Policy-Report-Only`, regras de `/api` e `/_next`, e produto sem `headers()` (o guard não cria a chave). Em `next dev` só avisa. `next start` lê o `routes-manifest.json` e não chama `headers()`, então nada muda em runtime.
20
+ - Regra pura exportada: `findCspInlineScriptBlocks`, `assertNeetruCspAllowsAppRouterScripts`, `hasNextAppRouter`.
21
+ - Limites: CSP montada no middleware ou em `<meta>` não passa por aqui. `'strict-dynamic'` sem nonce nenhum também bloquearia no navegador, mas passa no guard, como a proposta do bug pede (é a marca da configuração por nonce). Um `'nonce-…'` FIXO no `headers()` também passa no guard e ainda deixa a página em branco: o App Router lê o nonce do header `Content-Security-Policy` da REQUISIÇÃO (que o middleware põe), não da resposta que o `headers()` monta (conferido no `app-render.js` do Next 15.5.28). Esses casos ficam para a sonda pós-deploy do `/` (guarda 2 da proposta), que é do Core/agente e não faz parte desta mudança.
22
+
23
+ ## [3.9.0] — 2026-10-11 (signOut deixa de falhar em silêncio)
24
+
25
+ > **Por que MINOR e não PATCH.** O conteúdo é conserto de defeito, mas o tipo
26
+ > público mudou: `signOut()` passou de `Promise<void>` para
27
+ > `Promise<SignOutResult>`. Em runtime é aditivo — quem faz
28
+ > `await client.auth.signOut()` e ignora o retorno continua idêntico. Em
29
+ > TypeScript quebra quem anotou o retorno como `void` explicitamente ou
30
+ > implementa `AuthNamespace` por conta própria. Chamar isso de patch faria o
31
+ > número mentir sobre o código, que é o defeito que estamos justamente
32
+ > consertando no ecossistema esta semana.
33
+
34
+ ### Corrigido
35
+
36
+ - **`auth.signOut()` falhava em silêncio quando a revogação remota não acontecia** (bug_2bfde1e346a74737bf80104b1c95b2b2, continuação). A 3.8.0 consertou o *formato* da requisição (`application/x-www-form-urlencoded` + `client_id`, RFC 7009) — mas o `signOut` seguia devolvendo `void` e engolindo a falha num `console.warn`. Pro produto, "revoguei" e "o servidor recusou" eram **indistinguíveis**: a tela dizia "você saiu" e o `refresh_token` de 30 dias podia seguir válido no servidor. Num terminal compartilhado (PDV, balcão), é a próxima pessoa herdando a sessão.
37
+ - `auth.signOut()` e `mobile.signOut()` agora devolvem `SignOutResult` — `{ localSessionCleared, remoteRevocation }`, com `remoteRevocation` em `accepted | skipped | not_configured | failed`.
38
+ - **Não lança** em falha de revogação, de propósito: a sessão LOCAL é encerrada sempre (o usuário pediu pra sair, e deixá-lo logado porque a rede caiu é o pior dos mundos), e um `throw` seria engolido pelo `try/catch` que todo caller de signOut tem — inclusive o `<AccountBar>` deste próprio SDK. O sinal precisa voltar como **valor**, não como exceção.
39
+ - `not_configured` cobre o caso mais silencioso de todos: sem `oidcClientId`/`apiKey` o SDK não monta o `client_id` que o `/revoke` exige, então **nenhuma requisição saía** — zero fetch, zero erro, sessão do servidor intacta.
40
+ - Honestidade sobre o que `accepted` significa: a RFC 7009 §2.2 manda o `/revoke` responder 200 **inclusive** pra token desconhecido (não vazar enumeração). `accepted` é "o servidor aceitou a revogação", não "o token existia e morreu". `failed`, esse sim, é inequívoco.
41
+ - `<AccountBar>`: `onSignOut` passa a receber o `SignOutResult` (`undefined` se o signOut lançou).
42
+
43
+ - **Storage que falha podia abortar a saída do usuário.** Um `removeItem` que lançasse (localStorage bloqueado/quota; SecureStore indisponível no RN) derrubava o `signOut` inteiro **antes** do revoke: sobravam chaves no aparelho, a sessão do servidor seguia de pé e o produto recebia uma exceção no lugar da saída. Agora cada remoção é isolada, a revogação acontece mesmo assim, e `localSessionCleared: false` avisa que ainda pode haver material de sessão **neste** aparelho.
44
+ - No mobile, o `notify()` final também relia o storage: uma falha de **leitura** fazia o `signOut` rejeitar depois de já ter limpado e revogado — o resultado nunca chegava ao caller e os listeners de `onAuthStateChanged` não ficavam sabendo que o usuário saiu (a UI seguia mostrando sessão). O `notify` agora aceita o estado já conhecido (`null` pós-signOut) e nunca rejeita por causa do storage.
45
+
46
+ > As três entradas abaixo vieram do #46, mesclado depois do PR de release da 3.9.0 (#45) e antes de qualquer publicação. A 3.9.0 nunca foi publicada, então o número continua identificando um código só: este.
47
+
48
+ - **A trava contra mock em produção estava pela metade.** Com `env: 'dev'` vazado para um runtime de produção, só o `auth` respeitava a trava: o `checkout` caía no `MockCheckout` e devolvia link de pagamento falso (`https://localhost:9003/portal/checkout/...`) como se fosse real; a `telemetry` virava console e respondia ok sem enviar nada; o `db.sql()` lançava "use `neetru dev`". Agora a decisão é uma só — `isDevMode()` em `src/runtime-env.ts` — e os quatro pontos consultam ela.
49
+ - **A guarda que impede dependência de Node no bundle de navegador nunca rodava.** O teste se pulava quando `dist/` não existia, e o gate rodava os testes antes do build (inclusive com `--full`), assim como o CI. Os dois bugs CRÍTICOS que ela devia cobrir (`bug_0f836014`, `bug_168368ae`, o segundo publicado no npm) ficaram "cobertos" por um teste verde que não olhava nada. A guarda virou `scripts/browser-bundle-guard.mjs` e roda no `postbuild` — então também no `prepublishOnly`: bundle contaminado não chega mais ao npm. A ordem do gate e do CI passou a ser `lint → build → test`, o detector roda sempre com fixtures em memória e a varredura do artefato falha (em vez de pular) quando `dist/` não existe.
50
+ - **O refresh de token podia morrer para sempre.** O `fetch` do refresh ia sem prazo: uma conexão pendurada (captive portal, proxy que engole o pacote, app voltando do background) deixava a promise sem desfecho, e o `finally` que libera o latch nunca rodava — nenhum refresh novo saía até recarregar o app. Agora há prazo de 15 s em duas camadas (`src/timeout.ts`): `AbortSignal` que corta a conexão e uma corrida que garante o desfecho mesmo se o `fetch` injetado ignorar o sinal. Resposta que chega depois do prazo é descartada, para não ressuscitar uma sessão que o caller já encerrou. Vale para o refresh na web e para o `postToken` do mobile (refresh e troca `code`→tokens).
51
+
52
+ ### Compatibilidade
53
+
54
+ - `signOut()` passou de `Promise<void>` para `Promise<SignOutResult>`. Em runtime é aditivo — quem faz `await client.auth.signOut()` e ignora o retorno continua idêntico. Em TypeScript só quebra quem anotou o retorno como `void` explicitamente (ex.: `const r: void = await signOut()`) ou implementa `AuthNamespace` por conta própria.
55
+
10
56
  ## [3.8.1] — 2026-10-11 (re-lease em falha de autenticação + doc de mTLS)
11
57
 
12
58
  ### Corrigido
package/README.md CHANGED
@@ -107,7 +107,10 @@ await auth.signIn({ redirectUri });
107
107
  await auth.completeSignIn(callbackUrl);
108
108
  const res = await auth.authFetch('/vendas'); // Bearer access_token, renova 1x num 401
109
109
  const me = await auth.getUserInfo(); // /userinfo do Core
110
- await auth.signOut(); // limpa local + revoga refresh/access no Core
110
+ const out = await auth.signOut(); // limpa local + revoga refresh/access no Core
111
+ if (out.remoteRevocation === 'failed') { // NÃO é silencioso: trate no produto
112
+ warn('Saímos deste aparelho, mas não deu pra encerrar a sessão no servidor.');
113
+ }
111
114
  ```
112
115
 
113
116
  `client.db` em React Native lança erro claro (dados de negócio vão pela API do
@@ -172,6 +175,16 @@ Grava `.next/neetru-build-manifest.json` com o `NEXT_PUBLIC_NEETRU_ENV`/`_PRODUC
172
175
 
173
176
  Só disponível via `@neetru/sdk/build-guard` (não o barrel `.`) — é o único módulo do SDK com import estático de `node:fs`/`node:path`, mantido fora do bundle universal de propósito.
174
177
 
178
+ **CSP que deixa a página em branco (não publicado ainda).** Em app com App Router (pasta `app/` ou `src/app/`), o guard embrulha o `headers()` do seu `next.config` e **falha o `next build`** se algum `Content-Security-Policy` bloquear script embutido: `script-src` (ou `script-src-elem`; sem os dois, o `default-src`) sem `'unsafe-inline'`, sem nonce e sem `'strict-dynamic'`. O App Router põe `<script>` embutidos em toda página (`self.__next_f.push`); com uma CSP dessas o navegador os bloqueia, a hidratação falha e a tela fica em branco, mesmo com o servidor respondendo 200 (caso Zelo, 2026-10-22). A mensagem de erro diz a linha a trocar:
179
+
180
+ ```
181
+ 1) headers() → source "/(.*)" → Content-Security-Policy
182
+ troque: script-src 'self'
183
+ por: script-src 'self' 'unsafe-inline'
184
+ ```
185
+
186
+ Ficam de fora: Pages Router puro, `Content-Security-Policy-Report-Only`, regras de `/api` e `/_next`, e CSP montada no middleware ou em `<meta>` (o guard só enxerga o `headers()` do `next.config`). Em `next dev` só avisa no terminal.
187
+
175
188
  ## Exemplos por namespace
176
189
 
177
190
  ### Login OIDC — Authorization Code + PKCE (3.1.3)
package/dist/ai.cjs CHANGED
@@ -82,7 +82,7 @@ function Z(t, e) {
82
82
  }
83
83
  function Q() {
84
84
  try {
85
- return "3.8.1";
85
+ return "3.9.1";
86
86
  } catch {
87
87
  return;
88
88
  }
package/dist/ai.d.cts CHANGED
@@ -1,3 +1,3 @@
1
- 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, aK as createAiNamespace } from './types-yv3EDKg2.cjs';
1
+ 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, aM as createAiNamespace } from './types-Bl_4HROd.cjs';
2
2
  import 'drizzle-orm/node-postgres';
3
3
  import './errors.cjs';
package/dist/ai.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- 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, aK as createAiNamespace } from './types-BYPk_3HR.js';
1
+ 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, aM as createAiNamespace } from './types-Bqnsqvow.js';
2
2
  import 'drizzle-orm/node-postgres';
3
3
  import './errors.js';
package/dist/ai.mjs CHANGED
@@ -80,7 +80,7 @@ function Z(t, e) {
80
80
  }
81
81
  function Q() {
82
82
  try {
83
- return "3.8.1";
83
+ return "3.9.1";
84
84
  } catch {
85
85
  return;
86
86
  }