@neetru/sdk 1.1.1 → 1.2.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 (83) hide show
  1. package/CHANGELOG.md +33 -3
  2. package/README.md +135 -159
  3. package/dist/auth.cjs +482 -42
  4. package/dist/auth.cjs.map +1 -1
  5. package/dist/auth.d.cts +1 -1
  6. package/dist/auth.d.ts +1 -1
  7. package/dist/auth.mjs +482 -42
  8. package/dist/auth.mjs.map +1 -1
  9. package/dist/catalog.cjs +63 -24
  10. package/dist/catalog.cjs.map +1 -1
  11. package/dist/catalog.d.cts +2 -2
  12. package/dist/catalog.d.ts +2 -2
  13. package/dist/catalog.mjs +63 -24
  14. package/dist/catalog.mjs.map +1 -1
  15. package/dist/checkout.cjs +60 -18
  16. package/dist/checkout.cjs.map +1 -1
  17. package/dist/checkout.d.cts +1 -1
  18. package/dist/checkout.d.ts +1 -1
  19. package/dist/checkout.mjs +60 -18
  20. package/dist/checkout.mjs.map +1 -1
  21. package/dist/db.cjs +66 -25
  22. package/dist/db.cjs.map +1 -1
  23. package/dist/db.d.cts +1 -1
  24. package/dist/db.d.ts +1 -1
  25. package/dist/db.mjs +66 -25
  26. package/dist/db.mjs.map +1 -1
  27. package/dist/entitlements.cjs +101 -24
  28. package/dist/entitlements.cjs.map +1 -1
  29. package/dist/entitlements.d.cts +11 -5
  30. package/dist/entitlements.d.ts +11 -5
  31. package/dist/entitlements.mjs +101 -24
  32. package/dist/entitlements.mjs.map +1 -1
  33. package/dist/index.cjs +487 -43
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.cts +3 -3
  36. package/dist/index.d.ts +3 -3
  37. package/dist/index.mjs +484 -44
  38. package/dist/index.mjs.map +1 -1
  39. package/dist/mocks.cjs +3 -2
  40. package/dist/mocks.cjs.map +1 -1
  41. package/dist/mocks.d.cts +4 -2
  42. package/dist/mocks.d.ts +4 -2
  43. package/dist/mocks.mjs +3 -2
  44. package/dist/mocks.mjs.map +1 -1
  45. package/dist/notifications.cjs +296 -0
  46. package/dist/notifications.cjs.map +1 -0
  47. package/dist/notifications.d.cts +1 -0
  48. package/dist/notifications.d.ts +1 -0
  49. package/dist/notifications.mjs +293 -0
  50. package/dist/notifications.mjs.map +1 -0
  51. package/dist/react.cjs +7 -3
  52. package/dist/react.cjs.map +1 -1
  53. package/dist/react.d.cts +1 -1
  54. package/dist/react.d.ts +1 -1
  55. package/dist/react.mjs +7 -3
  56. package/dist/react.mjs.map +1 -1
  57. package/dist/support.cjs +60 -18
  58. package/dist/support.cjs.map +1 -1
  59. package/dist/support.d.cts +1 -1
  60. package/dist/support.d.ts +1 -1
  61. package/dist/support.mjs +60 -18
  62. package/dist/support.mjs.map +1 -1
  63. package/dist/telemetry.cjs +130 -19
  64. package/dist/telemetry.cjs.map +1 -1
  65. package/dist/telemetry.d.cts +17 -1
  66. package/dist/telemetry.d.ts +17 -1
  67. package/dist/telemetry.mjs +130 -19
  68. package/dist/telemetry.mjs.map +1 -1
  69. package/dist/{types-BA53dd8S.d.cts → types-CQAfwqUS.d.cts} +172 -8
  70. package/dist/{types-BA53dd8S.d.ts → types-CQAfwqUS.d.ts} +172 -8
  71. package/dist/usage.cjs +60 -18
  72. package/dist/usage.cjs.map +1 -1
  73. package/dist/usage.d.cts +1 -1
  74. package/dist/usage.d.ts +1 -1
  75. package/dist/usage.mjs +60 -18
  76. package/dist/usage.mjs.map +1 -1
  77. package/dist/webhooks.cjs +316 -0
  78. package/dist/webhooks.cjs.map +1 -0
  79. package/dist/webhooks.d.cts +1 -0
  80. package/dist/webhooks.d.ts +1 -0
  81. package/dist/webhooks.mjs +312 -0
  82. package/dist/webhooks.mjs.map +1 -0
  83. package/package.json +12 -2
package/CHANGELOG.md CHANGED
@@ -7,11 +7,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- ### Planned (post-1.1)
11
- - Telemetry batching + flush on unload.
12
- - LRU cache em entitlements.check (TTL configurável).
10
+ ### Planned (post-1.2)
13
11
  - size-limit budget no CI (<12KB gz core com db namespace).
14
12
  - CDN distribution (`cdn.neetru.com/sdk/v1/`).
13
+ - Endpoint batch `/api/v1/sdk/telemetry/batch` (substitui drenagem N×1 do `track()` por 1 request).
14
+
15
+ ## [1.2.0] - 2026-05-19 — **Webhooks + Notifications + DX (cache, retry, batch)**
16
+
17
+ Release de qualidade fechando 3 CRITICAL + 6 IMPORTANT do code review interno + 4 melhorias de DX. Adiciona `webhooks` + `notifications` no `NeetruClient`.
18
+
19
+ ### Added
20
+ - **`client.webhooks`** — `register`/`list`/`unregister`/`test` pra endpoints HTTP do produto receberem eventos do Core (subscription.activated, usage.quota_exceeded, etc).
21
+ - **`verifyWebhookSignature(payload, signature, secret)`** — util pura (HMAC SHA-256 constant-time compare via `node:crypto`) pra consumidor validar payloads recebidos.
22
+ - **`client.notifications`** — `send`/`list`/`markRead`/`dismiss` pra produto integrar com a bandeja in-app do Neetru.
23
+ - **`client.telemetry.track(input)`** + `client.telemetry.flush()` — fire-and-forget batch (500ms debounce). Ideal pra alta frequência (page-views, cliques). `event()` segue como single-shot com `eventId` ack.
24
+ - **`client.entitlements.check(..., { cacheBust })`** — cache LRU em memória (60s TTL, 100 entries). Corta 90%+ requests em renders repetidos do `<EntitlementGate>`. `cacheBust: true` força ida ao servidor.
25
+ - **httpRequest retry/backoff** — 2 retries default em `rate_limited` (429), `server_error` (5xx), `network_error`. Honra `Retry-After` header. Caller opt-out com `opts.retries: 0`.
26
+ - **Subpaths novos**: `@neetru/sdk/webhooks`, `@neetru/sdk/notifications`.
27
+
28
+ ### Changed
29
+ - **`client.catalog.list()` / `get()`** agora consomem `/api/sdk/v1/catalog` (público, sem Bearer) em vez de `/api/v1/cli/catalog` (staff). Consumidor não precisa mais de chave staff só pra ler catálogo. `includeDrafts` é ignorado — rascunhos só via CLI.
30
+ - **`auth.signOut()`** revoga token em `auth.neetru.com/api/v1/oauth/revoke` (canônico), não mais `api.neetru.com/oauth/revoke` (404 em prod).
31
+ - **`<EntitlementGate>`** passa `tenantId` (do `client.config.tenantId`) pra `usage.check`. Sem tenantId, cai pra `entitlements.check` em vez de chamar `usage.check` e travar em `validation_failed` silencioso.
32
+ - **`engines.node`** subiu pra `>=20` (alinha com `target: node20` do tsup; Node 18 EOL).
33
+
34
+ ### Fixed
35
+ - **CRITICAL** — `webhooks` e `notifications` lançavam `'invalid_input'`, código ausente da union `NeetruErrorCode`. Todas as 17 ocorrências viraram `'validation_failed'`.
36
+ - **CRITICAL** — `telemetry.log()` chamava `/sdk/v1/telemetry/log` (404). Corrigido pra `/api/sdk/v1/telemetry/log`.
37
+ - **CRITICAL** — `db` namespace tinha o mesmo bug em 6 paths (`/sdk/v1/datastore/...`). Corrigido em massa pra `/api/sdk/v1/datastore/...`.
38
+ - **CRITICAL** — 8 `httpRequest` calls em `webhooks` e `notifications` não passavam `requireAuth: true` — todos hits em prod retornavam 401. Corrigido.
39
+ - **`MockSupport.mockTicketSeq`** virou instance field (era module-level, poluía tests entre suites).
40
+ - **`db.list()`** removeu variável `query` dead code (refactor incompleto de pre-1.1).
41
+
42
+ ### Internal
43
+ - 51 testes novos (webhooks: 22, notifications: 20, react: 9). Total: 215 testes (16 files), 100% passing. tsc clean.
44
+ - `api-surface-stability.test.ts` agora lock `webhooks` + `notifications` no `NeetruClient`.
15
45
 
16
46
  ## [1.1.0] - 2026-05-08 — **Checkout namespace + React helpers**
17
47
 
package/README.md CHANGED
@@ -1,218 +1,194 @@
1
1
  # @neetru/sdk
2
2
 
3
- Biblioteca runtime para consumir o ecossistema Neetru catálogo público de
4
- produtos, entitlements de tenant e telemetria — de qualquer
5
- JavaScript/TypeScript moderno (browser, Node ≥20, Edge runtimes).
3
+ > Biblioteca runtime oficial pra consumir o ecossistema Neetru a partir de produtos SaaS (Next.js, Node, browser, Edge runtimes).
6
4
 
7
- > **Status:** `1.0.0` GA — superfície pública estabilizada (2026-05-06).
8
- > Namespaces `auth`/`catalog`/`entitlements`/`telemetry`/`usage`/`support`/`db`.
9
- > A partir de v1.0, breaking changes só em majors. CDN distribution segue
10
- > roadmap pós-1.0 — vide [`docs/PLAN_SDK_NEETRU.md`](../docs/PLAN_SDK_NEETRU.md).
5
+ <p>
6
+ <img alt="npm" src="https://img.shields.io/npm/v/@neetru/sdk?logo=npm">
7
+ <img alt="downloads" src="https://img.shields.io/npm/dm/@neetru/sdk?logo=npm">
8
+ <img alt="bundle size" src="https://img.shields.io/bundlephobia/minzip/@neetru/sdk">
9
+ <img alt="Node" src="https://img.shields.io/badge/node-%3E%3D18-339933?logo=node.js&logoColor=white">
10
+ <img alt="license" src="https://img.shields.io/badge/license-MIT-22c55e">
11
+ </p>
11
12
 
12
- ---
13
-
14
- ## Princípios
15
-
16
- - **Vendor-neutral** — apesar do Core usar Firebase, a superfície pública do
17
- SDK não vaza isso (sem `firebase/app` exposto).
18
- - **TypeScript-first** — `.d.ts` shipped, JSDoc em toda função pública.
19
- - **Tree-shakable** — ESM-first, `"sideEffects": false`. Subpath imports
20
- permitidos (`@neetru/sdk/catalog`, `@neetru/sdk/telemetry`, etc).
21
- - **Universal** — usa `fetch` global. Sem `node:` builtins no core.
22
- - **Erros tipados** — todos erros são `NeetruError` com `.code`, `.status`,
23
- `.requestId`.
24
- - **Semver estrito** — pós v1.0, breaking changes só em majors.
25
-
26
- ## Install
13
+ ## Instalação
27
14
 
28
15
  ```bash
29
16
  npm install @neetru/sdk
30
17
  ```
31
18
 
32
- > Pacote ainda **privado** (`private: true`) e não publicado no npm.
33
- > Reservar é responsabilidade do owner em Sprint 6 do plano.
34
-
35
- ## Quick start
19
+ ## Hello world
36
20
 
37
21
  ```ts
38
- import { createNeetruClient, NeetruError } from '@neetru/sdk';
22
+ import { createNeetruClient } from '@neetru/sdk';
39
23
 
40
- const client = createNeetruClient({
41
- apiKey: process.env.NEETRU_API_KEY, // ou deixe undefined que ele lê do env
42
- baseUrl: 'https://api.neetru.com', // default
24
+ const neetru = createNeetruClient({
25
+ apiKey: process.env.NEETRU_API_KEY, // nrt_<keyId>_<secret>
26
+ env: 'prod', // 'dev' = mocks in-memory
43
27
  });
44
28
 
45
- // 1. Catálogo público de produtos
46
- const { products } = await client.catalog.list();
47
- console.log(products.map((p) => p.slug));
48
-
49
- const product = await client.catalog.get('neetru-pulse');
50
-
51
- // 2. Entitlements — pode o caller usar a feature `export-pdf` do produto?
52
- const allowed = await client.entitlements.check('neetru-pulse', 'export-pdf');
53
- if (!allowed) showUpgradeBanner();
29
+ // Auth
30
+ const user = await neetru.auth.signIn();
31
+ console.log('logado como:', user?.email);
54
32
 
55
- // 3. Telemetria — emite evento de uso
56
- await client.telemetry.event({
57
- name: 'report_exported',
58
- properties: { format: 'pdf', plan: 'pro' },
59
- });
60
- ```
61
-
62
- Discriminação de erro:
63
-
64
- ```ts
65
- try {
66
- await client.catalog.list();
67
- } catch (err) {
68
- if (err instanceof NeetruError) {
69
- if (err.code === 'rate_limited') retry();
70
- if (err.code === 'unauthorized') promptLogin();
71
- console.error(err.code, err.message, err.status, err.requestId);
72
- }
73
- }
33
+ // Entitlement check
34
+ const canAi = await neetru.entitlements.check('gestovendas', 'ai_recommendations');
35
+ if (canAi) { /* mostrar feature */ }
74
36
  ```
75
37
 
76
- ## API reference (v0.2)
38
+ ## Princípios
77
39
 
78
- ### `createNeetruClient(config?)`
40
+ - **Vendor-neutral** — superfície pública NÃO vaza Firebase/Stripe/etc. Backend Neetru pode mudar no futuro sem reescrever produto.
41
+ - **Tree-shakable** — ESM-first, sem side-effects. Importe só os namespaces que usa.
42
+ - **Universal** — browser, Node ≥18, Edge runtimes (Vercel Edge, Cloudflare Workers). Usa `fetch` global.
43
+ - **Tipado** — erros via `NeetruError` com `.code`, `.status`, `.requestId`.
44
+ - **Dev mode** — `NEETRU_ENV=dev` ativa mocks automáticos — zero rede em testes locais.
79
45
 
80
- | Campo | Tipo | Descrição |
81
- |---|---|---|
82
- | `apiKey` | `string?` | Bearer token `nrt_<keyId>_<secret>`. Default lê `process.env.NEETRU_API_KEY` em Node. |
83
- | `baseUrl` | `string?` | URL base. Default `https://api.neetru.com`. |
84
- | `fetch` | `typeof fetch?` | Implementação custom. Default `globalThis.fetch`. |
85
- | `env` | `'dev' \| 'workspace' \| 'prod'?` | Ativa mocks automáticos em `dev`. Default `prod` (lê `NEETRU_ENV`). |
86
- | `mocks` | `{ auth?, usage?, support?, entitlements? }?` | Override de namespaces — útil em tests do consumer. |
46
+ ## Namespaces v1.2
87
47
 
88
- Retorna `NeetruClient` com `.config`, `.auth`, `.catalog`, `.entitlements`, `.telemetry`, `.usage`, `.support`.
48
+ | Namespace | O que oferece |
49
+ |---|---|
50
+ | `auth` | OIDC sign-in / sign-out + dev fixture user |
51
+ | `catalog` | Produtos públicos (`list` / `get`) |
52
+ | `entitlements` | Verificação `(productSlug, feature)` → boolean ou detalhado |
53
+ | `telemetry` | `event(...)` + `log(...)` per-product |
54
+ | `usage` | `track` / `getQuota` / `report` / `check` (metering canônico) |
55
+ | `support` | `createTicket` / `listMyTickets` |
56
+ | `db` | Coleções tenant-scoped (`list` / `get` / `set` / `add` / `update` / `remove`) |
57
+ | `checkout` | Stripe Checkout intent (`start` / `get` / `cancel` + auto-redirect) |
58
+ | `webhooks` ⭐ v1.2 | Produtos registram URL pra receber eventos Core (subscription.activated, usage.quota_exceeded, etc) |
59
+ | `notifications` ⭐ v1.2 | Produto envia notification in-app pros SEUS usuários (distinto das staff-only do Core) |
89
60
 
90
- ### `client.auth` (v0.2)
61
+ ## Exemplos por namespace
91
62
 
92
- | Método | Descrição |
93
- |---|---|
94
- | `signIn(options?)` | Redireciona pro authorize endpoint (browser) ou retorna fixture user (dev). |
95
- | `signOut()` | Limpa session local + revoga refresh server-side. |
96
- | `getUser()` | Retorna `NeetruUser` cached do id_token ou `null`. |
97
- | `onAuthStateChanged(listener)` | Sub a mudanças. Dispatch sync no subscribe. Retorna unsubscribe. |
63
+ ### Webhooks outbound (v1.2)
98
64
 
99
- ### `client.catalog`
65
+ ```ts
66
+ await neetru.webhooks.register({
67
+ url: 'https://meu-produto.com/webhooks/neetru',
68
+ events: ['subscription.activated', 'subscription.cancelled', 'usage.quota_exceeded'],
69
+ secret: 'chave-32-chars-pra-hmac-sha256',
70
+ });
100
71
 
101
- | Método | Descrição |
102
- |---|---|
103
- | `list(opts?)` | `GET /api/v1/cli/catalog`. Retorna `{ products, fetchedAt }`. |
104
- | `get(slug)` | `GET /api/v1/cli/catalog/{slug}`. Retorna `Product` ou lança `not_found`. |
72
+ const endpoints = await neetru.webhooks.list();
73
+ const test = await neetru.webhooks.test(endpoints[0].id);
74
+ console.log(test.statusCode, test.durationMs);
75
+ ```
105
76
 
106
- ### `client.entitlements`
77
+ Eventos recebidos no seu endpoint chegam com:
78
+ - `X-Neetru-Signature: sha256=<hmac>` (se `secret` registrado)
79
+ - `X-Neetru-Timestamp: <ms>` (replay protection — rejeitar > 5min skew)
107
80
 
108
- | Método | Descrição |
109
- |---|---|
110
- | `check(slug, feature)` | `boolean`. Atalho do `checkDetailed`. |
111
- | `checkDetailed(slug, feature)` | `EntitlementCheck` com `allowed`, `reason`. |
81
+ ### Notifications produto user (v1.2)
112
82
 
113
- ### `client.telemetry`
83
+ ```ts
84
+ await neetru.notifications.send({
85
+ userId: 'usr_xyz',
86
+ kind: 'order.received',
87
+ severity: 'success',
88
+ title: 'Novo pedido #1234',
89
+ body: 'Pedido de R$ 89,90',
90
+ link: '/orders/1234',
91
+ fingerprint: 'order:1234', // dedup < 24h
92
+ });
114
93
 
115
- | Método | Descrição |
116
- |---|---|
117
- | `event({ name, properties?, timestamp? })` | `POST /api/v1/sdk/telemetry/event`. Retorna `{ ok, eventId }`. |
94
+ const notifs = await neetru.notifications.list('usr_xyz', { onlyUnread: true });
95
+ await neetru.notifications.markRead(notifs[0].id);
96
+ ```
118
97
 
119
- ### `client.usage` (v0.2)
98
+ ### Entitlements
120
99
 
121
- | Método | Descrição |
122
- |---|---|
123
- | `track(event, props?)` | `POST /sdk/v1/usage/record`. Persiste consumo. |
124
- | `getQuota(metric)` | `GET /sdk/v1/usage/quota?metric=`. Retorna `{ used, limit, plan, resetsAt? }`. |
100
+ ```ts
101
+ const ok = await neetru.entitlements.check('gestovendas', 'ai_recommendations');
102
+ const detailed = await neetru.entitlements.detailed('gestovendas', 'ai_recommendations');
103
+ // { allowed, planId, remaining?, limit?, reason }
104
+ ```
125
105
 
126
- ### `client.support` (v0.2)
106
+ ### Usage tracking
127
107
 
128
- | Método | Descrição |
129
- |---|---|
130
- | `createTicket({subject, message, severity?, productSlug?})` | `POST /api/v1/products/{slug}/tickets`. |
131
- | `listMyTickets()` | `GET /api/v1/products/_default/tickets`. |
108
+ ```ts
109
+ await neetru.usage.track('report_generated', { count: 42, format: 'pdf' });
132
110
 
133
- ### Mocks (`@neetru/sdk/mocks`)
111
+ const quota = await neetru.usage.getQuota('reports_per_month');
112
+ // → { used: 15, limit: 100, resetsAt: '...', plan: 'starter' }
113
+ ```
134
114
 
135
- Use em tests do consumer ou ative globalmente com `NEETRU_ENV=dev`:
115
+ ### Support
136
116
 
137
117
  ```ts
138
- import { createNeetruClient, MockAuth, MockUsage, MockSupport } from '@neetru/sdk';
139
-
140
- const client = createNeetruClient({
141
- mocks: {
142
- auth: new MockAuth({ uid: 'fake', email: 'fake@x.com' }),
143
- usage: new MockUsage(),
144
- support: new MockSupport(),
145
- },
118
+ await neetru.support.createTicket({
119
+ subject: 'Bug ao exportar CSV',
120
+ message: 'Quando seleciono >1000 rows o export falha',
121
+ severity: 'high',
146
122
  });
123
+
124
+ const myTickets = await neetru.support.listMyTickets({ status: 'open' });
147
125
  ```
148
126
 
149
- ### Códigos de erro estáveis (`NeetruError.code`)
127
+ ### DB (tenant-scoped, vendor-neutral)
150
128
 
151
- `invalid_config` · `missing_api_key` · `unauthorized` · `forbidden` ·
152
- `not_found` · `rate_limited` · `validation_failed` · `network_error` ·
153
- `invalid_response` · `server_error` · `unknown`.
129
+ ```ts
130
+ await neetru.db.add('orders', { customerId: 'usr_x', total: 9990 });
131
+ const orders = await neetru.db.list('orders', {
132
+ where: [['customerId', '==', 'usr_x']],
133
+ orderBy: 'createdAt',
134
+ limit: 50,
135
+ });
136
+ ```
154
137
 
155
- ## Subpath imports (tree-shaking)
138
+ ### Checkout
156
139
 
157
140
  ```ts
158
- // Importa o tipo de erro (zero deps de transport)
159
- import { NeetruError } from '@neetru/sdk/errors';
160
-
161
- // Bundlers podem fazer code-split por namespace
162
- import { createCatalogNamespace } from '@neetru/sdk/catalog';
141
+ const intent = await neetru.checkout.start({
142
+ productId: 'gestovendas',
143
+ planId: 'pro',
144
+ tenantType: 'company',
145
+ tenantId: 'company_xyz',
146
+ });
147
+ window.location.href = intent.checkoutUrl;
163
148
  ```
164
149
 
165
- ## Build
150
+ ## Modo dev (mocks automáticos)
166
151
 
167
- ```bash
168
- npm run build # tsup dist/{index,catalog,entitlements,telemetry,errors}.{mjs,cjs,d.ts}
169
- npm run dev # watch mode
170
- npm run lint # tsc --noEmit
171
- npm run test # vitest run (Sprint 2+)
152
+ ```ts
153
+ const neetru = createNeetruClient({ env: 'dev' });
154
+ // auth retorna DEV_FIXTURE_USER, usage/db/webhooks/notifications são in-memory
172
155
  ```
173
156
 
174
- Tooling: [tsup](https://tsup.egoist.dev) (esbuild backend, dual ESM+CJS,
175
- auto `.d.ts`).
157
+ Override pra testes determinísticos:
176
158
 
177
- ## Migration v0.3 → v1.0
178
-
179
- **Sem breaking changes.** Upgrade direto via `npm install @neetru/sdk@1.0.0`.
159
+ ```ts
160
+ import { MockAuth, MockUsage } from '@neetru/sdk';
180
161
 
181
- - `initNeetru` continua deprecated mas funcional. **Será removido em v2.0.0.**
182
- Use `createNeetruClient` em código novo.
183
- - `NeetruConfig` continua deprecated — use `NeetruClientConfig`.
184
- - Tipos exportados continuam idênticos.
185
- - Comportamento runtime idêntico apenas estabilização de contratos.
162
+ const neetru = createNeetruClient({
163
+ apiKey: 'nrt_test',
164
+ env: 'prod',
165
+ mocks: {
166
+ auth: new MockAuth({ user: { uid: 'test', email: 'a@b' } }),
167
+ usage: new MockUsage(),
168
+ },
169
+ });
170
+ ```
186
171
 
187
- ## Stability promise (v1.x)
172
+ ## Versionamento
188
173
 
189
- A partir de v1.0:
190
- - Métodos novos podem ser adicionados a namespaces existentes (minor bump).
191
- - Métodos podem ser marcados `@deprecated` em qualquer minor removidos
192
- em major.
193
- - Tipos nunca ganham campos required em minor (só optional ou via union).
194
- - `NeetruErrorCode` é union fechado em v1.0 — qualquer novo código bumpa minor.
174
+ - **SemVer estrito** — breaking changes só em major.
175
+ - v1.0 GA (2026-05-06) superfície estável de 7 namespaces
176
+ - v1.1 (2026-05)checkout namespace
177
+ - v1.2 (2026-05) — webhooks + notifications namespaces
195
178
 
196
- ## Generate API docs
179
+ `initNeetru` (API v0.0.1) está deprecated desde v0.2 — funciona até v2.0.
197
180
 
198
- ```bash
199
- npm install --include=dev # garante typedoc
200
- npm run docs:gen # → sdk/docs-html/index.html
201
- ```
181
+ ## Stack
202
182
 
203
- ## Roadmap
183
+ - TypeScript 5 ESM-first
184
+ - Zero dependências runtime (usa `fetch` global)
185
+ - Bundle minzip <10KB (todos namespaces somados, tree-shake-friendly)
204
186
 
205
- - **v1.0** — API stability + GA. JSDoc completo + typedoc.
206
- - **v1.1** — Telemetry batching + flush on unload.
207
- - **v1.2** — LRU cache em entitlements.check (TTL configurável).
208
- - **v1.x** — CDN release (`cdn.neetru.com/sdk/v1/`), SRI integrity.json,
209
- UMD/IIFE bundle.
187
+ ## Mais info
210
188
 
211
- Detalhes em
212
- [`docs/PLAN_SDK_NEETRU.md`](../docs/PLAN_SDK_NEETRU.md) +
213
- [`docs/PLAN_SDK_CLI_CDN.md`](../docs/PLAN_SDK_CLI_CDN.md).
189
+ - **Repo:** [github.com/Neetru/neetru-core](https://github.com/Neetru/neetru-core)
190
+ - **CLI complementar:** `npm install -g @neetru/cli`
214
191
 
215
- ## License
192
+ ## Licença
216
193
 
217
- UNLICENSED uso interno Neetru. License pública será definida em release
218
- público (npm publish).
194
+ MIT © Neetru