@lenne.tech/nest-server 11.39.0 → 11.40.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.
- package/.claude/rules/configurable-features.md +1 -0
- package/.claude/rules/module-inheritance.md +2 -0
- package/.claude/rules/package-management.md +51 -2
- package/.claude/rules/testing.md +182 -3
- package/CLAUDE.md +13 -1
- package/FRAMEWORK-API.md +2 -2
- package/dist/core/common/interfaces/server-options.interface.d.ts +1 -1
- package/dist/core/modules/ai/providers/openai-compatible.provider.d.ts +2 -0
- package/dist/core/modules/ai/providers/openai-compatible.provider.js +28 -3
- package/dist/core/modules/ai/providers/openai-compatible.provider.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/migration-guides/11.39.0-to-11.40.0.md +186 -0
- package/package.json +5 -4
- package/src/core/common/interfaces/server-options.interface.ts +17 -1
- package/src/core/modules/ai/README.md +33 -0
- package/src/core/modules/ai/providers/openai-compatible.provider.ts +76 -3
|
@@ -333,6 +333,7 @@ This pattern is currently applied to:
|
|
|
333
333
|
| Cron Job Deduplication | per job: `distributed` in `CronJobConfig` | Explicit Boolean | **`true` when `redis` is configured, otherwise `false`** — a single-replica project that upgrades must not silently gain a `cron-locks` collection, a lease write per tick, and a new way for a tick to be skipped. A Redis-less multi-replica fleet opts in per job with `distributed: true` (MongoDB lease). Mechanism: BullMQ job scheduler when Redis + the OPTIONAL peer `bullmq` are present AND `cronTime` is a string without `utcOffset`; otherwise local timer + lease (Redis `SET NX`, else a TTL-indexed `cron-locks` document). Tick lease TTL 3600 s. **Leases fail open** — an unreachable lease store runs the tick everywhere rather than stopping all scheduled work fleet-wide. **`runOnInit` (default `true`) deduplicates over a FIXED per-job key with a 300 s TTL**, because replicas do not share a boot instant: replicas booting within 5 min run the startup tick once between them, and a replica restarting inside that window SKIPS its startup tick — set `distributed: false` on jobs whose `runOnInit` work is per-process (warming a process-local cache). No constructor change needed: `CoreModule` fills `core-cron-jobs.registry.ts` via `CoreCronJobsInitializer` and `CoreCronJobs` reads it lazily; explicit `{ connection, redisService }` in `CoreCronJobsOptions` wins. With neither source it warns once and every replica runs every tick |
|
|
334
334
|
| Shutdown Delay | `shutdownDelayMs` | Numeric Sentinel — Family B (`0` = off) | `0` (default, no delay, no log). Waits N ms **in the SIGTERM/SIGINT handler, before `close()` is entered**, so a load balancer can finish deregistering while the instance is still fully healthy. NOT a lifecycle hook: `close()` runs `onModuleDestroy` → `beforeApplicationShutdown` → dispose → `onApplicationShutdown`, so a delay in `beforeApplicationShutdown` would wait with every module already torn down while the socket still accepts — worse than no delay. **Requires `installGracefulShutdown(app)` in main.ts, which REPLACES `server.enableShutdownHooks()`** — keeping both makes Nest close the app in parallel with the wait, so the delay silently never happens. At delay `0` the helper IS `enableShutdownHooks()`. **Keep the value well below the orchestrator grace period AND leave room for the drain that follows**: Compose `stop_grace_period` 10s, Kubernetes `terminationGracePeriodSeconds` 30s, and `installProcessDiagnostics()` force-exits after 30s — exceed any and the process is SIGKILLed mid-wait with no hook running. Warns above `10000`, capped at `60000`. Non-numeric / negative values behave like `0` |
|
|
335
335
|
| Trust Proxy | `trustProxy` | Explicit Value (pass-through, Express default) | `false` (Express's own default — the forwarded chain is not trusted). Passed verbatim to `app.set('trust proxy', …)` by `CoreTrustProxyInitializer`, a `CoreModule` provider, so a consumer inherits it by upgrading and needs no `main.ts` edit. Accepts `false` / a hop count (`1`, `2`) / `'loopback'` / a subnet list — **not** Express's predicate function: the value must survive `NEST_SERVER_CONFIG` / `NSC__*` (JSON) and the ConfigService deep clone. **This is what makes `request.ip` correct, and every IP-keyed rate limit depends on it**: unset behind Caddy/nginx/an ingress, `req.ip` is the PROXY address for every request, so all clients share ONE bucket and `auth.rateLimit.max` throttles everybody at once — exactly fleet-wide once `redis` is configured. Trusting MORE hops than exist is the opposite failure: a client prepends its own header entry and picks a fresh bucket per request. Applied at module init (inside `app.init()`/`listen()`, i.e. AFTER `main.ts`), so a configured value wins over a hand-written `app.set()`; an UNSET value is never applied, which keeps `app.set('trust proxy', fn)` in `main.ts` available as the escape hatch for the predicate form. **Unset + an IP-keyed limiter enabled (`auth.rateLimit` / `betterAuth.rateLimit`) logs a boot warning naming the shared-bucket consequence**; `trustProxy: false` is the explicit "nothing proxies me" answer that silences it. The AI limiter keys on the user id and is unaffected |
|
|
336
|
+
| AI Egress Allowlist (SSRF) | `ai.allowedBaseUrlHosts` | Explicit Value — **unset = permissive**, malformed = INTERPRETED or reported, never silently off | `undefined` → no restriction, so a local provider (Ollama on `localhost:11434`) works out of the box. Set → only those hosts are reachable, matched against `URL.host` (incl. port) and `URL.hostname`. **Accepts an array OR a comma-separated string, and the string form is not a convenience** — it is what the framework's own env mapping produces: `NSC__AI__ALLOWED_BASE_URL_HOSTS` becomes `{ ai: { allowedBaseUrlHosts: '<string>' } }` and lodash `merge` assigns that scalar straight over a configured array. Until 11.39.x a bare `!Array.isArray(...) -> return` read that as "not configured" and skipped the check entirely, so the canonical `NSC__` spelling silently disabled SSRF egress control with no log line at all. Entries are trimmed, lowercased and stripped of a fully-qualifying trailing dot, and the SAME normalisation is applied to the URL, so neither side wins by spelling one DNS name differently; a bare hostname entry matches any port, and an entry naming the scheme's default port (`example.com:443` on https) also matches the portless URL. A value that is neither array nor string carries no hostnames — the allowlist is then inactive and that is LOGGED as an error, because from the outside it looks exactly like "correctly unset". Enforced on **all three** outbound paths (`chat()`, the capability `probe()`, and `probeContextWindow()` — the last was unguarded before 11.39.x and is reachable from an ordinary user prompt via `detectAndPersistCapabilities()`, before the rate limit). Implementation: `openai-compatible.provider.ts` → `assertBaseUrlAllowed()` / `resolveAllowedBaseUrlHosts()` |
|
|
336
337
|
| AI Assistant | `ai` | Presence Implies Enabled | Core: `maxIterations: 5`, `defaultMode: 'auto'` (or `'plan'`), `rateLimit` (presence implies enabled: `max: 20`, `windowSeconds: 60`), `systemPrompt`, `documentation` (injected into the system prompt), `encryptionSecret`. **DB-backed LLM connections** (`aiConnections`, admin CRUD) with AES-256-GCM-encrypted API keys (`AiCryptoService`, secret from `ai.encryptionSecret` / `NSC__AI__ENCRYPTION_SECRET` / `SECRETS_ENCRYPTION_KEY`; `apiKeyEncrypted` is a global `secretFields` entry, never returned — only `hasApiKey`); optional `defaultConnection` one-time seed. **Provider abstraction** (`ILlmProvider`, default `OpenAiCompatibleProvider` for any OpenAI-compatible endpoint via `fetch`; per-connection `supportsNativeTools`/`supportsJsonResponse` capabilities, emulated tool calling when native tools are unavailable). **Tool registry** (`AiToolRegistry`, tools self-register, role-filtered; tools may be `mutating`/`destructive` and define `authorize()` for pre-flight data-level checks). **Plan mode** (`input.mode: 'plan'`): full plan → pre-flight authorize ALL steps → all-or-nothing execution with a translated (de/en) error when any step is not permitted. **Confirmation policy**: `confirmation.mutating: { default, enforced }` + client `input.requireConfirmation` (ignored when enforced); `destructive` always confirms. **Client metadata** (`input.metadata`: URL/nav/console logs, untrusted+capped). **Multi-turn conversations** (`aiConversations`, owner-scoped). **SSE streaming** (`POST /ai/stream`). **Audit** (`audit: false` → persist to `aiInteractions`, admin-readable). **Token budgets** (`budget: { period: 'day'|'month'|'none', user: { maxTokens?, maxPrompts? }, tenant: { maxTokens?, maxPrompts? } }`, requires audit): per-user AND per-tenant limits with config defaults; admins override per user/tenant at runtime (`aiBudgetLimits`, `CoreAiBudgetService`). Resolution: override → default → unlimited (missing/0 = unlimited). Enforced before the run (HTTP 429 + translated). Each response carries a compact `budget` summary (promptTokens, usedTokens, remainingTokens, resetAt); full breakdown via `aiUsage` query / `GET /ai/usage`. **Self-optimizing prompts**: the system prompt is assembled from keyed fragments (`CoreAiPromptBuilderService` ships built-in defaults; works with zero rows). Admin-editable overrides per slot (`aiSlots`, admin CRUD, `/ai/slots`) scoped by `key`/`locale`/`capability`/`tenantId`, with tenant override/reset semantics and placeholder tokens resolved at run time via the placeholder registry. **Governed learning loop** (`promptLearning: { enabled: true, autoApply: false }`): tool errors record `suggested` hints (`aiPromptHints`, admin CRUD, `/ai/prompt-hints`) that only reach the prompt once admin-approved (or auto-approved when `autoApply`); hints only ADD guidance, never relax permissions. **Context window** (`contextWindow`, default 8192; auto-detected per connection via `ILlmProvider.detectContextWindow()` — Ollama `/api/show` probe / known-model table / Claude alias — and persisted): per-user/session history is trimmed (oldest non-system turns dropped, last truncated) and tool-results capped to `maxToolResultChars` (default 12000) so a session never overflows the model. A connection's window can be seeded via `ai.defaultConnection.contextWindow` (validated: a non-positive/non-integer value is dropped with a warning). **Capability drift check** (`capabilityDriftCheck`, default `false`): opt-in boot self-check that probes each enabled connection with an EXPLICIT `supportsNativeTools`/`supportsJsonResponse` (built with those flags cleared so the endpoint is actually re-probed) and logs a warning on mismatch — the stored value is never changed. OFF by default because it makes outbound calls to the LLM endpoints on every boot; also skipped in the ci/e2e runners. **Deferred tool schemas** (`deferToolSchemas`, default `false`): the system-prompt tool catalog then lists only tool NAMES + descriptions instead of full JSON schemas, and the model fetches a schema on demand via the built-in `search_tools` meta-tool — with a large registry the schemas alone can dominate a small context window. `deferToolSummaryChars` (default `0` = untruncated) additionally caps each description in that DEFERRED catalog: whole sentences up to the cap (always at least the first), word-boundary cut when the first sentence already exceeds it, and a `…` marker appended ON TOP of the cap. The default of `0` keeps the saving opt-in, so enabling `deferToolSchemas` alone never changes what a description says; set roughly 200–400 alongside it to actually reclaim the context. Both apply to EMULATED providers only — a connection with `supportsNativeTools: true` receives every full description + schema via `buildToolSchemas()` regardless, so truncation and the banner are skipped there rather than asserting a cut the tool payload contradicts. The omitted tail is where preconditions and role restrictions usually live — the catalog banner tells the model to fetch the full text via `search_tools` first, but this is model GUIDANCE only: authorization is enforced server-side by the registry's role filter (`forUser()`), the execution-time re-check, and the `mutating`/`destructive` flags read by the confirmation gate — never by what the catalog shows. (`AiTool.authorize()` runs in PLAN MODE only; in auto mode and over MCP, data-level checks must live inside `execute()`.) **MCP server** (`mcp: false` → `/ai/mcp` Streamable HTTP, Bearer auth, lazy `@modelcontextprotocol/sdk`; `mcp: { oauth: true, oauthSecret }` adds OAuth 2.1 — HMAC tokens + PKCE S256 + dynamic registration via `mountAiMcpOAuth(app)` in main.ts). Overrides via `CoreModule.forRoot(env, { ai: { budgetService, connectionResolver, connectionService, controller, conversationService, interactionService, mcpClientService, modeService, placeholderRegistry, preferenceService, promptBuilder, promptHintService, promptService, resolver, service, slotService, toolGrantService, toolPolicyService } })` |
|
|
337
338
|
|
|
338
339
|
## Module Override Pattern (via `ICoreModuleOverrides`)
|
|
@@ -83,6 +83,8 @@ override async signIn(...): Promise<Auth> {
|
|
|
83
83
|
|------------|--------|---------|
|
|
84
84
|
| `CoreAuthResolver` | `checkLegacyGraphQLEnabled(name)` | Throws HTTP 410 if legacy endpoints disabled |
|
|
85
85
|
| `CoreAuthController` | `checkLegacyRESTEnabled(name)` | Throws HTTP 410 if legacy endpoints disabled |
|
|
86
|
+
| `OpenAiCompatibleProvider` | `resolveAllowedBaseUrlHosts()` | Normalises the SSRF egress allowlist (CSV string, case, trailing dot) and reports a malformed value. An override of `assertBaseUrlAllowed()` that re-reads `ConfigService` directly silently loses all of it — including the string form the framework's own `NSC__` mapping produces, which is the shape that used to switch the control off |
|
|
87
|
+
| `OpenAiCompatibleProvider` | `assertBaseUrlAllowed(url)` | Call it before ANY new outbound `fetch` you add to a provider. It already guards `chat()`, `probe()` and `probeContextWindow()`; a fourth path that forgets it is a hole the allowlist's own tests cannot see unless they assert on `fetch` |
|
|
86
88
|
|
|
87
89
|
**Rule**: When you override a method, check if the parent calls any `protected` helper methods. If so, call them in your override too.
|
|
88
90
|
|
|
@@ -151,7 +151,7 @@ Two ordering rules, both enforced by the contract test:
|
|
|
151
151
|
| Rule | Why |
|
|
152
152
|
|------|-----|
|
|
153
153
|
| `packageManager` is exact (`x.y.z+sha512.<hash>`), never a range | Same fixed-version rule as dependencies; corepack rejects ranges outright |
|
|
154
|
-
| `engines.pnpm` tracks the pin's major (`^<major>.0.0`) | A soft gate that warns pnpm 10 users. It is not a pin and cannot tell CI what to install |
|
|
154
|
+
| `engines.pnpm` tracks the pin's major (`^<major>.0.0`) | A soft gate that warns pnpm 10 users. It is not a pin and cannot tell CI what to install. Note it is deliberately looser than what the check chains rely on: `pnpm peers check` is a pnpm 11 subcommand, and `^11.0.0` does not guarantee the minor that introduced it. The real guarantee is `packageManager`, which is exact — this range is not the place to encode a floor |
|
|
155
155
|
| Never declare `devEngines.packageManager` | npm/npx abort with `EBADDEVENGINES`; corepack rejects ranges inside it |
|
|
156
156
|
| Never pass `version:` to `pnpm/action-setup` | Two sources drift; the action hard-errors on a mismatch |
|
|
157
157
|
| Never `RUN corepack …` | Absent on Node >= 25 |
|
|
@@ -168,7 +168,8 @@ Two ordering rules, both enforced by the contract test:
|
|
|
168
168
|
|
|
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
|
-
**Keep the set minimal.** On the pnpm 11 upgrade the list was pruned from 36 to the 9 still
|
|
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
173
|
|
|
173
174
|
### Rule: Override Targets MUST Be Fixed Versions
|
|
174
175
|
|
|
@@ -263,6 +264,16 @@ The reliable tells are narrower:
|
|
|
263
264
|
3. **The lockfile resolves two versions of the package inside one major.** Beware `@types/x`, which
|
|
264
265
|
looks like a second resolution of `x` and is not.
|
|
265
266
|
|
|
267
|
+
**This is automated now — `pnpm run check:overrides`.** The guard (`scripts/check-overrides.mjs`)
|
|
268
|
+
cross-references every `overrides:` entry against a live `pnpm audit` report and reports four
|
|
269
|
+
classes: **TOO LOW** (the override resolves and still delivers a version the advisory covers — modes
|
|
270
|
+
1 and 2 above), **NOT MATCHING** (the selector no longer reaches the path it was written for), plus
|
|
271
|
+
**NO FIX** and **UNUSED** as warnings. It runs inside `check`, `check:fix`, `check:naf` and
|
|
272
|
+
`check:raw`, and in CI on both `build.yml` and `publish.yml`. The three tells above are still how you
|
|
273
|
+
*read* a report by hand; the guard is what makes sure somebody does. `--audit-file` and
|
|
274
|
+
`--advisory-file` make a run reproducible offline, and CI passes `--audit-file` so the
|
|
275
|
+
cannot-obtain-a-report skip (correct on a laptop, a silent pass on a runner) is unreachable there.
|
|
276
|
+
|
|
266
277
|
**The fix in both cases is one entry, floored below the current patch line, targeting a version at
|
|
267
278
|
or above it:**
|
|
268
279
|
|
|
@@ -280,6 +291,44 @@ or above it:**
|
|
|
280
291
|
`ERR_PNPM_NO_MATURE_MATCHING_VERSION`. Take the oldest version that clears every advisory — which
|
|
281
292
|
is the right instinct regardless of the policy.
|
|
282
293
|
|
|
294
|
+
### Suppressions age the same way, and worse
|
|
295
|
+
|
|
296
|
+
`auditConfig.ignoreGhsas` in `pnpm-workspace.yaml` suppresses an advisory outright. It is the other
|
|
297
|
+
half of the problem above, and the blinder half.
|
|
298
|
+
|
|
299
|
+
An override at least stays visible: `pnpm audit` keeps reporting its package, so a stale entry can be
|
|
300
|
+
caught by reading the report against the file. **A suppressed advisory is removed from
|
|
301
|
+
`pnpm audit --json` entirely** — `advisories` drops it and `muted` comes back empty. Once a GHSA is
|
|
302
|
+
listed there, no audit run ever mentions it again. If upstream ships a fix tomorrow, nothing says so.
|
|
303
|
+
|
|
304
|
+
That is not hypothetical either. `GHSA-mh99-v99m-4gvg` was suppressed on 2026-07-28 with a
|
|
305
|
+
justification that was correct in every detail: the newest 1.x was 1.1.16 and carried no length
|
|
306
|
+
guard, and the one remaining path could not be lifted. **1.1.17 — the backport the entry said did not
|
|
307
|
+
exist — was published on 2026-07-29, one day later.** The entry sat obsolete for five weeks, and
|
|
308
|
+
nothing in the repo could have said so.
|
|
309
|
+
|
|
310
|
+
**Rules for an entry here:**
|
|
311
|
+
|
|
312
|
+
1. **Name the advisory, the affected path, and why it cannot be fixed** — not just why it is
|
|
313
|
+
tolerable.
|
|
314
|
+
2. **Record what you verified and when**, with a re-verification trigger ("re-check when @nestjs/cli
|
|
315
|
+
drops fork-ts-checker-webpack-plugin"). A justification without a date cannot be audited later.
|
|
316
|
+
3. **Assume it will stop being true without telling you.** Ask, before adding it: *what will notice
|
|
317
|
+
when this expires?* If the answer is "nothing", the entry is a liability regardless of how good
|
|
318
|
+
today's reasoning is.
|
|
319
|
+
4. **Prefer an override.** A suppression is the last resort, for an advisory with no patched version
|
|
320
|
+
anywhere. A drifted override is at least still visible.
|
|
321
|
+
|
|
322
|
+
`pnpm run check:overrides` re-checks every listed GHSA against the GitHub Advisory API and **fails**
|
|
323
|
+
on `FIX AVAILABLE` (a `first_patched_version` now exists) or on a withdrawn advisory. An unreachable
|
|
324
|
+
API is reported as `UNVERIFIED` and tolerated locally — but **fails under `CI`**, because a skip
|
|
325
|
+
nobody reads is indistinguishable from a check that ran.
|
|
326
|
+
|
|
327
|
+
One consequence worth knowing before you reach for this mechanism: the guard fires when the advisory
|
|
328
|
+
has a patched version for **any** affected range. That makes `ignoreGhsas` nearly unusable for an
|
|
329
|
+
advisory that is fixed *somewhere* but unfixable on *your* path — which is the honest outcome, since
|
|
330
|
+
that case is an override problem, not a suppression problem.
|
|
331
|
+
|
|
283
332
|
### Safe Override Workflow
|
|
284
333
|
|
|
285
334
|
When adding an override to fix a vulnerability:
|
package/.claude/rules/testing.md
CHANGED
|
@@ -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
|
|
269
|
+
pnpm run check:mutations -- --no-infra # only the 63 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,10 @@ 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
|
|
288
|
+
at 109 mutations — past the threshold this paragraph has carried since the gate was written,
|
|
289
|
+
now reached exactly. The full run is approaching half an hour. **The re-evaluation is due now**: the
|
|
290
|
+
next person to add a mutation should decide whether selective re-running has become worth its
|
|
291
|
+
failure mode (a stale PASS for a test that has since gone vacuous), not bump this number again.
|
|
289
292
|
|
|
290
293
|
Not part of `pnpm run check` — it edits source and re-runs whole e2e suites. It belongs in review
|
|
291
294
|
and on the publish path. It is also reachable on demand, without cutting a release:
|
|
@@ -326,7 +329,7 @@ exactly the environment where the answer matters.
|
|
|
326
329
|
|
|
327
330
|
Worth knowing before optimising the wrong thing: the specs behind all 46 e2e mutations add up to
|
|
328
331
|
**~40 seconds**. The step takes ~740s. The remaining ~700s is paying vitest's startup — process
|
|
329
|
-
spawn, transform, module graph, mongod connect, DB create and drop — once per mutation,
|
|
332
|
+
spawn, transform, module graph, mongod connect, DB create and drop — once per mutation, 109 times.
|
|
330
333
|
That work is largely single-threaded I/O and barely scales with cores: the full registry measures
|
|
331
334
|
**744s on a 12-core laptop and 777s on a 4-vCPU CI runner**.
|
|
332
335
|
|
|
@@ -370,6 +373,155 @@ When a change adds or edits a test that claims to fix or pin a bug:
|
|
|
370
373
|
4. **"Is the mutation the defect, or a proxy for it?"** A mutation that breaks everything proves
|
|
371
374
|
nothing about the specific behaviour.
|
|
372
375
|
|
|
376
|
+
## `disableConsoleIntercept` — why both runners set it
|
|
377
|
+
|
|
378
|
+
**Rule: both vitest configs in THIS repo set `disableConsoleIntercept: true`, because both were
|
|
379
|
+
measured and both showed exposure. Do not remove it to get per-file console attribution back
|
|
380
|
+
without reading this first — and do not copy it into another repo without measuring there.**
|
|
381
|
+
|
|
382
|
+
It is the fix for an `EnvironmentTeardownError` that failed `pnpm run check` roughly **1 run in
|
|
383
|
+
10**, with every test green:
|
|
384
|
+
|
|
385
|
+
```
|
|
386
|
+
EnvironmentTeardownError: [vitest-worker]: Closing rpc while "onUserConsoleLog" was pending
|
|
387
|
+
Test Files 108 passed (108)
|
|
388
|
+
Tests 2300 passed | 1 skipped (2301)
|
|
389
|
+
Errors 1 error
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### The mechanism
|
|
393
|
+
|
|
394
|
+
vitest normally replaces `globalThis.console` in every worker (`setupConsoleLogSpy()`) and
|
|
395
|
+
forwards each write to the main thread as an `onUserConsoleLog` RPC. At worker teardown
|
|
396
|
+
`execute()` does **not** await those calls — it rejects whatever is still in flight:
|
|
397
|
+
|
|
398
|
+
```js
|
|
399
|
+
rpc.$rejectPendingCalls(({ method, reject }) =>
|
|
400
|
+
reject(new EnvironmentTeardownError(`Closing rpc while "${method}" was pending`)))
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
The rejection surfaces as an unhandled error and fails the run. So a console write from the last
|
|
404
|
+
test of a file can lose a race against its own cleanup.
|
|
405
|
+
|
|
406
|
+
`disableConsoleIntercept: true` skips `setupConsoleLogSpy()` entirely, so the custom console is
|
|
407
|
+
never installed. Worker-side, `rpc.onUserConsoleLog` has exactly ONE caller — `sendLog()` inside
|
|
408
|
+
that console (`vitest/dist/chunks/console.*.js`); every other reference is main-process reporter
|
|
409
|
+
code. No spy, no caller, nothing that can be pending. **That is a structural fix, not a reduced
|
|
410
|
+
probability** — which matters, because the rate is load-dependent and no number of green runs
|
|
411
|
+
would have proved it.
|
|
412
|
+
|
|
413
|
+
### The cost, and why it is not what it looks like
|
|
414
|
+
|
|
415
|
+
The obvious reading — "you lose the `stdout | <file>` prefix" — is wrong, and both configs said so
|
|
416
|
+
until it was measured. With the intercept ON, the default reporter **swallows console output from
|
|
417
|
+
PASSING tests entirely** in a piped run (which is how CI and every piped `check` runs). Removing it
|
|
418
|
+
does not strip a prefix; it makes previously invisible output appear:
|
|
419
|
+
|
|
420
|
+
```
|
|
421
|
+
nest-server unit disableConsoleIntercept: false -> 0 visible lines
|
|
422
|
+
disableConsoleIntercept: true -> 8-9 visible lines
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
The range is not sloppiness: three of those lines are the rate-limit-store capacity warning, whose
|
|
426
|
+
count depends on how many counters a run happens to create, so the total moves between runs. Quote a
|
|
427
|
+
range when a measurement varies — a single number invites the next reader to treat a normal 8 as a
|
|
428
|
+
regression from 9 and go looking for it.
|
|
429
|
+
|
|
430
|
+
**And count the writes, not one phrasing of them.** A first attempt at re-measuring this grepped for
|
|
431
|
+
`Configured for|No local config` and reported **1**, because the other seven lines are a hub-buffer
|
|
432
|
+
warning, a ConfigService merge notice, three rate-limit warnings and two dev auth URLs — none of
|
|
433
|
+
which match those words. That reads as "no exposure" and is the same artefact as counting reporter
|
|
434
|
+
output, arrived at from a different direction. Diff a flag-off run against a flag-on run instead;
|
|
435
|
+
the difference IS the answer, and it cannot be narrowed by a pattern.
|
|
436
|
+
|
|
437
|
+
Measure by flipping the value IN THE CONFIG. A CLI override does not win against a config value —
|
|
438
|
+
a first attempt at this measurement was worthless for exactly that reason.
|
|
439
|
+
|
|
440
|
+
**And it does not point the same way in every suite.** In an e2e config, where the reporter DOES
|
|
441
|
+
print passing-test output, the intercept adds a header line per write, so removing it roughly
|
|
442
|
+
halves the volume. Same flag, opposite ledger.
|
|
443
|
+
|
|
444
|
+
That direction is the finding; do not quote a figure for it. The `57 → 37` this line used to carry
|
|
445
|
+
came from a comment in the starter's own config (`vitest-e2e.config.ts:96`, "this run went from 57
|
|
446
|
+
visible lines to 37") that nobody here has re-run, and whose scope is ambiguous — the paragraph
|
|
447
|
+
above it discusses a single-spec run, so the numbers may describe one file or the whole suite.
|
|
448
|
+
**Where a number has not been measured, state the direction and stop.** The claim that matters —
|
|
449
|
+
that the ledger flips in an e2e config, because that reporter does print passing-test output — needs
|
|
450
|
+
no figure at all, and a figure nobody can source invites the next reader to treat it as a baseline.
|
|
451
|
+
|
|
452
|
+
### Not a rule to apply blindly — measure both sides
|
|
453
|
+
|
|
454
|
+
`nest-server` sets it in both runners because both showed exposure. That is a finding here, not a
|
|
455
|
+
default. `nest-server-starter` deliberately sets it ONLY in the e2e config, `nuxt-base-starter`
|
|
456
|
+
and `offers` set it nowhere — each after measuring.
|
|
457
|
+
|
|
458
|
+
The trap is the measurement itself. Counting `grep -cE '^(stdout|stderr) \| '` reports what the
|
|
459
|
+
REPORTER PRINTS, not the RPC traffic — so a suite with 114 suppressed writes measures 0 and looks
|
|
460
|
+
immune. That artefact produced a wrong "zero exposure" verdict in the starter before
|
|
461
|
+
`nuxt-base-starter` caught it. The honest procedure is:
|
|
462
|
+
|
|
463
|
+
1. Exposure — does the suite make `console.*` calls at all? (Nest `Logger` output does not count;
|
|
464
|
+
it bypasses the intercept.)
|
|
465
|
+
2. Cost — visible lines with the flag versus without, flipped in the config.
|
|
466
|
+
3. Does it actually flake? Write COUNT does not predict the race; write TIMING relative to the end
|
|
467
|
+
of a file does. The starter's unit suite makes 114 writes and did not flake in 15 runs;
|
|
468
|
+
nest-server's makes 9 and flaked about 1 in 10.
|
|
469
|
+
|
|
470
|
+
Where a suite flakes AND the noise cost is high, the better fix is neither option: silence the
|
|
471
|
+
writes at the source. `nuxt-base-starter` measures 0 writes and 0 noise because its
|
|
472
|
+
`tests/unit/setup.ts` mocks `console.debug`/`console.info` globally.
|
|
473
|
+
|
|
474
|
+
### Three things that made this expensive to diagnose
|
|
475
|
+
|
|
476
|
+
1. **It is a race, not a late log.** Every spec involved `await`s correctly. Hunting for an
|
|
477
|
+
unawaited promise finds nothing and sends you the wrong way.
|
|
478
|
+
2. **The reported file is not the cause.** vitest attributes the unhandled rejection to whichever
|
|
479
|
+
file's worker was running ("It doesn't mean the error was thrown inside the file itself").
|
|
480
|
+
The file it named logs nothing of its own.
|
|
481
|
+
3. **A wrong explanation survives five green runs.** The first diagnosis here — a keep-alive
|
|
482
|
+
socket holding a handle — was plausible, fitted the observation, and was WRONG; a bisect with
|
|
483
|
+
the suspected file excluded still reproduced it. At ~1 in 10, a handful of green runs is not
|
|
484
|
+
evidence of anything. Bisect, or do not claim a cause.
|
|
485
|
+
|
|
486
|
+
### Where the output actually came from
|
|
487
|
+
|
|
488
|
+
Worth recording, because `tests/setup.ts` looks like it already handles this and does not — and
|
|
489
|
+
because the obvious remedy is the wrong one.
|
|
490
|
+
|
|
491
|
+
**Only raw `console.*` calls feed the RPC. Nest `Logger` output does not.** vitest replaces
|
|
492
|
+
`globalThis.console` and nothing else; it does not patch `process.stdout`/`stderr`. Nest's
|
|
493
|
+
`ConsoleLogger` writes straight to those streams, so its output reaches the terminal without ever
|
|
494
|
+
becoming an `onUserConsoleLog` call. Verified both ways: a `[Nest] … DEBUG …` line carries no
|
|
495
|
+
`stdout | <file>` prefix, while every attributed line traces to a bare `console.*`.
|
|
496
|
+
|
|
497
|
+
The consequence is the useful part: **silencing the Nest logger does nothing for this flake.**
|
|
498
|
+
`Logger.overrideLogger(['error','fatal'])` — and any per-spec capture of `logger.error` — is noise
|
|
499
|
+
reduction, not a fix. Reaching for it because the loud lines look like the culprit is a dead end.
|
|
500
|
+
|
|
501
|
+
The writes that actually fed the RPC:
|
|
502
|
+
|
|
503
|
+
| Source | Call |
|
|
504
|
+
|--------|------|
|
|
505
|
+
| `common/helpers/config.helper.ts` | `console.info` — "Configured for: …", "No local config.json found!" |
|
|
506
|
+
| `common/services/config.service.ts` | `console.warn` from `mergeConfig` |
|
|
507
|
+
| `common/services/rate-limit-store.ts` | `console.warn` from `InMemoryRateLimitStore.hit` |
|
|
508
|
+
| `modules/hub/hub-buffer.ts` | `console.debug` from `readShared` |
|
|
509
|
+
| `modules/better-auth/…-email-verification.service.ts` | `console.log` from `logAuthUrlForDevelopment` |
|
|
510
|
+
|
|
511
|
+
### Separately: capture the error output a spec EXPECTS
|
|
512
|
+
|
|
513
|
+
Independent of the flake, and still worth doing — `captureExpectedLogs()` in
|
|
514
|
+
`tests/helpers/expected-log-output.ts`. A spec that deliberately drives a failure path (SMTP down,
|
|
515
|
+
Redis refused, GridFS chunks missing) otherwise prints `logger.error` plus stack traces on a GREEN
|
|
516
|
+
run. That is the same "output that is always there is output nobody reads" argument the rest of
|
|
517
|
+
this file makes, and the helper RETURNS what was logged so the message becomes an assertion rather
|
|
518
|
+
than noise. Four specs use it; three gained a real assertion in the process, and one —
|
|
519
|
+
`'re-throws a send failure after logging it'` — had never asserted the half of its name after the
|
|
520
|
+
comma.
|
|
521
|
+
|
|
522
|
+
Do not reach for a global silence instead: `Logger.overrideLogger([])` would also silence the
|
|
523
|
+
failing run, removing the diagnostics you need exactly when something breaks.
|
|
524
|
+
|
|
373
525
|
## A catch that asserts nothing makes its test pass on every outcome
|
|
374
526
|
|
|
375
527
|
**Rule: a `catch` block in a test either asserts something that could be false, or rethrows. Never
|
|
@@ -446,6 +598,33 @@ The vector predates 11.38.0 — Better-Auth already hashed on reset — so this
|
|
|
446
598
|
factor roughly doubling, not a new exposure. It is not scaffolded here because a load profile
|
|
447
599
|
belongs with a running API and an agreed traffic shape, not bolted onto a static review.
|
|
448
600
|
|
|
601
|
+
## A test that reads `CI` answers differently on a runner
|
|
602
|
+
|
|
603
|
+
**Rule: when a spec drives behaviour that depends on the `CI` environment variable, it must PIN the
|
|
604
|
+
variable — never inherit it.** Otherwise the assertion means one thing on a laptop and another on a
|
|
605
|
+
runner, and the laptop is where it gets written.
|
|
606
|
+
|
|
607
|
+
`scripts/check-overrides.mjs` is the case: an unverified suppression is TOLERATED locally and
|
|
608
|
+
ESCALATED to a hard failure under `CI`, deliberately, because a skip nobody reads is
|
|
609
|
+
indistinguishable from a check that ran. `tests/unit/check-overrides.guard.spec.ts` spawns that
|
|
610
|
+
guard, so every case it runs inherits whatever `CI` the surrounding process has.
|
|
611
|
+
|
|
612
|
+
One case did not pin it, asserted `status === 0`, and passed locally for its whole life. It failed
|
|
613
|
+
the release CI run for 11.40.0 — the first time it had ever executed on a runner. The fix is one
|
|
614
|
+
line (`env: { CI: '' }`); the point is that nothing would have found it earlier, because the
|
|
615
|
+
environment that breaks it is the one nobody runs tests in by hand.
|
|
616
|
+
|
|
617
|
+
**Before a release, run the unit suite the way a runner sees it:**
|
|
618
|
+
|
|
619
|
+
```bash
|
|
620
|
+
CI=true npx vitest run --config vitest.config.ts --reporter=dot
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
Deliberately NOT wired into `check`. It would run all 2381 unit tests a second time — about 40s on
|
|
624
|
+
every local check — to protect against a class that currently has exactly one member, and CI itself
|
|
625
|
+
already catches it at the cost of one failed PR run. Revisit that trade if a second env-dependent
|
|
626
|
+
spec appears; the balance is about how many, not about principle.
|
|
627
|
+
|
|
449
628
|
## Consumer gate: the starter runs BEFORE publish, not after
|
|
450
629
|
|
|
451
630
|
`pnpm run check:consumer` builds the tarball (`pnpm pack`), installs it into a **throwaway copy** of
|
package/CLAUDE.md
CHANGED
|
@@ -24,7 +24,8 @@ The following documents must be kept up to date when making changes that affect
|
|
|
24
24
|
| `.claude/rules/configurable-features.md` | Adding new configurable features |
|
|
25
25
|
| `src/templates/*.ejs` + `tests/unit/email-templates.spec.ts` | Changing a mail template — a template is never imported, type-checked or linted, so the only thing binding it to its caller is the variable names inside it. Add the caller's data shape to the spec |
|
|
26
26
|
| `FRAMEWORK-API.md` | Auto-regenerated by `pnpm run build` — verify after adding interfaces, CrudService methods, or core modules |
|
|
27
|
-
| `.claude/rules/
|
|
27
|
+
| `.claude/rules/package-management.md` | Changing the `overrides:` set, adding or removing an `auditConfig.ignoreGhsas` suppression, or changing the `check:overrides` guard. Same reasoning as the row below: the guard exists because an override and a suppression both decay in silence — and a guard nobody knows about decays exactly the same way |
|
|
28
|
+
| `.claude/rules/testing.md` | Changing the test-runner split, the per-run DB lifecycle or its **drop guard**, the run governor, the infrastructure containers, the regression-evidence gate, or **`disableConsoleIntercept`** (both runners set it; removing it to get per-file console attribution back re-arms an `EnvironmentTeardownError` that fails `check` roughly 1 run in 10 with every test green). This row exists because the drop guard — the one thing standing between a test run and a developer's data — went undocumented for its whole life: nothing in this table pointed at the file that describes everything around it |
|
|
28
29
|
|
|
29
30
|
**Rule:** When a code change adds, removes, or modifies a feature listed in `docs/REQUEST-LIFECYCLE.md` (Features Overview, diagrams, decorator reference, configuration, etc.), update the document in the same commit or PR.
|
|
30
31
|
|
|
@@ -131,6 +132,17 @@ pnpm run lint:fix # Auto-fix
|
|
|
131
132
|
pnpm run format # oxfmt format
|
|
132
133
|
|
|
133
134
|
# Import-cycle / SWC safety (part of `check`)
|
|
135
|
+
# Supply-chain guards (part of `check`)
|
|
136
|
+
pnpm run check:overrides # Cross-checks every pnpm override and every auditConfig.ignoreGhsas
|
|
137
|
+
# suppression against live advisory data. The only step that catches an
|
|
138
|
+
# override whose target drifted BELOW the advisory's fixed-in version:
|
|
139
|
+
# `pnpm audit` reports the advisory, but nothing otherwise says that a
|
|
140
|
+
# supposed remedy for it is already sitting in pnpm-workspace.yaml.
|
|
141
|
+
# Also catches a suppression upstream has since patched — those are
|
|
142
|
+
# invisible to `pnpm audit` by design, so nothing else can.
|
|
143
|
+
# See .claude/rules/package-management.md → "Overrides AGE"
|
|
144
|
+
pnpm peers check # pnpm 11 builtin: unmet/missing peer dependencies, read from the lockfile
|
|
145
|
+
|
|
134
146
|
pnpm run check:swc-tdz # SWC→CJS build, loads EVERY module as its own entry point.
|
|
135
147
|
# The only step that catches a temporal-dead-zone crash from an
|
|
136
148
|
# import cycle — tsc, vitest and oxlint are all blind to it.
|
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
|
|
3
|
+
> Auto-generated from source code as of 2026-09-04 (v11.40.0)
|
|
4
4
|
> File: `FRAMEWORK-API.md` — compact, machine-readable API surface for Claude Code
|
|
5
5
|
|
|
6
6
|
## CoreModule.forRoot()
|
|
@@ -109,7 +109,7 @@ When `passkey` is enabled, `trustedOrigins` is required (compile-time enforcemen
|
|
|
109
109
|
|
|
110
110
|
### IAi
|
|
111
111
|
|
|
112
|
-
- `allowedBaseUrlHosts?`: `string[] | undefined` — Optional SSRF allowlist for connection base URLs. When set (non-empty), the
|
|
112
|
+
- `allowedBaseUrlHosts?`: `string | string[] | undefined` — Optional SSRF allowlist for connection base URLs. When set (non-empty), the
|
|
113
113
|
- `audit?`: `boolean | undefined` (default: `false`) — Persist an audit record (`aiInteractions`) for every prompt run (admin-readable).
|
|
114
114
|
- `budget?`: `{ period?: "day" | "month" | "none"; tenant?: { maxPrompts?: number; maxToken...` — Token/prompt budgets for AI prompts, enforced before a run (HTTP 429 + translated
|
|
115
115
|
- `capabilityDriftCheck?`: `boolean | undefined` (default: `false`) — Opt-in boot self-check: after startup, probe each enabled connection that declares
|
|
@@ -9,6 +9,8 @@ export declare class OpenAiCompatibleProvider implements ILlmProvider {
|
|
|
9
9
|
constructor(connection: ResolvedAiConnection);
|
|
10
10
|
chat(messages: LlmMessage[], tools: LlmToolSchema[], options?: LlmCompletionOptions): Promise<LlmResponse>;
|
|
11
11
|
protected assertBaseUrlAllowed(url: string): void;
|
|
12
|
+
protected resolveAllowedBaseUrlHosts(): string[];
|
|
13
|
+
protected normaliseHostEntry(value: string): string;
|
|
12
14
|
detectCapabilities(): Promise<{
|
|
13
15
|
jsonResponse?: boolean;
|
|
14
16
|
nativeTools?: boolean;
|
|
@@ -84,8 +84,8 @@ class OpenAiCompatibleProvider {
|
|
|
84
84
|
};
|
|
85
85
|
}
|
|
86
86
|
assertBaseUrlAllowed(url) {
|
|
87
|
-
const allowedHosts =
|
|
88
|
-
if (!
|
|
87
|
+
const allowedHosts = this.resolveAllowedBaseUrlHosts();
|
|
88
|
+
if (!allowedHosts.length) {
|
|
89
89
|
return;
|
|
90
90
|
}
|
|
91
91
|
let parsed;
|
|
@@ -95,11 +95,35 @@ class OpenAiCompatibleProvider {
|
|
|
95
95
|
catch {
|
|
96
96
|
throw new common_1.ServiceUnavailableException(error_code_1.ErrorCode.AI_CONNECTION_INVALID_URL);
|
|
97
97
|
}
|
|
98
|
-
|
|
98
|
+
const defaultPort = parsed.protocol === 'https:' ? '443' : parsed.protocol === 'http:' ? '80' : '';
|
|
99
|
+
const candidates = [parsed.host, parsed.hostname];
|
|
100
|
+
if (defaultPort && parsed.host === parsed.hostname) {
|
|
101
|
+
candidates.push(`${parsed.hostname}:${defaultPort}`);
|
|
102
|
+
}
|
|
103
|
+
if (!candidates.map((candidate) => this.normaliseHostEntry(candidate)).some((c) => allowedHosts.includes(c))) {
|
|
99
104
|
this.logger.warn(`AI connection "${this.connection.name}" host "${parsed.host}" is not in ai.allowedBaseUrlHosts`);
|
|
100
105
|
throw new common_1.ServiceUnavailableException(error_code_1.ErrorCode.AI_CONNECTION_NOT_AVAILABLE);
|
|
101
106
|
}
|
|
102
107
|
}
|
|
108
|
+
resolveAllowedBaseUrlHosts() {
|
|
109
|
+
const configured = config_service_1.ConfigService.get('ai.allowedBaseUrlHosts');
|
|
110
|
+
if (configured === undefined || configured === null) {
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
const entries = typeof configured === 'string' ? configured.split(',') : configured;
|
|
114
|
+
if (!Array.isArray(entries)) {
|
|
115
|
+
this.logger.error(`ai.allowedBaseUrlHosts is a ${typeof configured} and carries no hostnames — the SSRF egress ` +
|
|
116
|
+
'allowlist is NOT active. Use an array or a comma-separated string.');
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
return entries.map((host) => this.normaliseHostEntry(String(host))).filter(Boolean);
|
|
120
|
+
}
|
|
121
|
+
normaliseHostEntry(value) {
|
|
122
|
+
return value
|
|
123
|
+
.trim()
|
|
124
|
+
.toLowerCase()
|
|
125
|
+
.replace(/\.(?=$|:)/, '');
|
|
126
|
+
}
|
|
103
127
|
async detectCapabilities() {
|
|
104
128
|
const result = {};
|
|
105
129
|
if (this.connection.supportsJsonResponse === undefined) {
|
|
@@ -179,6 +203,7 @@ class OpenAiCompatibleProvider {
|
|
|
179
203
|
if (!base.startsWith('http')) {
|
|
180
204
|
return undefined;
|
|
181
205
|
}
|
|
206
|
+
this.assertBaseUrlAllowed(`${base}/api/show`);
|
|
182
207
|
const response = await fetch(`${base}/api/show`, {
|
|
183
208
|
body: JSON.stringify({ name: this.connection.model }),
|
|
184
209
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-compatible.provider.js","sourceRoot":"","sources":["../../../../../src/core/modules/ai/providers/openai-compatible.provider.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"openai-compatible.provider.js","sourceRoot":"","sources":["../../../../../src/core/modules/ai/providers/openai-compatible.provider.ts"],"names":[],"mappings":"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"}
|