@neetru/sdk 3.1.12 → 3.1.13

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 (2) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/package.json +161 -161
package/CHANGELOG.md CHANGED
@@ -5,6 +5,26 @@ All notable changes to `@neetru/sdk` will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.1.13] - 2026-07-14 — **fix(auth): refresh_token rotation mantém a sessão viva além de ~1h (bug_339a100e)**
9
+
10
+ Release **patch** (bugfix de segurança/continuidade de sessão).
11
+
12
+ ### Fixed
13
+
14
+ - **Gap**: o SDK **descartava** o `refresh_token` que o `/api/v1/oauth/token` já devolvia. No vencimento do `id_token` (~1h) a sessão do cliente final simplesmente caía — `scheduleExpiryTimer` só deslogava. Nenhuma rota de auto-refresh existia.
15
+
16
+ ### Changed
17
+
18
+ - **`completeSignIn`** agora persiste o `refresh_token` em `localStorage['neetru_refresh_token']` (par do `neetru_id_token`).
19
+ - **Renovação proativa por timer**: o token é renovado ANTES de expirar (lead de 20% da vida restante, mín 30s) via `grant_type=refresh_token`. A rotação do Core (novo `id_token` + novo `refresh_token`, com replay-detection) é honrada — cada refresh persiste o par rotacionado.
20
+ - **Refresh silencioso no reload**: se a página recarrega com `id_token` já expirado mas um `refresh_token` presente, `getUser()` retorna `null` imediato e `onAuthStateChanged` recebe o usuário assim que o refresh assíncrono conclui.
21
+ - **`signOut`** remove também o `refresh_token` do storage.
22
+ - Falha de refresh (`invalid_grant`/replay/network/resposta inválida) → limpa a sessão inteira e notifica `null`. Dedup por `_refreshInFlight` (chamadas concorrentes compartilham um único POST).
23
+
24
+ ### Por que refresh_token rotation e NÃO silent-auth via iframe (`prompt=none`)
25
+
26
+ O SDK roda no domínio do PRODUTO e o IdP é `auth.neetru.com` — o cookie de sessão é **third-party**, então iframe silencioso quebra sob Safari ITP / Chrome third-party-cookie phase-out. O Core já implementa rotation + replay-detection (`token/route.ts handleRefreshToken`), que é a recomendação do **OAuth 2.0 for Browser-Based Apps BCP** pra SPA sem BFF. Ambos os grants (`prompt=none` e `refresh_token`) existem no Core; escolhemos o mais confiável sob política de cookie moderna.
27
+
8
28
  ## [3.1.12] - 2026-07-10 — **fix(auth): `completeSignIn` fecha o fluxo SPA PKCE (incidente de login pdv-agiliza)**
9
29
 
10
30
  Release **patch** (bugfix de gap). Descoberto 2026-07-10 durante incidente de login do pdv-agiliza.
package/package.json CHANGED
@@ -1,161 +1,161 @@
1
- {
2
- "name": "@neetru/sdk",
3
- "version": "3.1.12",
4
- "description": "Neetru SDK 3.0 — biblioteca runtime universal (browser/Node/Edge) para consumir o ecossistema Neetru. Paths canonical /api/sdk/v1/*, productId obrigatório, Idempotency-Key em mutations, WebCrypto signatures, baseUrl allowlist fail-closed.",
5
- "type": "module",
6
- "main": "./dist/index.cjs",
7
- "module": "./dist/index.mjs",
8
- "types": "./dist/index.d.ts",
9
- "exports": {
10
- ".": {
11
- "types": "./dist/index.d.ts",
12
- "import": "./dist/index.mjs",
13
- "require": "./dist/index.cjs"
14
- },
15
- "./auth": {
16
- "types": "./dist/auth.d.ts",
17
- "import": "./dist/auth.mjs",
18
- "require": "./dist/auth.cjs"
19
- },
20
- "./catalog": {
21
- "types": "./dist/catalog.d.ts",
22
- "import": "./dist/catalog.mjs",
23
- "require": "./dist/catalog.cjs"
24
- },
25
- "./entitlements": {
26
- "types": "./dist/entitlements.d.ts",
27
- "import": "./dist/entitlements.mjs",
28
- "require": "./dist/entitlements.cjs"
29
- },
30
- "./telemetry": {
31
- "types": "./dist/telemetry.d.ts",
32
- "import": "./dist/telemetry.mjs",
33
- "require": "./dist/telemetry.cjs"
34
- },
35
- "./usage": {
36
- "types": "./dist/usage.d.ts",
37
- "import": "./dist/usage.mjs",
38
- "require": "./dist/usage.cjs"
39
- },
40
- "./support": {
41
- "types": "./dist/support.d.ts",
42
- "import": "./dist/support.mjs",
43
- "require": "./dist/support.cjs"
44
- },
45
- "./mocks": {
46
- "types": "./dist/mocks.d.ts",
47
- "import": "./dist/mocks.mjs",
48
- "require": "./dist/mocks.cjs"
49
- },
50
- "./db": {
51
- "types": "./dist/db.d.ts",
52
- "import": "./dist/db.mjs",
53
- "require": "./dist/db.cjs"
54
- },
55
- "./errors": {
56
- "types": "./dist/errors.d.ts",
57
- "import": "./dist/errors.mjs",
58
- "require": "./dist/errors.cjs"
59
- },
60
- "./checkout": {
61
- "types": "./dist/checkout.d.ts",
62
- "import": "./dist/checkout.mjs",
63
- "require": "./dist/checkout.cjs"
64
- },
65
- "./firestore-compat": {
66
- "types": "./dist/firestore-compat.d.ts",
67
- "import": "./dist/firestore-compat.mjs",
68
- "require": "./dist/firestore-compat.cjs"
69
- },
70
- "./react": {
71
- "types": "./dist/react.d.ts",
72
- "import": "./dist/react.mjs",
73
- "require": "./dist/react.cjs"
74
- },
75
- "./db/react": {
76
- "types": "./dist/db-react.d.ts",
77
- "import": "./dist/db-react.mjs",
78
- "require": "./dist/db-react.cjs"
79
- },
80
- "./webhooks": {
81
- "types": "./dist/webhooks.d.ts",
82
- "import": "./dist/webhooks.mjs",
83
- "require": "./dist/webhooks.cjs"
84
- },
85
- "./notifications": {
86
- "types": "./dist/notifications.d.ts",
87
- "import": "./dist/notifications.mjs",
88
- "require": "./dist/notifications.cjs"
89
- },
90
- "./ai": {
91
- "types": "./dist/ai.d.ts",
92
- "import": "./dist/ai.mjs",
93
- "require": "./dist/ai.cjs"
94
- }
95
- },
96
- "peerDependencies": {
97
- "@electric-sql/pglite": "^0.4.0",
98
- "drizzle-orm": "^0.43.0 || ^0.44.0 || ^0.45.0",
99
- "pg": "^8.0.0",
100
- "pg-mem": "^3.0.0",
101
- "react": "^18.0.0 || ^19.0.0"
102
- },
103
- "peerDependenciesMeta": {
104
- "@electric-sql/pglite": {
105
- "optional": true
106
- },
107
- "drizzle-orm": {
108
- "optional": true
109
- },
110
- "pg": {
111
- "optional": true
112
- },
113
- "pg-mem": {
114
- "optional": true
115
- },
116
- "react": {
117
- "optional": true
118
- }
119
- },
120
- "sideEffects": false,
121
- "scripts": {
122
- "build": "tsup",
123
- "dev": "tsup --watch",
124
- "test": "vitest run",
125
- "lint": "tsc --noEmit",
126
- "docs:gen": "typedoc --options scripts/typedoc.config.json"
127
- },
128
- "files": [
129
- "dist",
130
- "README.md",
131
- "CHANGELOG.md"
132
- ],
133
- "engines": {
134
- "node": ">=20"
135
- },
136
- "license": "UNLICENSED",
137
- "devDependencies": {
138
- "@electric-sql/pglite": "^0.4.6",
139
- "@testing-library/jest-dom": "^6.9.1",
140
- "@testing-library/react": "^16.3.2",
141
- "@types/pg": "^8.11.10",
142
- "@types/react": "^19.2.15",
143
- "@types/react-dom": "^19.2.3",
144
- "@vitest/browser": "^4.1.7",
145
- "drizzle-orm": "^0.43.1",
146
- "fake-indexeddb": "^6.2.5",
147
- "jsdom": "^29.1.1",
148
- "pg": "^8.15.6",
149
- "pg-mem": "^3.0.5",
150
- "react": "^19.2.6",
151
- "react-dom": "^19.2.6",
152
- "tsup": "^8.3.5",
153
- "typedoc": "^0.28.19",
154
- "typescript": "^5.9.3",
155
- "vitest": "^4.1.7"
156
- },
157
- "dependencies": {
158
- "idb": "^8.0.3",
159
- "jose": "^6.2.3"
160
- }
161
- }
1
+ {
2
+ "name": "@neetru/sdk",
3
+ "version": "3.1.13",
4
+ "description": "Neetru SDK 3.0 — biblioteca runtime universal (browser/Node/Edge) para consumir o ecossistema Neetru. Paths canonical /api/sdk/v1/*, productId obrigatório, Idempotency-Key em mutations, WebCrypto signatures, baseUrl allowlist fail-closed.",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.mjs",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.mjs",
13
+ "require": "./dist/index.cjs"
14
+ },
15
+ "./auth": {
16
+ "types": "./dist/auth.d.ts",
17
+ "import": "./dist/auth.mjs",
18
+ "require": "./dist/auth.cjs"
19
+ },
20
+ "./catalog": {
21
+ "types": "./dist/catalog.d.ts",
22
+ "import": "./dist/catalog.mjs",
23
+ "require": "./dist/catalog.cjs"
24
+ },
25
+ "./entitlements": {
26
+ "types": "./dist/entitlements.d.ts",
27
+ "import": "./dist/entitlements.mjs",
28
+ "require": "./dist/entitlements.cjs"
29
+ },
30
+ "./telemetry": {
31
+ "types": "./dist/telemetry.d.ts",
32
+ "import": "./dist/telemetry.mjs",
33
+ "require": "./dist/telemetry.cjs"
34
+ },
35
+ "./usage": {
36
+ "types": "./dist/usage.d.ts",
37
+ "import": "./dist/usage.mjs",
38
+ "require": "./dist/usage.cjs"
39
+ },
40
+ "./support": {
41
+ "types": "./dist/support.d.ts",
42
+ "import": "./dist/support.mjs",
43
+ "require": "./dist/support.cjs"
44
+ },
45
+ "./mocks": {
46
+ "types": "./dist/mocks.d.ts",
47
+ "import": "./dist/mocks.mjs",
48
+ "require": "./dist/mocks.cjs"
49
+ },
50
+ "./db": {
51
+ "types": "./dist/db.d.ts",
52
+ "import": "./dist/db.mjs",
53
+ "require": "./dist/db.cjs"
54
+ },
55
+ "./errors": {
56
+ "types": "./dist/errors.d.ts",
57
+ "import": "./dist/errors.mjs",
58
+ "require": "./dist/errors.cjs"
59
+ },
60
+ "./checkout": {
61
+ "types": "./dist/checkout.d.ts",
62
+ "import": "./dist/checkout.mjs",
63
+ "require": "./dist/checkout.cjs"
64
+ },
65
+ "./firestore-compat": {
66
+ "types": "./dist/firestore-compat.d.ts",
67
+ "import": "./dist/firestore-compat.mjs",
68
+ "require": "./dist/firestore-compat.cjs"
69
+ },
70
+ "./react": {
71
+ "types": "./dist/react.d.ts",
72
+ "import": "./dist/react.mjs",
73
+ "require": "./dist/react.cjs"
74
+ },
75
+ "./db/react": {
76
+ "types": "./dist/db-react.d.ts",
77
+ "import": "./dist/db-react.mjs",
78
+ "require": "./dist/db-react.cjs"
79
+ },
80
+ "./webhooks": {
81
+ "types": "./dist/webhooks.d.ts",
82
+ "import": "./dist/webhooks.mjs",
83
+ "require": "./dist/webhooks.cjs"
84
+ },
85
+ "./notifications": {
86
+ "types": "./dist/notifications.d.ts",
87
+ "import": "./dist/notifications.mjs",
88
+ "require": "./dist/notifications.cjs"
89
+ },
90
+ "./ai": {
91
+ "types": "./dist/ai.d.ts",
92
+ "import": "./dist/ai.mjs",
93
+ "require": "./dist/ai.cjs"
94
+ }
95
+ },
96
+ "peerDependencies": {
97
+ "@electric-sql/pglite": "^0.4.0",
98
+ "drizzle-orm": "^0.43.0 || ^0.44.0 || ^0.45.0",
99
+ "pg": "^8.0.0",
100
+ "pg-mem": "^3.0.0",
101
+ "react": "^18.0.0 || ^19.0.0"
102
+ },
103
+ "peerDependenciesMeta": {
104
+ "@electric-sql/pglite": {
105
+ "optional": true
106
+ },
107
+ "drizzle-orm": {
108
+ "optional": true
109
+ },
110
+ "pg": {
111
+ "optional": true
112
+ },
113
+ "pg-mem": {
114
+ "optional": true
115
+ },
116
+ "react": {
117
+ "optional": true
118
+ }
119
+ },
120
+ "sideEffects": false,
121
+ "scripts": {
122
+ "build": "tsup",
123
+ "dev": "tsup --watch",
124
+ "test": "vitest run",
125
+ "lint": "tsc --noEmit",
126
+ "docs:gen": "typedoc --options scripts/typedoc.config.json"
127
+ },
128
+ "files": [
129
+ "dist",
130
+ "README.md",
131
+ "CHANGELOG.md"
132
+ ],
133
+ "engines": {
134
+ "node": ">=20"
135
+ },
136
+ "license": "UNLICENSED",
137
+ "devDependencies": {
138
+ "@electric-sql/pglite": "^0.4.6",
139
+ "@testing-library/jest-dom": "^6.9.1",
140
+ "@testing-library/react": "^16.3.2",
141
+ "@types/pg": "^8.11.10",
142
+ "@types/react": "^19.2.15",
143
+ "@types/react-dom": "^19.2.3",
144
+ "@vitest/browser": "^4.1.7",
145
+ "drizzle-orm": "^0.43.1",
146
+ "fake-indexeddb": "^6.2.5",
147
+ "jsdom": "^29.1.1",
148
+ "pg": "^8.15.6",
149
+ "pg-mem": "^3.0.5",
150
+ "react": "^19.2.6",
151
+ "react-dom": "^19.2.6",
152
+ "tsup": "^8.3.5",
153
+ "typedoc": "^0.28.19",
154
+ "typescript": "^5.9.3",
155
+ "vitest": "^4.1.7"
156
+ },
157
+ "dependencies": {
158
+ "idb": "^8.0.3",
159
+ "jose": "^6.2.3"
160
+ }
161
+ }