@neetru/sdk 3.9.0 → 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.
- package/CHANGELOG.md +13 -0
- package/README.md +10 -0
- package/dist/ai.cjs +1 -1
- package/dist/ai.mjs +1 -1
- package/dist/auth.cjs +1 -1
- package/dist/auth.mjs +1 -1
- package/dist/build-guard.cjs +186 -82
- package/dist/build-guard.d.cts +53 -1
- package/dist/build-guard.d.ts +53 -1
- package/dist/build-guard.mjs +175 -74
- package/dist/catalog.cjs +1 -1
- package/dist/catalog.mjs +1 -1
- package/dist/checkout.cjs +1 -1
- package/dist/checkout.mjs +1 -1
- package/dist/db.cjs +1 -1
- package/dist/db.mjs +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +2 -2
- package/dist/notifications.cjs +1 -1
- package/dist/notifications.mjs +1 -1
- package/dist/support.cjs +1 -1
- package/dist/support.mjs +1 -1
- package/dist/telemetry.cjs +1 -1
- package/dist/telemetry.mjs +1 -1
- package/dist/usage.cjs +1 -1
- package/dist/usage.mjs +1 -1
- package/dist/webhooks.cjs +1 -1
- package/dist/webhooks.mjs +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,19 @@ 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
|
+
|
|
10
23
|
## [3.9.0] — 2026-10-11 (signOut deixa de falhar em silêncio)
|
|
11
24
|
|
|
12
25
|
> **Por que MINOR e não PATCH.** O conteúdo é conserto de defeito, mas o tipo
|
package/README.md
CHANGED
|
@@ -175,6 +175,16 @@ Grava `.next/neetru-build-manifest.json` com o `NEXT_PUBLIC_NEETRU_ENV`/`_PRODUC
|
|
|
175
175
|
|
|
176
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.
|
|
177
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
|
+
|
|
178
188
|
## Exemplos por namespace
|
|
179
189
|
|
|
180
190
|
### Login OIDC — Authorization Code + PKCE (3.1.3)
|
package/dist/ai.cjs
CHANGED
package/dist/ai.mjs
CHANGED
package/dist/auth.cjs
CHANGED
package/dist/auth.mjs
CHANGED
package/dist/build-guard.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
3
|
+
var a = require('fs');
|
|
4
|
+
var l = require('path');
|
|
5
5
|
|
|
6
6
|
function _interopNamespace(e) {
|
|
7
7
|
if (e && e.__esModule) return e;
|
|
@@ -21,160 +21,264 @@ function _interopNamespace(e) {
|
|
|
21
21
|
return Object.freeze(n);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
var u__namespace = /*#__PURE__*/_interopNamespace(u);
|
|
25
24
|
var a__namespace = /*#__PURE__*/_interopNamespace(a);
|
|
25
|
+
var l__namespace = /*#__PURE__*/_interopNamespace(l);
|
|
26
26
|
|
|
27
27
|
// src/build-guard.ts
|
|
28
|
-
var
|
|
29
|
-
constructor(
|
|
30
|
-
super(
|
|
28
|
+
var p = class extends Error {
|
|
29
|
+
constructor(t) {
|
|
30
|
+
super(t), this.name = "NeetruBuildGuardError";
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
|
-
function
|
|
33
|
+
function g(e) {
|
|
34
34
|
return e == null || e.trim() === "";
|
|
35
35
|
}
|
|
36
36
|
function k(e) {
|
|
37
37
|
if (e.builtEnv !== "prod") return;
|
|
38
|
-
let
|
|
39
|
-
if (
|
|
40
|
-
let
|
|
41
|
-
throw new
|
|
38
|
+
let t = [];
|
|
39
|
+
if (g(e.oidcClientId) && t.push("NEXT_PUBLIC_NEETRU_OIDC_CLIENT_ID"), g(e.productId) && t.push("NEXT_PUBLIC_NEETRU_PRODUCT_ID"), t.length === 0) return;
|
|
40
|
+
let n = t.length > 1;
|
|
41
|
+
throw new p(
|
|
42
42
|
[
|
|
43
43
|
"[neetru-sdk] BUILD DE PRODU\xC7\xC3O ABORTADO (withNeetruBuildGuard).",
|
|
44
44
|
"",
|
|
45
|
-
`Vari\xE1ve${
|
|
46
|
-
...
|
|
45
|
+
`Vari\xE1ve${n ? "is" : "l"} de ambiente obrigat\xF3ri${n ? "as" : "a"} ausente${n ? "s" : ""}/vazia${n ? "s" : ""} no build de produ\xE7\xE3o (NEXT_PUBLIC_NEETRU_ENV=prod):`,
|
|
46
|
+
...t.map((r) => ` \u2022 ${r}`),
|
|
47
47
|
"",
|
|
48
|
-
`Sem ${
|
|
48
|
+
`Sem ${n ? "essas vari\xE1veis" : "essa vari\xE1vel"} o SDK n\xE3o consegue montar o client_id do login OIDC \u2014 o bot\xE3o "Entrar com Neetru" (NeetruLoginButton) N\xC3O redireciona e o login do produto quebra EM SIL\xCANCIO em produ\xE7\xE3o (incidente gestovendas 2026-09-06: workspace recriado perdeu a env var e shippou um build de prod com o client_id vazio).`,
|
|
49
49
|
"",
|
|
50
50
|
"Como corrigir \u2014 defina no .env.production do produto (ou no ambiente do build de deploy):",
|
|
51
|
-
...
|
|
51
|
+
...t.map((r) => ` ${r}=<valor real vindo do cat\xE1logo do produto no Core>`),
|
|
52
52
|
"",
|
|
53
53
|
"dev/workspace N\xC3O exigem essas vari\xE1veis (usam MockAuth/sandbox) \u2014 s\xF3 o build de produ\xE7\xE3o enfor\xE7a."
|
|
54
54
|
].join(`
|
|
55
55
|
`)
|
|
56
56
|
);
|
|
57
57
|
}
|
|
58
|
-
var
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
var w = [
|
|
59
|
+
"script-src-elem",
|
|
60
|
+
"script-src",
|
|
61
|
+
"default-src"
|
|
62
|
+
], E = /^\/(?:api|_next)(?:\/|$)/, m = /^'sha(?:256|384|512)-/;
|
|
63
|
+
function N(e) {
|
|
64
|
+
let t = /* @__PURE__ */ new Map();
|
|
65
|
+
for (let n of e.split(";")) {
|
|
66
|
+
let r = n.trim().split(/\s+/).filter(Boolean);
|
|
67
|
+
if (r.length === 0) continue;
|
|
68
|
+
let o = r[0].toLowerCase();
|
|
69
|
+
t.has(o) || t.set(o, { raw: r.join(" "), sources: r.slice(1) });
|
|
70
|
+
}
|
|
71
|
+
return t;
|
|
72
|
+
}
|
|
73
|
+
function I(e, t) {
|
|
74
|
+
let n = t.filter((o) => {
|
|
75
|
+
let s = o.toLowerCase();
|
|
76
|
+
return s !== "'none'" && !m.test(s);
|
|
77
|
+
});
|
|
78
|
+
return n.some((o) => o.toLowerCase() === "'unsafe-inline'") || n.push("'unsafe-inline'"), n.length === 1 && n.unshift("'self'"), `${e === "default-src" ? "script-src" : e} ${n.join(" ")}`;
|
|
79
|
+
}
|
|
80
|
+
function C(e) {
|
|
81
|
+
let t = N(e), n = w.find((c) => t.has(c));
|
|
82
|
+
if (!n) return null;
|
|
83
|
+
let { raw: r, sources: o } = t.get(n), s = o.map((c) => c.toLowerCase());
|
|
84
|
+
if (s.some((c) => c.startsWith("'nonce-")) || s.includes("'strict-dynamic'")) return null;
|
|
85
|
+
let i = s.includes("'unsafe-inline'"), u = s.some((c) => m.test(c));
|
|
86
|
+
return i && !u ? null : {
|
|
87
|
+
directiveName: n,
|
|
88
|
+
directive: r,
|
|
89
|
+
suggestion: I(n, o),
|
|
90
|
+
unsafeInlineIgnoredByHash: i && u
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function S(e) {
|
|
94
|
+
if (!Array.isArray(e)) return [];
|
|
95
|
+
let t = [];
|
|
96
|
+
for (let n of e) {
|
|
97
|
+
if (!n || typeof n != "object") continue;
|
|
98
|
+
let { source: r, headers: o } = n, s = typeof r == "string" ? r : "";
|
|
99
|
+
if (!E.test(s) && Array.isArray(o))
|
|
100
|
+
for (let i of o) {
|
|
101
|
+
if (!i || typeof i != "object") continue;
|
|
102
|
+
let { key: u, value: c } = i;
|
|
103
|
+
if (!(typeof u != "string" || typeof c != "string") && u.trim().toLowerCase() === "content-security-policy")
|
|
104
|
+
for (let d of c.split(",")) {
|
|
105
|
+
let f = C(d);
|
|
106
|
+
f && t.push({ source: s, headerKey: u.trim(), ...f });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return t;
|
|
111
|
+
}
|
|
112
|
+
function _(e) {
|
|
113
|
+
if (typeof e != "string" || e.trim() === "") return false;
|
|
114
|
+
try {
|
|
115
|
+
return a__namespace.existsSync(l__namespace.join(e, "app")) || a__namespace.existsSync(l__namespace.join(e, "src", "app"));
|
|
116
|
+
} catch {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function b(e) {
|
|
121
|
+
let t = S(e);
|
|
122
|
+
if (t.length === 0) return;
|
|
123
|
+
let n = [
|
|
124
|
+
"[neetru-sdk] BUILD ABORTADO (withNeetruBuildGuard): a Content-Security-Policy do headers() do next.config bloqueia os scripts embutidos do App Router.",
|
|
125
|
+
"",
|
|
126
|
+
"O App Router p\xF5e <script> embutidos em toda p\xE1gina (self.__next_f.push, com o payload do React Server Components). Com a CSP abaixo o navegador bloqueia esses scripts, a hidrata\xE7\xE3o falha e o React desmonta a \xE1rvore: o servidor responde 200 com o HTML certo e a tela fica EM BRANCO (incidente Zelo 2026-10-22).",
|
|
127
|
+
"",
|
|
128
|
+
`Linha${t.length > 1 ? "s" : ""} a trocar no next.config:`
|
|
129
|
+
];
|
|
130
|
+
throw t.forEach((r, o) => {
|
|
131
|
+
n.push(""), n.push(`${o + 1}) headers() \u2192 source "${r.source}" \u2192 ${r.headerKey}`), r.directiveName === "default-src" ? (n.push(` a CSP n\xE3o tem script-src, ent\xE3o quem decide os scripts \xE9 o: ${r.directive}`), n.push(` acrescente: ${r.suggestion}`)) : (n.push(` troque: ${r.directive}`), n.push(` por: ${r.suggestion}`), r.unsafeInlineIgnoredByHash && n.push(" (com um hash 'sha\u2026-' na lista, o navegador ignora o 'unsafe-inline' \u2014 por isso o hash sai)"));
|
|
132
|
+
}), n.push(
|
|
133
|
+
"",
|
|
134
|
+
"Sem 'unsafe-inline': use nonce por requisi\xE7\xE3o \u2014 o middleware gera o nonce e manda a CSP com 'nonce-<valor>' 'strict-dynamic' (https://nextjs.org/docs/app/guides/content-security-policy). CSP com nonce ou 'strict-dynamic' passa nesta checagem."
|
|
135
|
+
), new p(n.join(`
|
|
136
|
+
`));
|
|
137
|
+
}
|
|
138
|
+
function R(e) {
|
|
139
|
+
if (_(process.cwd()))
|
|
140
|
+
try {
|
|
141
|
+
b(e);
|
|
142
|
+
} catch (t) {
|
|
143
|
+
if (t instanceof p && process.env.NODE_ENV === "development") {
|
|
144
|
+
typeof console < "u" && console.warn(t.message);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
throw t;
|
|
148
|
+
}
|
|
61
149
|
}
|
|
62
|
-
|
|
63
|
-
|
|
150
|
+
var y = ["pg", "drizzle-orm"], h = "*";
|
|
151
|
+
function v(e) {
|
|
152
|
+
return Array.isArray(e) ? e.filter((t) => typeof t == "string") : [];
|
|
153
|
+
}
|
|
154
|
+
function T(e, t, n) {
|
|
155
|
+
let r = [], o = t;
|
|
64
156
|
for (; ; ) {
|
|
65
157
|
r.push(o);
|
|
66
|
-
let
|
|
67
|
-
if (
|
|
68
|
-
o =
|
|
158
|
+
let s = l__namespace.dirname(o);
|
|
159
|
+
if (s === o) break;
|
|
160
|
+
o = s;
|
|
69
161
|
}
|
|
70
|
-
r.includes(
|
|
71
|
-
for (let
|
|
72
|
-
let
|
|
162
|
+
r.includes(n) || r.push(n);
|
|
163
|
+
for (let s of r) {
|
|
164
|
+
let i = l__namespace.join(s, "node_modules", e, "package.json");
|
|
73
165
|
try {
|
|
74
|
-
if (
|
|
166
|
+
if (a__namespace.existsSync(i)) return i;
|
|
75
167
|
} catch {
|
|
76
168
|
}
|
|
77
169
|
}
|
|
78
170
|
return null;
|
|
79
171
|
}
|
|
80
|
-
function
|
|
172
|
+
function B(e) {
|
|
81
173
|
if (typeof e != "string" || e.trim() === "") return [];
|
|
82
|
-
let
|
|
83
|
-
if (
|
|
84
|
-
n.add(o);
|
|
85
|
-
let s = _(o, i, e);
|
|
86
|
-
if (!s) return;
|
|
174
|
+
let t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), r = (o, s) => {
|
|
175
|
+
if (t.has(o)) return;
|
|
87
176
|
t.add(o);
|
|
88
|
-
let
|
|
177
|
+
let i = T(o, s, e);
|
|
178
|
+
if (!i) return;
|
|
179
|
+
n.add(o);
|
|
180
|
+
let u;
|
|
89
181
|
try {
|
|
90
|
-
|
|
182
|
+
u = JSON.parse(a__namespace.readFileSync(i, "utf8"));
|
|
91
183
|
} catch {
|
|
92
184
|
return;
|
|
93
185
|
}
|
|
94
186
|
let c = {
|
|
95
|
-
...
|
|
96
|
-
...
|
|
97
|
-
},
|
|
98
|
-
for (let
|
|
187
|
+
...u.dependencies ?? {},
|
|
188
|
+
...u.optionalDependencies ?? {}
|
|
189
|
+
}, d = l__namespace.dirname(i);
|
|
190
|
+
for (let f of Object.keys(c)) r(f, d);
|
|
99
191
|
};
|
|
100
192
|
try {
|
|
101
|
-
for (let o of
|
|
193
|
+
for (let o of y) r(o, e);
|
|
102
194
|
} catch {
|
|
103
195
|
return [];
|
|
104
196
|
}
|
|
105
|
-
return [...
|
|
197
|
+
return [...n].sort();
|
|
106
198
|
}
|
|
107
|
-
function
|
|
108
|
-
return e.map((
|
|
199
|
+
function x(e) {
|
|
200
|
+
return e.map((t) => `./node_modules/${t}/**`);
|
|
109
201
|
}
|
|
110
|
-
function
|
|
111
|
-
let
|
|
112
|
-
for (let
|
|
113
|
-
|
|
114
|
-
return
|
|
202
|
+
function A(e) {
|
|
203
|
+
let t = v(e);
|
|
204
|
+
for (let n of y)
|
|
205
|
+
t.includes(n) || t.push(n);
|
|
206
|
+
return t;
|
|
115
207
|
}
|
|
116
|
-
function
|
|
117
|
-
let
|
|
208
|
+
function O(e, t) {
|
|
209
|
+
let n = {};
|
|
118
210
|
if (e && typeof e == "object" && !Array.isArray(e))
|
|
119
|
-
for (let [o,
|
|
120
|
-
|
|
121
|
-
if (
|
|
122
|
-
let r = [...
|
|
123
|
-
for (let o of
|
|
211
|
+
for (let [o, s] of Object.entries(e))
|
|
212
|
+
n[o] = v(s);
|
|
213
|
+
if (t.length === 0) return n;
|
|
214
|
+
let r = [...n[h] ?? []];
|
|
215
|
+
for (let o of t)
|
|
124
216
|
r.includes(o) || r.push(o);
|
|
125
|
-
return
|
|
217
|
+
return n[h] = r, n;
|
|
126
218
|
}
|
|
127
|
-
function
|
|
128
|
-
let
|
|
219
|
+
function P(e, t = {}) {
|
|
220
|
+
let n = e.webpack, r = e.headers, o = [];
|
|
129
221
|
try {
|
|
130
|
-
|
|
222
|
+
o = x(B(process.cwd()));
|
|
131
223
|
} catch {
|
|
132
|
-
|
|
224
|
+
o = [];
|
|
133
225
|
}
|
|
134
226
|
return {
|
|
135
227
|
...e,
|
|
136
228
|
// `serverExternalPackages` é reforço (não o conserto do caso webpackIgnore);
|
|
137
229
|
// o `outputFileTracingIncludes` computado é o que realmente inclui o closure.
|
|
138
|
-
serverExternalPackages:
|
|
139
|
-
outputFileTracingIncludes:
|
|
230
|
+
serverExternalPackages: A(e.serverExternalPackages),
|
|
231
|
+
outputFileTracingIncludes: O(
|
|
140
232
|
e.outputFileTracingIncludes,
|
|
141
|
-
|
|
233
|
+
o
|
|
142
234
|
),
|
|
143
|
-
|
|
144
|
-
|
|
235
|
+
// CSP x App Router (incidente Zelo 2026-10-22): só embrulha quando o produto
|
|
236
|
+
// TEM `headers()`. Sem ele não há CSP do next.config a checar, e o config
|
|
237
|
+
// continua sem a chave (não inventa um `headers` que o Next não pediu).
|
|
238
|
+
...typeof r == "function" ? {
|
|
239
|
+
async headers(...s) {
|
|
240
|
+
let i = await r.apply(this, s);
|
|
241
|
+
return R(i), i;
|
|
242
|
+
}
|
|
243
|
+
} : {},
|
|
244
|
+
webpack(s, i) {
|
|
245
|
+
let u = typeof n == "function" ? n(s, i) : s;
|
|
145
246
|
if (!i.dev && i.isServer) {
|
|
146
|
-
let
|
|
247
|
+
let c = {
|
|
147
248
|
builtEnv: process.env.NEXT_PUBLIC_NEETRU_ENV ?? null,
|
|
148
249
|
productId: process.env.NEXT_PUBLIC_NEETRU_PRODUCT_ID ?? null,
|
|
149
250
|
oidcClientId: process.env.NEXT_PUBLIC_NEETRU_OIDC_CLIENT_ID ?? null,
|
|
150
251
|
builtAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
151
252
|
};
|
|
152
253
|
try {
|
|
153
|
-
let
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
JSON.stringify(
|
|
254
|
+
let d = l__namespace.resolve(process.cwd(), t.outputDir ?? ".next");
|
|
255
|
+
a__namespace.mkdirSync(d, { recursive: !0 }), a__namespace.writeFileSync(
|
|
256
|
+
l__namespace.join(d, "neetru-build-manifest.json"),
|
|
257
|
+
JSON.stringify(c, null, 2),
|
|
157
258
|
"utf8"
|
|
158
259
|
);
|
|
159
|
-
} catch (
|
|
260
|
+
} catch (d) {
|
|
160
261
|
typeof console < "u" && console.warn(
|
|
161
262
|
"[neetru-sdk] withNeetruBuildGuard: falha ao gravar neetru-build-manifest.json (ignorado, build segue):",
|
|
162
|
-
|
|
263
|
+
d
|
|
163
264
|
);
|
|
164
265
|
}
|
|
165
|
-
k(
|
|
266
|
+
k(c);
|
|
166
267
|
}
|
|
167
|
-
return
|
|
268
|
+
return u;
|
|
168
269
|
}
|
|
169
270
|
};
|
|
170
271
|
}
|
|
171
272
|
|
|
172
|
-
exports.NEETRU_SQL_SERVER_EXTERNAL_PACKAGES =
|
|
173
|
-
exports.NEETRU_SQL_TRACE_INCLUDE_KEY =
|
|
174
|
-
exports.NeetruBuildGuardError =
|
|
273
|
+
exports.NEETRU_SQL_SERVER_EXTERNAL_PACKAGES = y;
|
|
274
|
+
exports.NEETRU_SQL_TRACE_INCLUDE_KEY = h;
|
|
275
|
+
exports.NeetruBuildGuardError = p;
|
|
276
|
+
exports.assertNeetruCspAllowsAppRouterScripts = b;
|
|
175
277
|
exports.assertNeetruProdBuildEnv = k;
|
|
176
|
-
exports.
|
|
177
|
-
exports.
|
|
178
|
-
exports.
|
|
179
|
-
exports.
|
|
180
|
-
exports.
|
|
278
|
+
exports.findCspInlineScriptBlocks = S;
|
|
279
|
+
exports.hasNextAppRouter = _;
|
|
280
|
+
exports.mergeOutputFileTracingIncludes = O;
|
|
281
|
+
exports.mergeServerExternalPackages = A;
|
|
282
|
+
exports.resolveSqlRuntimeClosure = B;
|
|
283
|
+
exports.sqlClosureToTraceGlobs = x;
|
|
284
|
+
exports.withNeetruBuildGuard = P;
|
package/dist/build-guard.d.cts
CHANGED
|
@@ -36,6 +36,57 @@ declare class NeetruBuildGuardError extends Error {
|
|
|
36
36
|
* reprova; retorna `void` quando passa.
|
|
37
37
|
*/
|
|
38
38
|
declare function assertNeetruProdBuildEnv(resolved: Pick<NeetruBuildManifest, 'builtEnv' | 'productId' | 'oidcClientId'>): void;
|
|
39
|
+
/**
|
|
40
|
+
* Uma regra de `headers()` do `next.config` (`{ source, headers: [{ key, value }] }`).
|
|
41
|
+
* Tipada frouxa de propósito: é config de produto, pode vir malformada, e quem
|
|
42
|
+
* valida o formato é o próprio Next logo depois. O guard só lê.
|
|
43
|
+
*/
|
|
44
|
+
interface NeetruHeaderRule {
|
|
45
|
+
source?: unknown;
|
|
46
|
+
headers?: unknown;
|
|
47
|
+
[key: string]: unknown;
|
|
48
|
+
}
|
|
49
|
+
/** Diretivas que decidem um `<script>` embutido, na ordem de precedência da CSP. */
|
|
50
|
+
type InlineScriptDirectiveName = 'script-src-elem' | 'script-src' | 'default-src';
|
|
51
|
+
/** Uma CSP de `headers()` que bloqueia os `<script>` embutidos do App Router. */
|
|
52
|
+
interface NeetruCspInlineScriptBlock {
|
|
53
|
+
/** `source` da regra de `headers()` (ex.: `'/(.*)'`). */
|
|
54
|
+
source: string;
|
|
55
|
+
/** Nome do header como o produto escreveu (ex.: `'Content-Security-Policy'`). */
|
|
56
|
+
headerKey: string;
|
|
57
|
+
/** Diretiva efetiva para `<script>` embutido. `default-src` = a CSP não tem `script-src`. */
|
|
58
|
+
directiveName: InlineScriptDirectiveName;
|
|
59
|
+
/** A diretiva como está na CSP, espaços normalizados (ex.: `"script-src 'self'"`). */
|
|
60
|
+
directive: string;
|
|
61
|
+
/** Linha que resolve, pronta pra colar (ex.: `"script-src 'self' 'unsafe-inline'"`). */
|
|
62
|
+
suggestion: string;
|
|
63
|
+
/** `true` quando há `'unsafe-inline'`, mas um hash `'sha…-'` na lista faz o navegador ignorá-lo. */
|
|
64
|
+
unsafeInlineIgnoredByHash: boolean;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Checagem pura (sem I/O): lista cada `Content-Security-Policy` do retorno de
|
|
68
|
+
* `headers()` que bloqueia os `<script>` embutidos do App Router. Lista vazia =
|
|
69
|
+
* nada a reprovar. Nunca lança — entrada malformada é ignorada (o Next valida).
|
|
70
|
+
*
|
|
71
|
+
* - Só `Content-Security-Policy` (sem diferença de maiúscula). `…-Report-Only`
|
|
72
|
+
* não bloqueia nada e fica de fora.
|
|
73
|
+
* - Valor com vírgula = várias políticas no mesmo header; TODAS valem no
|
|
74
|
+
* navegador, então cada uma é checada.
|
|
75
|
+
* - Regras de `/api` e `/_next` ficam de fora (não servem página).
|
|
76
|
+
*/
|
|
77
|
+
declare function findCspInlineScriptBlocks(rules: unknown): NeetruCspInlineScriptBlock[];
|
|
78
|
+
/**
|
|
79
|
+
* App Router presente? Mesma regra do `findPagesDir` do Next: pasta `app/` na
|
|
80
|
+
* raiz do projeto, ou `src/app/`. Só Pages Router → `false` (ali o Next não põe
|
|
81
|
+
* script EXECUTÁVEL embutido — o `__NEXT_DATA__` é `type="application/json"`).
|
|
82
|
+
*/
|
|
83
|
+
declare function hasNextAppRouter(projectDir: string): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Lança `NeetruBuildGuardError` se alguma CSP de `headers()` bloquear os
|
|
86
|
+
* `<script>` embutidos do App Router, com a linha a trocar de cada uma. Não
|
|
87
|
+
* olha se o app TEM App Router — isso é do `withNeetruBuildGuard`.
|
|
88
|
+
*/
|
|
89
|
+
declare function assertNeetruCspAllowsAppRouterScripts(rules: unknown): void;
|
|
39
90
|
/**
|
|
40
91
|
* Formato mínimo de `next.config.mjs` que o wrapper precisa entender — só
|
|
41
92
|
* o suficiente pra compor a chave `webpack` sem acoplar o SDK ao pacote
|
|
@@ -49,6 +100,7 @@ type MinimalWebpackContext = {
|
|
|
49
100
|
};
|
|
50
101
|
type MinimalNextConfig = Record<string, unknown> & {
|
|
51
102
|
webpack?: (config: unknown, context: MinimalWebpackContext) => unknown;
|
|
103
|
+
headers?: (...args: unknown[]) => unknown;
|
|
52
104
|
serverExternalPackages?: string[];
|
|
53
105
|
outputFileTracingIncludes?: Record<string, string[]>;
|
|
54
106
|
};
|
|
@@ -114,4 +166,4 @@ declare function mergeServerExternalPackages(existing: unknown): string[];
|
|
|
114
166
|
declare function mergeOutputFileTracingIncludes(existing: unknown, globs: readonly string[]): Record<string, string[]>;
|
|
115
167
|
declare function withNeetruBuildGuard<T extends MinimalNextConfig>(nextConfig: T, options?: WithNeetruBuildGuardOptions): T;
|
|
116
168
|
|
|
117
|
-
export { NEETRU_SQL_SERVER_EXTERNAL_PACKAGES, NEETRU_SQL_TRACE_INCLUDE_KEY, NeetruBuildGuardError, type NeetruBuildManifest, type WithNeetruBuildGuardOptions, assertNeetruProdBuildEnv, mergeOutputFileTracingIncludes, mergeServerExternalPackages, resolveSqlRuntimeClosure, sqlClosureToTraceGlobs, withNeetruBuildGuard };
|
|
169
|
+
export { NEETRU_SQL_SERVER_EXTERNAL_PACKAGES, NEETRU_SQL_TRACE_INCLUDE_KEY, NeetruBuildGuardError, type NeetruBuildManifest, type NeetruCspInlineScriptBlock, type NeetruHeaderRule, type WithNeetruBuildGuardOptions, assertNeetruCspAllowsAppRouterScripts, assertNeetruProdBuildEnv, findCspInlineScriptBlocks, hasNextAppRouter, mergeOutputFileTracingIncludes, mergeServerExternalPackages, resolveSqlRuntimeClosure, sqlClosureToTraceGlobs, withNeetruBuildGuard };
|
package/dist/build-guard.d.ts
CHANGED
|
@@ -36,6 +36,57 @@ declare class NeetruBuildGuardError extends Error {
|
|
|
36
36
|
* reprova; retorna `void` quando passa.
|
|
37
37
|
*/
|
|
38
38
|
declare function assertNeetruProdBuildEnv(resolved: Pick<NeetruBuildManifest, 'builtEnv' | 'productId' | 'oidcClientId'>): void;
|
|
39
|
+
/**
|
|
40
|
+
* Uma regra de `headers()` do `next.config` (`{ source, headers: [{ key, value }] }`).
|
|
41
|
+
* Tipada frouxa de propósito: é config de produto, pode vir malformada, e quem
|
|
42
|
+
* valida o formato é o próprio Next logo depois. O guard só lê.
|
|
43
|
+
*/
|
|
44
|
+
interface NeetruHeaderRule {
|
|
45
|
+
source?: unknown;
|
|
46
|
+
headers?: unknown;
|
|
47
|
+
[key: string]: unknown;
|
|
48
|
+
}
|
|
49
|
+
/** Diretivas que decidem um `<script>` embutido, na ordem de precedência da CSP. */
|
|
50
|
+
type InlineScriptDirectiveName = 'script-src-elem' | 'script-src' | 'default-src';
|
|
51
|
+
/** Uma CSP de `headers()` que bloqueia os `<script>` embutidos do App Router. */
|
|
52
|
+
interface NeetruCspInlineScriptBlock {
|
|
53
|
+
/** `source` da regra de `headers()` (ex.: `'/(.*)'`). */
|
|
54
|
+
source: string;
|
|
55
|
+
/** Nome do header como o produto escreveu (ex.: `'Content-Security-Policy'`). */
|
|
56
|
+
headerKey: string;
|
|
57
|
+
/** Diretiva efetiva para `<script>` embutido. `default-src` = a CSP não tem `script-src`. */
|
|
58
|
+
directiveName: InlineScriptDirectiveName;
|
|
59
|
+
/** A diretiva como está na CSP, espaços normalizados (ex.: `"script-src 'self'"`). */
|
|
60
|
+
directive: string;
|
|
61
|
+
/** Linha que resolve, pronta pra colar (ex.: `"script-src 'self' 'unsafe-inline'"`). */
|
|
62
|
+
suggestion: string;
|
|
63
|
+
/** `true` quando há `'unsafe-inline'`, mas um hash `'sha…-'` na lista faz o navegador ignorá-lo. */
|
|
64
|
+
unsafeInlineIgnoredByHash: boolean;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Checagem pura (sem I/O): lista cada `Content-Security-Policy` do retorno de
|
|
68
|
+
* `headers()` que bloqueia os `<script>` embutidos do App Router. Lista vazia =
|
|
69
|
+
* nada a reprovar. Nunca lança — entrada malformada é ignorada (o Next valida).
|
|
70
|
+
*
|
|
71
|
+
* - Só `Content-Security-Policy` (sem diferença de maiúscula). `…-Report-Only`
|
|
72
|
+
* não bloqueia nada e fica de fora.
|
|
73
|
+
* - Valor com vírgula = várias políticas no mesmo header; TODAS valem no
|
|
74
|
+
* navegador, então cada uma é checada.
|
|
75
|
+
* - Regras de `/api` e `/_next` ficam de fora (não servem página).
|
|
76
|
+
*/
|
|
77
|
+
declare function findCspInlineScriptBlocks(rules: unknown): NeetruCspInlineScriptBlock[];
|
|
78
|
+
/**
|
|
79
|
+
* App Router presente? Mesma regra do `findPagesDir` do Next: pasta `app/` na
|
|
80
|
+
* raiz do projeto, ou `src/app/`. Só Pages Router → `false` (ali o Next não põe
|
|
81
|
+
* script EXECUTÁVEL embutido — o `__NEXT_DATA__` é `type="application/json"`).
|
|
82
|
+
*/
|
|
83
|
+
declare function hasNextAppRouter(projectDir: string): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Lança `NeetruBuildGuardError` se alguma CSP de `headers()` bloquear os
|
|
86
|
+
* `<script>` embutidos do App Router, com a linha a trocar de cada uma. Não
|
|
87
|
+
* olha se o app TEM App Router — isso é do `withNeetruBuildGuard`.
|
|
88
|
+
*/
|
|
89
|
+
declare function assertNeetruCspAllowsAppRouterScripts(rules: unknown): void;
|
|
39
90
|
/**
|
|
40
91
|
* Formato mínimo de `next.config.mjs` que o wrapper precisa entender — só
|
|
41
92
|
* o suficiente pra compor a chave `webpack` sem acoplar o SDK ao pacote
|
|
@@ -49,6 +100,7 @@ type MinimalWebpackContext = {
|
|
|
49
100
|
};
|
|
50
101
|
type MinimalNextConfig = Record<string, unknown> & {
|
|
51
102
|
webpack?: (config: unknown, context: MinimalWebpackContext) => unknown;
|
|
103
|
+
headers?: (...args: unknown[]) => unknown;
|
|
52
104
|
serverExternalPackages?: string[];
|
|
53
105
|
outputFileTracingIncludes?: Record<string, string[]>;
|
|
54
106
|
};
|
|
@@ -114,4 +166,4 @@ declare function mergeServerExternalPackages(existing: unknown): string[];
|
|
|
114
166
|
declare function mergeOutputFileTracingIncludes(existing: unknown, globs: readonly string[]): Record<string, string[]>;
|
|
115
167
|
declare function withNeetruBuildGuard<T extends MinimalNextConfig>(nextConfig: T, options?: WithNeetruBuildGuardOptions): T;
|
|
116
168
|
|
|
117
|
-
export { NEETRU_SQL_SERVER_EXTERNAL_PACKAGES, NEETRU_SQL_TRACE_INCLUDE_KEY, NeetruBuildGuardError, type NeetruBuildManifest, type WithNeetruBuildGuardOptions, assertNeetruProdBuildEnv, mergeOutputFileTracingIncludes, mergeServerExternalPackages, resolveSqlRuntimeClosure, sqlClosureToTraceGlobs, withNeetruBuildGuard };
|
|
169
|
+
export { NEETRU_SQL_SERVER_EXTERNAL_PACKAGES, NEETRU_SQL_TRACE_INCLUDE_KEY, NeetruBuildGuardError, type NeetruBuildManifest, type NeetruCspInlineScriptBlock, type NeetruHeaderRule, type WithNeetruBuildGuardOptions, assertNeetruCspAllowsAppRouterScripts, assertNeetruProdBuildEnv, findCspInlineScriptBlocks, hasNextAppRouter, mergeOutputFileTracingIncludes, mergeServerExternalPackages, resolveSqlRuntimeClosure, sqlClosureToTraceGlobs, withNeetruBuildGuard };
|
package/dist/build-guard.mjs
CHANGED
|
@@ -1,149 +1,250 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import * as
|
|
1
|
+
import * as a from 'fs';
|
|
2
|
+
import * as l from 'path';
|
|
3
3
|
|
|
4
4
|
// src/build-guard.ts
|
|
5
|
-
var
|
|
6
|
-
constructor(
|
|
7
|
-
super(
|
|
5
|
+
var p = class extends Error {
|
|
6
|
+
constructor(t) {
|
|
7
|
+
super(t), this.name = "NeetruBuildGuardError";
|
|
8
8
|
}
|
|
9
9
|
};
|
|
10
|
-
function
|
|
10
|
+
function g(e) {
|
|
11
11
|
return e == null || e.trim() === "";
|
|
12
12
|
}
|
|
13
13
|
function k(e) {
|
|
14
14
|
if (e.builtEnv !== "prod") return;
|
|
15
|
-
let
|
|
16
|
-
if (
|
|
17
|
-
let
|
|
18
|
-
throw new
|
|
15
|
+
let t = [];
|
|
16
|
+
if (g(e.oidcClientId) && t.push("NEXT_PUBLIC_NEETRU_OIDC_CLIENT_ID"), g(e.productId) && t.push("NEXT_PUBLIC_NEETRU_PRODUCT_ID"), t.length === 0) return;
|
|
17
|
+
let n = t.length > 1;
|
|
18
|
+
throw new p(
|
|
19
19
|
[
|
|
20
20
|
"[neetru-sdk] BUILD DE PRODU\xC7\xC3O ABORTADO (withNeetruBuildGuard).",
|
|
21
21
|
"",
|
|
22
|
-
`Vari\xE1ve${
|
|
23
|
-
...
|
|
22
|
+
`Vari\xE1ve${n ? "is" : "l"} de ambiente obrigat\xF3ri${n ? "as" : "a"} ausente${n ? "s" : ""}/vazia${n ? "s" : ""} no build de produ\xE7\xE3o (NEXT_PUBLIC_NEETRU_ENV=prod):`,
|
|
23
|
+
...t.map((r) => ` \u2022 ${r}`),
|
|
24
24
|
"",
|
|
25
|
-
`Sem ${
|
|
25
|
+
`Sem ${n ? "essas vari\xE1veis" : "essa vari\xE1vel"} o SDK n\xE3o consegue montar o client_id do login OIDC \u2014 o bot\xE3o "Entrar com Neetru" (NeetruLoginButton) N\xC3O redireciona e o login do produto quebra EM SIL\xCANCIO em produ\xE7\xE3o (incidente gestovendas 2026-09-06: workspace recriado perdeu a env var e shippou um build de prod com o client_id vazio).`,
|
|
26
26
|
"",
|
|
27
27
|
"Como corrigir \u2014 defina no .env.production do produto (ou no ambiente do build de deploy):",
|
|
28
|
-
...
|
|
28
|
+
...t.map((r) => ` ${r}=<valor real vindo do cat\xE1logo do produto no Core>`),
|
|
29
29
|
"",
|
|
30
30
|
"dev/workspace N\xC3O exigem essas vari\xE1veis (usam MockAuth/sandbox) \u2014 s\xF3 o build de produ\xE7\xE3o enfor\xE7a."
|
|
31
31
|
].join(`
|
|
32
32
|
`)
|
|
33
33
|
);
|
|
34
34
|
}
|
|
35
|
-
var
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
var w = [
|
|
36
|
+
"script-src-elem",
|
|
37
|
+
"script-src",
|
|
38
|
+
"default-src"
|
|
39
|
+
], E = /^\/(?:api|_next)(?:\/|$)/, m = /^'sha(?:256|384|512)-/;
|
|
40
|
+
function N(e) {
|
|
41
|
+
let t = /* @__PURE__ */ new Map();
|
|
42
|
+
for (let n of e.split(";")) {
|
|
43
|
+
let r = n.trim().split(/\s+/).filter(Boolean);
|
|
44
|
+
if (r.length === 0) continue;
|
|
45
|
+
let o = r[0].toLowerCase();
|
|
46
|
+
t.has(o) || t.set(o, { raw: r.join(" "), sources: r.slice(1) });
|
|
47
|
+
}
|
|
48
|
+
return t;
|
|
49
|
+
}
|
|
50
|
+
function I(e, t) {
|
|
51
|
+
let n = t.filter((o) => {
|
|
52
|
+
let s = o.toLowerCase();
|
|
53
|
+
return s !== "'none'" && !m.test(s);
|
|
54
|
+
});
|
|
55
|
+
return n.some((o) => o.toLowerCase() === "'unsafe-inline'") || n.push("'unsafe-inline'"), n.length === 1 && n.unshift("'self'"), `${e === "default-src" ? "script-src" : e} ${n.join(" ")}`;
|
|
56
|
+
}
|
|
57
|
+
function C(e) {
|
|
58
|
+
let t = N(e), n = w.find((c) => t.has(c));
|
|
59
|
+
if (!n) return null;
|
|
60
|
+
let { raw: r, sources: o } = t.get(n), s = o.map((c) => c.toLowerCase());
|
|
61
|
+
if (s.some((c) => c.startsWith("'nonce-")) || s.includes("'strict-dynamic'")) return null;
|
|
62
|
+
let i = s.includes("'unsafe-inline'"), u = s.some((c) => m.test(c));
|
|
63
|
+
return i && !u ? null : {
|
|
64
|
+
directiveName: n,
|
|
65
|
+
directive: r,
|
|
66
|
+
suggestion: I(n, o),
|
|
67
|
+
unsafeInlineIgnoredByHash: i && u
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function S(e) {
|
|
71
|
+
if (!Array.isArray(e)) return [];
|
|
72
|
+
let t = [];
|
|
73
|
+
for (let n of e) {
|
|
74
|
+
if (!n || typeof n != "object") continue;
|
|
75
|
+
let { source: r, headers: o } = n, s = typeof r == "string" ? r : "";
|
|
76
|
+
if (!E.test(s) && Array.isArray(o))
|
|
77
|
+
for (let i of o) {
|
|
78
|
+
if (!i || typeof i != "object") continue;
|
|
79
|
+
let { key: u, value: c } = i;
|
|
80
|
+
if (!(typeof u != "string" || typeof c != "string") && u.trim().toLowerCase() === "content-security-policy")
|
|
81
|
+
for (let d of c.split(",")) {
|
|
82
|
+
let f = C(d);
|
|
83
|
+
f && t.push({ source: s, headerKey: u.trim(), ...f });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return t;
|
|
88
|
+
}
|
|
89
|
+
function _(e) {
|
|
90
|
+
if (typeof e != "string" || e.trim() === "") return false;
|
|
91
|
+
try {
|
|
92
|
+
return a.existsSync(l.join(e, "app")) || a.existsSync(l.join(e, "src", "app"));
|
|
93
|
+
} catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function b(e) {
|
|
98
|
+
let t = S(e);
|
|
99
|
+
if (t.length === 0) return;
|
|
100
|
+
let n = [
|
|
101
|
+
"[neetru-sdk] BUILD ABORTADO (withNeetruBuildGuard): a Content-Security-Policy do headers() do next.config bloqueia os scripts embutidos do App Router.",
|
|
102
|
+
"",
|
|
103
|
+
"O App Router p\xF5e <script> embutidos em toda p\xE1gina (self.__next_f.push, com o payload do React Server Components). Com a CSP abaixo o navegador bloqueia esses scripts, a hidrata\xE7\xE3o falha e o React desmonta a \xE1rvore: o servidor responde 200 com o HTML certo e a tela fica EM BRANCO (incidente Zelo 2026-10-22).",
|
|
104
|
+
"",
|
|
105
|
+
`Linha${t.length > 1 ? "s" : ""} a trocar no next.config:`
|
|
106
|
+
];
|
|
107
|
+
throw t.forEach((r, o) => {
|
|
108
|
+
n.push(""), n.push(`${o + 1}) headers() \u2192 source "${r.source}" \u2192 ${r.headerKey}`), r.directiveName === "default-src" ? (n.push(` a CSP n\xE3o tem script-src, ent\xE3o quem decide os scripts \xE9 o: ${r.directive}`), n.push(` acrescente: ${r.suggestion}`)) : (n.push(` troque: ${r.directive}`), n.push(` por: ${r.suggestion}`), r.unsafeInlineIgnoredByHash && n.push(" (com um hash 'sha\u2026-' na lista, o navegador ignora o 'unsafe-inline' \u2014 por isso o hash sai)"));
|
|
109
|
+
}), n.push(
|
|
110
|
+
"",
|
|
111
|
+
"Sem 'unsafe-inline': use nonce por requisi\xE7\xE3o \u2014 o middleware gera o nonce e manda a CSP com 'nonce-<valor>' 'strict-dynamic' (https://nextjs.org/docs/app/guides/content-security-policy). CSP com nonce ou 'strict-dynamic' passa nesta checagem."
|
|
112
|
+
), new p(n.join(`
|
|
113
|
+
`));
|
|
114
|
+
}
|
|
115
|
+
function R(e) {
|
|
116
|
+
if (_(process.cwd()))
|
|
117
|
+
try {
|
|
118
|
+
b(e);
|
|
119
|
+
} catch (t) {
|
|
120
|
+
if (t instanceof p && process.env.NODE_ENV === "development") {
|
|
121
|
+
typeof console < "u" && console.warn(t.message);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
throw t;
|
|
125
|
+
}
|
|
38
126
|
}
|
|
39
|
-
|
|
40
|
-
|
|
127
|
+
var y = ["pg", "drizzle-orm"], h = "*";
|
|
128
|
+
function v(e) {
|
|
129
|
+
return Array.isArray(e) ? e.filter((t) => typeof t == "string") : [];
|
|
130
|
+
}
|
|
131
|
+
function T(e, t, n) {
|
|
132
|
+
let r = [], o = t;
|
|
41
133
|
for (; ; ) {
|
|
42
134
|
r.push(o);
|
|
43
|
-
let
|
|
44
|
-
if (
|
|
45
|
-
o =
|
|
135
|
+
let s = l.dirname(o);
|
|
136
|
+
if (s === o) break;
|
|
137
|
+
o = s;
|
|
46
138
|
}
|
|
47
|
-
r.includes(
|
|
48
|
-
for (let
|
|
49
|
-
let
|
|
139
|
+
r.includes(n) || r.push(n);
|
|
140
|
+
for (let s of r) {
|
|
141
|
+
let i = l.join(s, "node_modules", e, "package.json");
|
|
50
142
|
try {
|
|
51
|
-
if (
|
|
143
|
+
if (a.existsSync(i)) return i;
|
|
52
144
|
} catch {
|
|
53
145
|
}
|
|
54
146
|
}
|
|
55
147
|
return null;
|
|
56
148
|
}
|
|
57
|
-
function
|
|
149
|
+
function B(e) {
|
|
58
150
|
if (typeof e != "string" || e.trim() === "") return [];
|
|
59
|
-
let
|
|
60
|
-
if (
|
|
61
|
-
n.add(o);
|
|
62
|
-
let s = _(o, i, e);
|
|
63
|
-
if (!s) return;
|
|
151
|
+
let t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), r = (o, s) => {
|
|
152
|
+
if (t.has(o)) return;
|
|
64
153
|
t.add(o);
|
|
65
|
-
let
|
|
154
|
+
let i = T(o, s, e);
|
|
155
|
+
if (!i) return;
|
|
156
|
+
n.add(o);
|
|
157
|
+
let u;
|
|
66
158
|
try {
|
|
67
|
-
|
|
159
|
+
u = JSON.parse(a.readFileSync(i, "utf8"));
|
|
68
160
|
} catch {
|
|
69
161
|
return;
|
|
70
162
|
}
|
|
71
163
|
let c = {
|
|
72
|
-
...
|
|
73
|
-
...
|
|
74
|
-
},
|
|
75
|
-
for (let
|
|
164
|
+
...u.dependencies ?? {},
|
|
165
|
+
...u.optionalDependencies ?? {}
|
|
166
|
+
}, d = l.dirname(i);
|
|
167
|
+
for (let f of Object.keys(c)) r(f, d);
|
|
76
168
|
};
|
|
77
169
|
try {
|
|
78
|
-
for (let o of
|
|
170
|
+
for (let o of y) r(o, e);
|
|
79
171
|
} catch {
|
|
80
172
|
return [];
|
|
81
173
|
}
|
|
82
|
-
return [...
|
|
174
|
+
return [...n].sort();
|
|
83
175
|
}
|
|
84
|
-
function
|
|
85
|
-
return e.map((
|
|
176
|
+
function x(e) {
|
|
177
|
+
return e.map((t) => `./node_modules/${t}/**`);
|
|
86
178
|
}
|
|
87
|
-
function
|
|
88
|
-
let
|
|
89
|
-
for (let
|
|
90
|
-
|
|
91
|
-
return
|
|
179
|
+
function A(e) {
|
|
180
|
+
let t = v(e);
|
|
181
|
+
for (let n of y)
|
|
182
|
+
t.includes(n) || t.push(n);
|
|
183
|
+
return t;
|
|
92
184
|
}
|
|
93
|
-
function
|
|
94
|
-
let
|
|
185
|
+
function O(e, t) {
|
|
186
|
+
let n = {};
|
|
95
187
|
if (e && typeof e == "object" && !Array.isArray(e))
|
|
96
|
-
for (let [o,
|
|
97
|
-
|
|
98
|
-
if (
|
|
99
|
-
let r = [...
|
|
100
|
-
for (let o of
|
|
188
|
+
for (let [o, s] of Object.entries(e))
|
|
189
|
+
n[o] = v(s);
|
|
190
|
+
if (t.length === 0) return n;
|
|
191
|
+
let r = [...n[h] ?? []];
|
|
192
|
+
for (let o of t)
|
|
101
193
|
r.includes(o) || r.push(o);
|
|
102
|
-
return
|
|
194
|
+
return n[h] = r, n;
|
|
103
195
|
}
|
|
104
|
-
function
|
|
105
|
-
let
|
|
196
|
+
function P(e, t = {}) {
|
|
197
|
+
let n = e.webpack, r = e.headers, o = [];
|
|
106
198
|
try {
|
|
107
|
-
|
|
199
|
+
o = x(B(process.cwd()));
|
|
108
200
|
} catch {
|
|
109
|
-
|
|
201
|
+
o = [];
|
|
110
202
|
}
|
|
111
203
|
return {
|
|
112
204
|
...e,
|
|
113
205
|
// `serverExternalPackages` é reforço (não o conserto do caso webpackIgnore);
|
|
114
206
|
// o `outputFileTracingIncludes` computado é o que realmente inclui o closure.
|
|
115
|
-
serverExternalPackages:
|
|
116
|
-
outputFileTracingIncludes:
|
|
207
|
+
serverExternalPackages: A(e.serverExternalPackages),
|
|
208
|
+
outputFileTracingIncludes: O(
|
|
117
209
|
e.outputFileTracingIncludes,
|
|
118
|
-
|
|
210
|
+
o
|
|
119
211
|
),
|
|
120
|
-
|
|
121
|
-
|
|
212
|
+
// CSP x App Router (incidente Zelo 2026-10-22): só embrulha quando o produto
|
|
213
|
+
// TEM `headers()`. Sem ele não há CSP do next.config a checar, e o config
|
|
214
|
+
// continua sem a chave (não inventa um `headers` que o Next não pediu).
|
|
215
|
+
...typeof r == "function" ? {
|
|
216
|
+
async headers(...s) {
|
|
217
|
+
let i = await r.apply(this, s);
|
|
218
|
+
return R(i), i;
|
|
219
|
+
}
|
|
220
|
+
} : {},
|
|
221
|
+
webpack(s, i) {
|
|
222
|
+
let u = typeof n == "function" ? n(s, i) : s;
|
|
122
223
|
if (!i.dev && i.isServer) {
|
|
123
|
-
let
|
|
224
|
+
let c = {
|
|
124
225
|
builtEnv: process.env.NEXT_PUBLIC_NEETRU_ENV ?? null,
|
|
125
226
|
productId: process.env.NEXT_PUBLIC_NEETRU_PRODUCT_ID ?? null,
|
|
126
227
|
oidcClientId: process.env.NEXT_PUBLIC_NEETRU_OIDC_CLIENT_ID ?? null,
|
|
127
228
|
builtAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
128
229
|
};
|
|
129
230
|
try {
|
|
130
|
-
let
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
JSON.stringify(
|
|
231
|
+
let d = l.resolve(process.cwd(), t.outputDir ?? ".next");
|
|
232
|
+
a.mkdirSync(d, { recursive: !0 }), a.writeFileSync(
|
|
233
|
+
l.join(d, "neetru-build-manifest.json"),
|
|
234
|
+
JSON.stringify(c, null, 2),
|
|
134
235
|
"utf8"
|
|
135
236
|
);
|
|
136
|
-
} catch (
|
|
237
|
+
} catch (d) {
|
|
137
238
|
typeof console < "u" && console.warn(
|
|
138
239
|
"[neetru-sdk] withNeetruBuildGuard: falha ao gravar neetru-build-manifest.json (ignorado, build segue):",
|
|
139
|
-
|
|
240
|
+
d
|
|
140
241
|
);
|
|
141
242
|
}
|
|
142
|
-
k(
|
|
243
|
+
k(c);
|
|
143
244
|
}
|
|
144
|
-
return
|
|
245
|
+
return u;
|
|
145
246
|
}
|
|
146
247
|
};
|
|
147
248
|
}
|
|
148
249
|
|
|
149
|
-
export {
|
|
250
|
+
export { y as NEETRU_SQL_SERVER_EXTERNAL_PACKAGES, h as NEETRU_SQL_TRACE_INCLUDE_KEY, p as NeetruBuildGuardError, b as assertNeetruCspAllowsAppRouterScripts, k as assertNeetruProdBuildEnv, S as findCspInlineScriptBlocks, _ as hasNextAppRouter, O as mergeOutputFileTracingIncludes, A as mergeServerExternalPackages, B as resolveSqlRuntimeClosure, x as sqlClosureToTraceGlobs, P as withNeetruBuildGuard };
|
package/dist/catalog.cjs
CHANGED
package/dist/catalog.mjs
CHANGED
package/dist/checkout.cjs
CHANGED
package/dist/checkout.mjs
CHANGED
package/dist/db.cjs
CHANGED
package/dist/db.mjs
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -156,7 +156,7 @@ function kr(n, e) {
|
|
|
156
156
|
}
|
|
157
157
|
function Ut() {
|
|
158
158
|
try {
|
|
159
|
-
return "3.9.
|
|
159
|
+
return "3.9.1";
|
|
160
160
|
} catch {
|
|
161
161
|
return;
|
|
162
162
|
}
|
|
@@ -6927,7 +6927,7 @@ function pi(n) {
|
|
|
6927
6927
|
|
|
6928
6928
|
// src/index.ts
|
|
6929
6929
|
ve();
|
|
6930
|
-
var Wa = "3.9.
|
|
6930
|
+
var Wa = "3.9.1";
|
|
6931
6931
|
|
|
6932
6932
|
exports.DEFAULT_BASE_URL = We;
|
|
6933
6933
|
exports.DEV_FIXTURE_USER = qe;
|
package/dist/index.d.cts
CHANGED
|
@@ -246,6 +246,6 @@ declare function detectNonServerRuntime(): NonServerRuntime | null;
|
|
|
246
246
|
*/
|
|
247
247
|
|
|
248
248
|
/** Versão do SDK — exportada explicitamente pra detecção em runtime. */
|
|
249
|
-
declare const VERSION: "3.9.
|
|
249
|
+
declare const VERSION: "3.9.1";
|
|
250
250
|
|
|
251
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
|
@@ -246,6 +246,6 @@ declare function detectNonServerRuntime(): NonServerRuntime | null;
|
|
|
246
246
|
*/
|
|
247
247
|
|
|
248
248
|
/** Versão do SDK — exportada explicitamente pra detecção em runtime. */
|
|
249
|
-
declare const VERSION: "3.9.
|
|
249
|
+
declare const VERSION: "3.9.1";
|
|
250
250
|
|
|
251
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.mjs
CHANGED
|
@@ -154,7 +154,7 @@ function kr(n, e) {
|
|
|
154
154
|
}
|
|
155
155
|
function Ut() {
|
|
156
156
|
try {
|
|
157
|
-
return "3.9.
|
|
157
|
+
return "3.9.1";
|
|
158
158
|
} catch {
|
|
159
159
|
return;
|
|
160
160
|
}
|
|
@@ -6925,6 +6925,6 @@ function pi(n) {
|
|
|
6925
6925
|
|
|
6926
6926
|
// src/index.ts
|
|
6927
6927
|
ve();
|
|
6928
|
-
var Wa = "3.9.
|
|
6928
|
+
var Wa = "3.9.1";
|
|
6929
6929
|
|
|
6930
6930
|
export { We as DEFAULT_BASE_URL, qe as DEV_FIXTURE_USER, me as MockAi, de as MockAuth, Oe as MockCheckout, ut as MockDb, fe as MockEntitlements, le as MockNotifications, pe as MockSupport, ue as MockUsage, ce as MockWebhooks, ir as NEETRU_OIDC_ISSUER, Qe as NEETRU_SENTINEL_KEY, $ as NeetruAuthRequiredError, v as NeetruDbError, c as NeetruError, Wa as VERSION, pi as accessTokenErrorToHttp, ui as authenticateProductRequest, ne as checkCoreVersionCompat, dt as createAiNamespace, st as createCheckoutNamespace, rr as createNeetruClient, ot as createNeetruDb, lt as createNotificationsNamespace, at as createWebhooksNamespace, J as detectNonServerRuntime, ci as getServerNeetruClient, Xr as increment, Q as isFieldSentinel, en as isIncrementSentinel, Zt as isServerTimestampSentinel, lr as readBearerToken, dr as readCookie, Jr as serverTimestamp, ar as verifyAccessToken, Lo as verifyWebhookRequest, wn as verifyWebhookSignature };
|
package/dist/notifications.cjs
CHANGED
package/dist/notifications.mjs
CHANGED
package/dist/support.cjs
CHANGED
package/dist/support.mjs
CHANGED
package/dist/telemetry.cjs
CHANGED
package/dist/telemetry.mjs
CHANGED
package/dist/usage.cjs
CHANGED
package/dist/usage.mjs
CHANGED
package/dist/webhooks.cjs
CHANGED
package/dist/webhooks.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neetru/sdk",
|
|
3
|
-
"version": "3.9.
|
|
3
|
+
"version": "3.9.1",
|
|
4
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
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|