@lenne.tech/nest-server 11.41.1 → 11.41.3

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.
@@ -169,7 +169,7 @@ Two ordering rules, both enforced by the contract test:
169
169
  Package overrides live in the `overrides:` section of **`pnpm-workspace.yaml`** (they moved out of `package.json`'s `pnpm.overrides` in the pnpm 11 upgrade). They force transitive dependencies to a security-patched version.
170
170
 
171
171
  **Keep the set minimal.** On the pnpm 11 upgrade the list was pruned from 36 to the 9 then still
172
- load-bearing (it has since grown back to 17 as new advisories landed) — an override is only necessary if removing it lets the package resolve back INTO its vulnerable range (verify with a with/without lockfile diff; `pnpm audit` is the arbiter). Each surviving entry carries its CVE rationale as a comment. Remove an entry once its parent dependency ships a fixed version.
172
+ load-bearing (it has since grown back to 18 as new advisories landed) — an override is only necessary if removing it lets the package resolve back INTO its vulnerable range (verify with a with/without lockfile diff; `pnpm audit` is the arbiter). Each surviving entry carries its CVE rationale as a comment. Remove an entry once its parent dependency ships a fixed version.
173
173
 
174
174
  ### Rule: Override Targets MUST Be Fixed Versions
175
175
 
@@ -266,7 +266,7 @@ pnpm run check:mutations -- --id=<id> # one mutation
266
266
  pnpm run check:mutations -- --list # the registry, without running anything
267
267
  pnpm run check:mutations -- --allow-dirty # when the fix and its evidence share a working tree
268
268
  pnpm run check:mutations -- --jobs=4 # N mutations at a time (default: 2, or 4 on >=12 cores)
269
- pnpm run check:mutations -- --no-infra # only the 66 that need no MongoDB
269
+ pnpm run check:mutations -- --no-infra # only the 67 that need no MongoDB
270
270
  pnpm run check:mutations -- --since=<ref> # only mutations touching files changed since <ref>
271
271
  ```
272
272
 
@@ -285,7 +285,7 @@ when the registry, a vitest config or a setup file changed, since those can move
285
285
  commit, so selective re-running would save ~10 minutes a release. The price is a cache that has to
286
286
  model each spec's full dependency closure correctly, and getting that wrong produces a stale PASS
287
287
  for a test that has since gone vacuous — exactly what the gate is there to prevent. Bad trade
288
- at 112 mutations — past the threshold this paragraph has carried since the gate was written,
288
+ at 113 mutations — past the threshold this paragraph has carried since the gate was written,
289
289
  now reached exactly. The full run is approaching half an hour. **The re-evaluation is due now**: the
290
290
  next person to add a mutation should decide whether selective re-running has become worth its
291
291
  failure mode (a stale PASS for a test that has since gone vacuous), not bump this number again.
@@ -329,7 +329,7 @@ exactly the environment where the answer matters.
329
329
 
330
330
  Worth knowing before optimising the wrong thing: the specs behind all 46 e2e mutations add up to
331
331
  **~40 seconds**. The step takes ~740s. The remaining ~700s is paying vitest's startup — process
332
- spawn, transform, module graph, mongod connect, DB create and drop — once per mutation, 112 times.
332
+ spawn, transform, module graph, mongod connect, DB create and drop — once per mutation, 113 times.
333
333
  That work is largely single-threaded I/O and barely scales with cores: the full registry measures
334
334
  **744s on a 12-core laptop and 777s on a 4-vCPU CI runner**.
335
335
 
package/FRAMEWORK-API.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @lenne.tech/nest-server — Framework API Reference
2
2
 
3
- > Auto-generated from source code as of 2026-09-08 (v11.41.1)
3
+ > Auto-generated from source code as of 2026-09-21 (v11.41.3)
4
4
  > File: `FRAMEWORK-API.md` — compact, machine-readable API surface for Claude Code
5
5
 
6
6
  ## CoreModule.forRoot()
@@ -11,17 +11,18 @@ A green `pnpm audit` inside the framework repo says nothing about your tree.
11
11
 
12
12
  ## What this concretely means for you
13
13
 
14
- The framework pulls in two transitive packages that resolve to a **vulnerable** version unless you
14
+ The framework pulls in three transitive packages that resolve to a **vulnerable** version unless you
15
15
  override them yourself:
16
16
 
17
17
  | Package | Advisory | Why it cannot resolve forward on its own |
18
18
  |---------|----------|------------------------------------------|
19
19
  | `ws` | [GHSA-96hv-2xvq-fx4p](https://github.com/advisories/GHSA-96hv-2xvq-fx4p) — high: memory-exhaustion DoS + uninitialized memory disclosure. Patched `>=8.21.0` | `@nestjs/graphql` declares `"ws": "8.20.1"` — an **exact pin**, not a caret. No amount of updating moves it |
20
20
  | `js-yaml` | [GHSA-pm4m-ph32-ghv5](https://github.com/advisories/GHSA-pm4m-ph32-ghv5) — high: exponential parsing time in flow collections (DoS). Patched `>=5.2.2` | `@nestjs/swagger` declares `"js-yaml": "5.2.1"` — an **exact pin**, the same shape as the `ws` case. It cannot resolve forward |
21
+ | `multer` | [GHSA-wc9g-mqfw-jrwm](https://github.com/advisories/GHSA-wc9g-mqfw-jrwm), [GHSA-535w-7cp7-47q4](https://github.com/advisories/GHSA-535w-7cp7-47q4), [GHSA-qfvm-cv95-jqjf](https://github.com/advisories/GHSA-qfvm-cv95-jqjf) — high: DoS via crafted multipart input; [GHSA-qvfw-j98x-7q72](https://github.com/advisories/GHSA-qvfw-j98x-7q72) — low: file size limit bypass. Patched `>=2.3.0` | `@nestjs/platform-express` declares `"multer": "2.2.0"` — an **exact pin** in every 11.2.x. The framework's own `multer: 2.3.0` dependency does not move it: you get both copies, and FileInterceptor uses the vulnerable one |
21
22
 
22
23
  `@nestjs/graphql` is a plain `dependencies` entry, so `ws` is installed even when you run with
23
- `graphQl: false`. `@nestjs/swagger` is likewise a plain `dependencies` entry. Neither is optional in
24
- practice.
24
+ `graphQl: false`. `@nestjs/swagger` and `@nestjs/platform-express` are likewise plain `dependencies`
25
+ entries. None of them is optional in practice.
25
26
 
26
27
  ## The fix
27
28
 
@@ -40,6 +41,11 @@ overrides:
40
41
  # Same shape as the ws entry: an exact pin cannot resolve forward.
41
42
  # Remove once @nestjs/swagger stops pinning it.
42
43
  'js-yaml@>=5.0.0 <5.2.2': '5.2.2'
44
+
45
+ # @nestjs/platform-express exact-pins multer@2.2.0 (GHSA-wc9g-mqfw-jrwm and three more, patched >=2.3.0).
46
+ # Keep the target in LOCKSTEP with the multer version @lenne.tech/nest-server declares.
47
+ # Remove once @nestjs/platform-express requests >=2.3.0 itself.
48
+ 'multer@>=2.0.0 <2.3.0': '2.3.0'
43
49
  ```
44
50
 
45
51
  ### Retired: `@hono/node-server` (removed 2026-08-22, nest-server 11.36.1)
@@ -0,0 +1,75 @@
1
+ # Migration Guide: 11.41.1 → 11.41.2
2
+
3
+ ## Overview
4
+
5
+ | Category | Effort | Applies to |
6
+ |----------|--------|-----------|
7
+ | **Security** | none | `nodemailer` 9.0.5 → 9.1.1 (four advisories, one high) arrives through this package's `dependencies` |
8
+ | **Security** | one override, ~2 min | `multer` 2.2.0 → 2.3.0 (three high, one low): **your project has to add an override** — see below |
9
+ | Tooling | none | Framework repo only: `oxlint --fix-suggestions` removed, `.gitattributes`, non-blocking Windows CI |
10
+
11
+ No API change and no configuration change. The multer fix does enforce file size limits that crafted uploads could previously bypass.
12
+
13
+ ## Quick Migration
14
+
15
+ ```bash
16
+ pnpm update @lenne.tech/nest-server
17
+ ```
18
+
19
+ ```bash
20
+ # Is a vulnerable multer still in your tree? Anything below 2.3.0 means: add the override below.
21
+ pnpm why multer
22
+ pnpm audit
23
+ ```
24
+
25
+ ## Security: multer needs an override in your project
26
+
27
+ `@lenne.tech/nest-server` now declares `multer: 2.3.0`, but that does not reach the copy that
28
+ uploads actually go through. `@nestjs/platform-express` declares `"multer": "2.2.0"` as an **exact
29
+ pin** in every 11.2.x, so your tree ends up with both versions, and `FileInterceptor` uses 2.2.0.
30
+ The advisories ([GHSA-wc9g-mqfw-jrwm](https://github.com/advisories/GHSA-wc9g-mqfw-jrwm),
31
+ [GHSA-535w-7cp7-47q4](https://github.com/advisories/GHSA-535w-7cp7-47q4),
32
+ [GHSA-qfvm-cv95-jqjf](https://github.com/advisories/GHSA-qfvm-cv95-jqjf) — DoS via crafted multipart
33
+ input; [GHSA-qvfw-j98x-7q72](https://github.com/advisories/GHSA-qvfw-j98x-7q72) — file size limit
34
+ bypass) are in that copy.
35
+
36
+ Overrides declared in this package do not travel with it (see
37
+ [docs/security-overrides.md](../docs/security-overrides.md)). Add the entry to your project's
38
+ `pnpm-workspace.yaml` (pnpm 11+; `pnpm.overrides` in `package.json` on pnpm 10 and earlier):
39
+
40
+ ```yaml
41
+ overrides:
42
+ # @nestjs/platform-express exact-pins multer@2.2.0 (GHSA-wc9g-mqfw-jrwm and three more, patched >=2.3.0).
43
+ # Keep the target in LOCKSTEP with the multer version @lenne.tech/nest-server declares.
44
+ # Remove once @nestjs/platform-express requests >=2.3.0 itself.
45
+ 'multer@>=2.0.0 <2.3.0': '2.3.0'
46
+ ```
47
+
48
+ If your project declares `multer` directly, raise it to `2.3.0` as well, so the tree carries exactly
49
+ one copy.
50
+
51
+ ```bash
52
+ pnpm install
53
+ pnpm why multer # expect a single multer@2.3.0
54
+ ```
55
+
56
+ Projects created from nest-server-starter after 2026-09-15 already carry both.
57
+
58
+ Vendor-mode projects adopt the `multer` and `nodemailer` bumps through the core update instead of
59
+ `pnpm update`. The override is needed there all the same, because `@nestjs/platform-express` is
60
+ installed from npm in both modes.
61
+
62
+ ## Under the hood
63
+
64
+ Changes to the framework repository that do not reach consumers:
65
+
66
+ - `oxlint --fix-suggestions` is gone from `lint:fix`, the pre-commit `lint-staged` config and
67
+ `scripts/check.mjs`. oxlint's `no-console` suggestion deletes the whole call, so a commit or a
68
+ `pnpm run check:fix` silently removed `console.log` statements from `src/` and `tests/`.
69
+ - The `hono` and `js-yaml` 4.x overrides were raised to 4.13.7 and 4.3.2. Both are inert: their
70
+ consumers reach the fixed versions on their own ranges. Nothing to mirror.
71
+ - `.gitattributes` pins LF line endings, so a Windows checkout no longer turns
72
+ `docker-entrypoint.sh`, the `Dockerfile` and `bin/migrate.js` into CRLF.
73
+ - `extras/sync-version.ts` stages the lockfile with `execFileSync`, so a repository path containing
74
+ a space works.
75
+ - A non-blocking Windows CI job (`windows.yml`) runs install, build and unit tests.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nest-server",
3
- "version": "11.41.1",
3
+ "version": "11.41.3",
4
4
  "description": "Modern, fast, powerful Node.js web framework in TypeScript based on Nest with a GraphQL API and a connection to MongoDB (or other databases).",
5
5
  "keywords": [
6
6
  "node",
@@ -20,7 +20,7 @@
20
20
  "build:copy-types": "mkdir -p dist/types && cp src/types/*.d.ts dist/types/",
21
21
  "build:dev": "pnpm run build",
22
22
  "build:framework-api": "tsx scripts/generate-framework-api.ts",
23
- "build:pack": "pnpm pack && echo 'use file:/ROOT_PATH_TO_TGZ_FILE to integrate the package'",
23
+ "build:pack": "pnpm pack && echo \"use file:/ROOT_PATH_TO_TGZ_FILE to integrate the package\"",
24
24
  "c": "pnpm run check",
25
25
  "cf": "pnpm run check:fix",
26
26
  "check": "node scripts/check.mjs",
@@ -39,7 +39,7 @@
39
39
  "format": "oxfmt --write src/ scripts/",
40
40
  "format:check": "oxfmt --check src/ scripts/",
41
41
  "lint": "oxlint --ignore-path .oxlintignore src/ tests/ scripts/",
42
- "lint:fix": "oxlint --fix --fix-suggestions --ignore-path .oxlintignore src/ tests/ scripts/",
42
+ "lint:fix": "oxlint --fix --ignore-path .oxlintignore src/ tests/ scripts/",
43
43
  "prepack": "pnpm run prestart:prod",
44
44
  "prepublishOnly": "pnpm run lint && pnpm run test:ci",
45
45
  "prestart:prod": "pnpm run build",
@@ -53,10 +53,10 @@
53
53
  "start:debug": "nodemon --config nodemon-debug.json",
54
54
  "start:dev": "nodemon",
55
55
  "start:dev:swc": "nest start -b swc -w --type-check",
56
- "start:local": "NODE_ENV=local nodemon",
57
- "start:local:swc": "NODE_ENV=local nest start -b swc -w --type-check",
56
+ "start:local": "cross-env NODE_ENV=local nodemon",
57
+ "start:local:swc": "cross-env NODE_ENV=local nest start -b swc -w --type-check",
58
58
  "start:nodemon": "ts-node -r tsconfig-paths/register src/main.ts",
59
- "start:prod": "NODE_ENV=production node dist/main.js",
59
+ "start:prod": "cross-env NODE_ENV=production node dist/main.js",
60
60
  "test": "pnpm run vitest:unit && pnpm run vitest",
61
61
  "test:ci": "pnpm run vitest:unit && pnpm run vitest:ci",
62
62
  "test:cleanup": "find tests -type f \\( -name '*.txt' -o -name '*.bin' -o -name '*.png' \\) -not -name '.gitkeep' -delete && echo 'Test artifacts cleaned up'",
@@ -68,12 +68,12 @@
68
68
  "test:types": "tsc --noEmit --skipLibCheck -p tests/types/tsconfig.json",
69
69
  "test:unit:watch": "vitest --config vitest.config.ts",
70
70
  "typecheck:tests": "tsc --noEmit -p tsconfig.tests.json",
71
- "vitest": "NODE_ENV=e2e vitest run --config vitest-e2e.config.ts",
72
- "vitest:ci": "NODE_ENV=ci vitest run --config vitest-e2e.config.ts",
73
- "vitest:cov": "NODE_ENV=e2e vitest run --coverage --config vitest-e2e.config.ts",
71
+ "vitest": "cross-env NODE_ENV=e2e vitest run --config vitest-e2e.config.ts",
72
+ "vitest:ci": "cross-env NODE_ENV=ci vitest run --config vitest-e2e.config.ts",
73
+ "vitest:cov": "cross-env NODE_ENV=e2e vitest run --coverage --config vitest-e2e.config.ts",
74
74
  "vitest:unit": "vitest run --config vitest.config.ts",
75
75
  "vitest:unit:cov": "vitest run --coverage --config vitest.config.ts",
76
- "vitest:watch": "NODE_ENV=e2e vitest --config vitest-e2e.config.ts",
76
+ "vitest:watch": "cross-env NODE_ENV=e2e vitest --config vitest-e2e.config.ts",
77
77
  "watch": "npm-watch"
78
78
  },
79
79
  "repository": {
@@ -127,9 +127,9 @@
127
127
  "lodash": "4.18.1",
128
128
  "mongodb": "7.5.0",
129
129
  "mongoose": "9.9.3",
130
- "multer": "2.2.0",
130
+ "multer": "2.3.0",
131
131
  "node-mailjet": "6.0.11",
132
- "nodemailer": "9.0.5",
132
+ "nodemailer": "9.1.1",
133
133
  "passport": "0.7.0",
134
134
  "passport-jwt": "4.0.1",
135
135
  "reflect-metadata": "0.2.2",
@@ -201,6 +201,7 @@
201
201
  "ansi-colors": "4.1.3",
202
202
  "better-auth": "1.7.1",
203
203
  "bullmq": "6.2.0",
204
+ "cross-env": "10.1.0",
204
205
  "find-file-up": "2.0.1",
205
206
  "husky": "9.1.7",
206
207
  "ioredis": "6.0.0",