@lenne.tech/nest-server 11.27.5 → 11.27.7
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/architecture.md +66 -0
- package/.claude/rules/better-auth.md +88 -2
- package/.claude/rules/configurable-features.md +2 -2
- package/.claude/rules/package-management.md +23 -14
- package/.claude/rules/testing.md +27 -9
- package/CLAUDE.md +12 -4
- package/FRAMEWORK-API.md +1 -1
- package/bin/migrate.js +84 -25
- package/dist/core/common/decorators/restricted.decorator.d.ts +4 -4
- package/dist/core/common/decorators/restricted.decorator.js +21 -22
- package/dist/core/common/decorators/restricted.decorator.js.map +1 -1
- package/dist/core/common/helpers/clone.helper.d.ts +6 -0
- package/dist/core/common/helpers/clone.helper.js +67 -0
- package/dist/core/common/helpers/clone.helper.js.map +1 -0
- package/dist/core/common/helpers/cookies.helper.d.ts +1 -0
- package/dist/core/common/helpers/cookies.helper.js +33 -16
- package/dist/core/common/helpers/cookies.helper.js.map +1 -1
- package/dist/core/common/helpers/db.helper.d.ts +2 -14
- package/dist/core/common/helpers/db.helper.js +13 -106
- package/dist/core/common/helpers/db.helper.js.map +1 -1
- package/dist/core/common/helpers/id.helper.d.ts +15 -0
- package/dist/core/common/helpers/id.helper.js +104 -0
- package/dist/core/common/helpers/id.helper.js.map +1 -0
- package/dist/core/common/helpers/input.helper.d.ts +1 -6
- package/dist/core/common/helpers/input.helper.js +11 -70
- package/dist/core/common/helpers/input.helper.js.map +1 -1
- package/dist/core/common/inputs/combined-filter.input.d.ts +1 -12
- package/dist/core/common/inputs/combined-filter.input.js +2 -51
- package/dist/core/common/inputs/combined-filter.input.js.map +1 -1
- package/dist/core/common/inputs/filter.input.d.ts +10 -1
- package/dist/core/common/inputs/filter.input.js +40 -5
- package/dist/core/common/inputs/filter.input.js.map +1 -1
- package/dist/core/common/services/config.service.js +5 -5
- package/dist/core/common/services/config.service.js.map +1 -1
- package/dist/core/modules/ai/core-ai.constants.d.ts +22 -0
- package/dist/core/modules/ai/core-ai.constants.js +26 -0
- package/dist/core/modules/ai/core-ai.constants.js.map +1 -0
- package/dist/core/modules/ai/index.d.ts +1 -0
- package/dist/core/modules/ai/index.js +1 -0
- package/dist/core/modules/ai/index.js.map +1 -1
- package/dist/core/modules/ai/interfaces/ai-interaction-record.interface.d.ts +17 -0
- package/dist/core/modules/ai/interfaces/ai-interaction-record.interface.js +3 -0
- package/dist/core/modules/ai/interfaces/ai-interaction-record.interface.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai-budget.service.d.ts +1 -2
- package/dist/core/modules/ai/services/core-ai-budget.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-budget.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-connection-preference.service.d.ts +1 -2
- package/dist/core/modules/ai/services/core-ai-connection-preference.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-connection-preference.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-connection.service.d.ts +1 -2
- package/dist/core/modules/ai/services/core-ai-connection.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-connection.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-conversation.service.d.ts +1 -2
- package/dist/core/modules/ai/services/core-ai-conversation.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-conversation.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-interaction.service.d.ts +2 -3
- package/dist/core/modules/ai/services/core-ai-interaction.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-interaction.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-mode.service.d.ts +1 -2
- package/dist/core/modules/ai/services/core-ai-mode.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-mode.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-prompt-hint.service.d.ts +1 -3
- package/dist/core/modules/ai/services/core-ai-prompt-hint.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-prompt-hint.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-prompt.service.d.ts +1 -2
- package/dist/core/modules/ai/services/core-ai-prompt.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-prompt.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-slot.service.d.ts +1 -2
- package/dist/core/modules/ai/services/core-ai-slot.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-slot.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-tool-grant.service.d.ts +1 -2
- package/dist/core/modules/ai/services/core-ai-tool-grant.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-tool-grant.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai-tool-policy.service.d.ts +1 -2
- package/dist/core/modules/ai/services/core-ai-tool-policy.service.js +7 -5
- package/dist/core/modules/ai/services/core-ai-tool-policy.service.js.map +1 -1
- package/dist/core/modules/ai/services/core-ai.service.d.ts +2 -17
- package/dist/core/modules/ai/services/core-ai.service.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth-roles.guard.js +2 -2
- package/dist/core/modules/better-auth/better-auth-roles.guard.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth.config.js +12 -8
- package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth.constants.d.ts +3 -0
- package/dist/core/modules/better-auth/core-better-auth.constants.js +7 -0
- package/dist/core/modules/better-auth/core-better-auth.constants.js.map +1 -0
- package/dist/core/modules/better-auth/core-better-auth.module.d.ts +1 -2
- package/dist/core/modules/better-auth/core-better-auth.module.js +23 -20
- package/dist/core/modules/better-auth/core-better-auth.module.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth.registry.d.ts +4 -0
- package/dist/core/modules/better-auth/core-better-auth.registry.js +16 -0
- package/dist/core/modules/better-auth/core-better-auth.registry.js.map +1 -0
- package/dist/core/modules/better-auth/core-better-auth.service.d.ts +1 -2
- package/dist/core/modules/better-auth/core-better-auth.service.js +7 -6
- package/dist/core/modules/better-auth/core-better-auth.service.js.map +1 -1
- package/dist/core/modules/better-auth/index.d.ts +1 -0
- package/dist/core/modules/better-auth/index.js +1 -0
- package/dist/core/modules/better-auth/index.js.map +1 -1
- package/dist/core/modules/migrate/migration-runner.d.ts +1 -0
- package/dist/core/modules/migrate/migration-runner.js +3 -2
- package/dist/core/modules/migrate/migration-runner.js.map +1 -1
- package/dist/core/modules/tus/tus.constants.d.ts +1 -0
- package/dist/core/modules/tus/tus.constants.js +5 -0
- package/dist/core/modules/tus/tus.constants.js.map +1 -0
- package/dist/core/modules/tus/tus.module.d.ts +1 -1
- package/dist/core/modules/tus/tus.module.js +8 -6
- package/dist/core/modules/tus/tus.module.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/docs/REQUEST-LIFECYCLE.md +17 -4
- package/migration-guides/11.27.5-to-11.27.6.md +359 -0
- package/migration-guides/11.27.6-to-11.27.7.md +374 -0
- package/package.json +11 -104
- package/src/core/common/decorators/restricted.decorator.ts +33 -8
- package/src/core/common/helpers/clone.helper.ts +110 -0
- package/src/core/common/helpers/cookies.helper.ts +101 -26
- package/src/core/common/helpers/db.helper.ts +14 -161
- package/src/core/common/helpers/id.helper.ts +198 -0
- package/src/core/common/helpers/input.helper.ts +12 -84
- package/src/core/common/inputs/combined-filter.input.ts +10 -57
- package/src/core/common/inputs/filter.input.ts +92 -1
- package/src/core/common/interfaces/server-options.interface.ts +35 -6
- package/src/core/common/services/config.service.ts +4 -1
- package/src/core/modules/ai/core-ai.constants.ts +92 -0
- package/src/core/modules/ai/index.ts +1 -0
- package/src/core/modules/ai/interfaces/ai-interaction-record.interface.ts +34 -0
- package/src/core/modules/ai/services/core-ai-budget.service.ts +8 -4
- package/src/core/modules/ai/services/core-ai-connection-preference.service.ts +8 -4
- package/src/core/modules/ai/services/core-ai-connection.service.ts +5 -6
- package/src/core/modules/ai/services/core-ai-conversation.service.ts +5 -6
- package/src/core/modules/ai/services/core-ai-interaction.service.ts +6 -7
- package/src/core/modules/ai/services/core-ai-mode.service.ts +8 -2
- package/src/core/modules/ai/services/core-ai-prompt-hint.service.ts +7 -4
- package/src/core/modules/ai/services/core-ai-prompt.service.ts +8 -2
- package/src/core/modules/ai/services/core-ai-slot.service.ts +7 -4
- package/src/core/modules/ai/services/core-ai-tool-grant.service.ts +8 -4
- package/src/core/modules/ai/services/core-ai-tool-policy.service.ts +8 -4
- package/src/core/modules/ai/services/core-ai.service.ts +8 -11
- package/src/core/modules/better-auth/README.md +10 -4
- package/src/core/modules/better-auth/better-auth-roles.guard.ts +11 -5
- package/src/core/modules/better-auth/better-auth.config.ts +90 -15
- package/src/core/modules/better-auth/core-better-auth.constants.ts +73 -0
- package/src/core/modules/better-auth/core-better-auth.module.ts +34 -8
- package/src/core/modules/better-auth/core-better-auth.registry.ts +53 -0
- package/src/core/modules/better-auth/core-better-auth.service.ts +19 -12
- package/src/core/modules/better-auth/index.ts +9 -0
- package/src/core/modules/migrate/migration-runner.ts +16 -2
- package/src/core/modules/tus/tus.constants.ts +25 -0
- package/src/core/modules/tus/tus.module.ts +7 -2
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
# Migration Guide: 11.27.6 → 11.27.7
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
| Category | Details |
|
|
6
|
+
|----------|---------|
|
|
7
|
+
| **Breaking Changes** | None |
|
|
8
|
+
| **New Features** | None. Four new leaf modules (`core-better-auth.constants.ts`, `core-better-auth.registry.ts`, `id.helper.ts`, `clone.helper.ts`) — the tokens and helpers they hold were already public and stay reachable from their old locations. The registry is module-internal and deliberately **not** exported. |
|
|
9
|
+
| **Public API** | Unchanged. Verified by diffing the full export surface of `src/index.ts` on both versions: **nothing removed, nothing renamed**. |
|
|
10
|
+
| **Bugfixes** | **(1)** Applications compiled with **SWC** (`nest start -b swc`, `nest build -b swc`) no longer crash at startup with `ReferenceError: Cannot access 'BETTER_AUTH_INSTANCE' before initialization` when BetterAuth is enabled. **(2)** A direct import of `core/common/inputs/combined-filter.input` no longer crashes under SWC with `ReferenceError: Cannot access 'CombinedFilterInput' before initialization`. **(3)** A consumer setting `betterAuth.options.advanced.defaultCookieAttributes` no longer silently strips the `Secure` flag from session cookies on an `https://` deployment. |
|
|
11
|
+
| **Security** | See bugfix (3). If your project sets `advanced.defaultCookieAttributes` for any reason (cookie partitioning, a custom domain) **and** runs on an `https://` baseURL, your session cookies were being sent without `Secure`. Updating fixes this with no action required. |
|
|
12
|
+
| **Deprecations** | The BetterAuth DI tokens re-exported from `core-better-auth.module` / `core-better-auth.service` are now marked deprecated in their docblocks. Import them from `core-better-auth.constants` (or the package root) instead. Both paths keep working. |
|
|
13
|
+
| **Toolchain** | The framework repo moved to **pnpm 11** (see the note below). **npm consumers are unaffected** — you do not inherit the framework's `packageManager` or `pnpm-workspace.yaml`. Relevant only if you contribute to the framework or mirror its toolchain. |
|
|
14
|
+
| **Migration Effort** | **npm mode:** 0 minutes (automatic) — `pnpm update` is enough. **Vendor mode:** see the note below — the BetterAuth change is an atomic file set. |
|
|
15
|
+
|
|
16
|
+
This is a **startup-crash + cookie-security bugfix release**. No source-code or
|
|
17
|
+
config changes are required in consuming projects.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Toolchain: pnpm 11 (framework contributors only)
|
|
22
|
+
|
|
23
|
+
**npm consumers of `@lenne.tech/nest-server` can ignore this section** — installing the
|
|
24
|
+
package does not import our package manager or its config.
|
|
25
|
+
|
|
26
|
+
The framework repo itself upgraded from pnpm 10 to **pnpm 11**, for one concrete reason:
|
|
27
|
+
**`pnpm audit` is broken on every pnpm 10.x** — npm retired the legacy audit endpoint
|
|
28
|
+
(HTTP 410) and only pnpm 11 uses the working bulk-advisory endpoint. The upgrade also
|
|
29
|
+
required migrating pnpm's config, because pnpm 11 has breaking changes:
|
|
30
|
+
|
|
31
|
+
- **The `pnpm` field in `package.json` is gone.** All pnpm settings moved to
|
|
32
|
+
`pnpm-workspace.yaml`: `overrides`, `allowBuilds`, `nodeLinker`, `autoInstallPeers`,
|
|
33
|
+
`strictPeerDependencies`, `peerDependencyRules`. `.npmrc` is now auth/registry only.
|
|
34
|
+
- **`allowBuilds` replaced `onlyBuiltDependencies`** — a map that must classify *every*
|
|
35
|
+
package with an install script as `true` (build it, e.g. `bcrypt`) or `false` (don't,
|
|
36
|
+
e.g. the `@scarf/scarf` telemetry). An unclassified build-script package makes
|
|
37
|
+
`pnpm install` exit non-zero.
|
|
38
|
+
- **Security overrides pruned 36 → 9.** Only entries still load-bearing (removing them
|
|
39
|
+
lets the package resolve back into its vulnerable range) were kept; `pnpm audit` on
|
|
40
|
+
pnpm 11 confirms the pruned set is still clean.
|
|
41
|
+
|
|
42
|
+
CI (`pnpm/action-setup`) and Docker (`corepack`) follow the `packageManager` field, so no
|
|
43
|
+
workflow or Dockerfile edits were needed — they use pnpm 11 automatically.
|
|
44
|
+
|
|
45
|
+
**If you develop against or vendor the framework's toolchain:** switch to pnpm 11
|
|
46
|
+
(`corepack use pnpm@11` or let corepack follow `packageManager`), and move any
|
|
47
|
+
`package.json#pnpm` settings you have into `pnpm-workspace.yaml`. See
|
|
48
|
+
`.claude/rules/package-management.md` for the full pattern.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Quick Migration
|
|
53
|
+
|
|
54
|
+
No code changes required.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Update package
|
|
58
|
+
pnpm add @lenne.tech/nest-server@11.27.7
|
|
59
|
+
|
|
60
|
+
# Verify build
|
|
61
|
+
pnpm run build
|
|
62
|
+
|
|
63
|
+
# Run tests
|
|
64
|
+
pnpm test
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## What's Fixed in 11.27.7
|
|
70
|
+
|
|
71
|
+
### Startup crash under the SWC compiler
|
|
72
|
+
|
|
73
|
+
**The symptom.** With BetterAuth enabled and the app started or built via SWC:
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
ReferenceError: Cannot access 'BETTER_AUTH_INSTANCE' before initialization
|
|
77
|
+
at core-better-auth.module.ts
|
|
78
|
+
at core-better-auth.service.ts
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
This affected anyone using `nest start -b swc` / `nest build -b swc` — including
|
|
82
|
+
the `start:dev:swc` and `start:local:swc` scripts shipped in the starter. Projects
|
|
83
|
+
building with the default `tsc` builder were **not** affected.
|
|
84
|
+
|
|
85
|
+
**The bug.** The three BetterAuth dependency-injection tokens were split across two
|
|
86
|
+
files that imported each other:
|
|
87
|
+
|
|
88
|
+
- `BETTER_AUTH_INSTANCE` was declared in `core-better-auth.module.ts`
|
|
89
|
+
- `BETTER_AUTH_CONFIG` and `BETTER_AUTH_COOKIE_DOMAIN` were declared in `core-better-auth.service.ts`
|
|
90
|
+
|
|
91
|
+
The service imported the first token from the module, and the module imported the
|
|
92
|
+
other two — plus the service class itself — back from the service. A genuine import
|
|
93
|
+
cycle.
|
|
94
|
+
|
|
95
|
+
The cycle alone would have been survivable. What made it fatal is *when* the token
|
|
96
|
+
is read: `@Inject(BETTER_AUTH_INSTANCE)` is a **constructor-parameter decorator**,
|
|
97
|
+
and decorator arguments are evaluated when the class is *defined* — that is, while
|
|
98
|
+
the module is still initializing. On a cycle, the importing side reads a `const`
|
|
99
|
+
that is still in its temporal dead zone.
|
|
100
|
+
|
|
101
|
+
Under `tsc`/CommonJS the evaluation order happened to work out. Under SWC it did
|
|
102
|
+
not, and the app died at startup.
|
|
103
|
+
|
|
104
|
+
**The fix.** All three tokens moved into a new **import-free leaf module**,
|
|
105
|
+
`core-better-auth.constants.ts`. A file with zero imports can never be
|
|
106
|
+
mid-evaluation when someone imports it — in any module system, under any compiler —
|
|
107
|
+
so the initialization order is now deterministic everywhere.
|
|
108
|
+
|
|
109
|
+
A second leaf, `core-better-auth.registry.ts`, does the same for the
|
|
110
|
+
`BetterAuthTokenService` reference that `BetterAuthRolesGuard` looks up statically,
|
|
111
|
+
removing the last import cycle inside the module. As a side effect this also fixes a
|
|
112
|
+
test-isolation leak: `CoreBetterAuthModule.reset()` previously did not clear that
|
|
113
|
+
reference, so a token service could survive into the next testing module.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Deprecations
|
|
118
|
+
|
|
119
|
+
The tokens are still re-exported from their old locations, so **every existing import
|
|
120
|
+
keeps working**:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
// Still works (now @deprecated)
|
|
124
|
+
import { BETTER_AUTH_INSTANCE } from '@lenne.tech/nest-server/dist/core/modules/better-auth/core-better-auth.module';
|
|
125
|
+
import { BETTER_AUTH_CONFIG } from '@lenne.tech/nest-server/dist/core/modules/better-auth/core-better-auth.service';
|
|
126
|
+
|
|
127
|
+
// Preferred
|
|
128
|
+
import { BETTER_AUTH_CONFIG, BETTER_AUTH_INSTANCE } from '@lenne.tech/nest-server';
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Importing from the package root (`@lenne.tech/nest-server`) was already the
|
|
132
|
+
recommended path and is unaffected — **most projects need to change nothing.**
|
|
133
|
+
|
|
134
|
+
The deprecated re-exports will be removed in a future MINOR.
|
|
135
|
+
|
|
136
|
+
> **The token string values are unchanged** (`'BETTER_AUTH_INSTANCE'`,
|
|
137
|
+
> `'BETTER_AUTH_CONFIG'`, `'BETTER_AUTH_COOKIE_DOMAIN'`), so `@Inject('BETTER_AUTH_INSTANCE')`
|
|
138
|
+
> written as a string literal keeps resolving. A new unit test pins these values
|
|
139
|
+
> precisely because they are part of the public contract.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Vendor Mode: five atomic file sets
|
|
144
|
+
|
|
145
|
+
Projects that vendor the framework core (`projects/api/src/core/`) sync via the
|
|
146
|
+
`/lt-dev:backend:update-nest-server-core` agent rather than `pnpm update`.
|
|
147
|
+
|
|
148
|
+
Every change in this release works the same way: a symbol moved into a new **leaf**
|
|
149
|
+
file, and its old home now re-exports it. That makes each one an **atomic set** —
|
|
150
|
+
adopt the edits without the new file and you get an unresolvable import and a broken
|
|
151
|
+
build.
|
|
152
|
+
|
|
153
|
+
**Seven files are new.** If a sync is interrupted, verify all seven exist before
|
|
154
|
+
building:
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
core/modules/better-auth/core-better-auth.constants.ts
|
|
158
|
+
core/modules/better-auth/core-better-auth.registry.ts
|
|
159
|
+
core/modules/ai/core-ai.constants.ts
|
|
160
|
+
core/modules/ai/interfaces/ai-interaction-record.interface.ts
|
|
161
|
+
core/modules/tus/tus.constants.ts
|
|
162
|
+
core/common/helpers/id.helper.ts
|
|
163
|
+
core/common/helpers/clone.helper.ts
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
> **Expect merge conflicts on locally-patched files.** If your project has local edits
|
|
167
|
+
> in `db.helper.ts`, `input.helper.ts`, `filter.input.ts`, `restricted.decorator.ts`
|
|
168
|
+
> or any `ai/services/*.service.ts`, this release moves code *out* of them — the sync
|
|
169
|
+
> will conflict there. The resolution is always the same: keep your local logic, keep
|
|
170
|
+
> the new `import` + `export … from` lines pointing at the leaf, and do not restore the
|
|
171
|
+
> declarations that moved out.
|
|
172
|
+
|
|
173
|
+
**Set 1 — BetterAuth DI tokens**
|
|
174
|
+
|
|
175
|
+
| File | Change |
|
|
176
|
+
|------|--------|
|
|
177
|
+
| `core/modules/better-auth/core-better-auth.constants.ts` | 🆕 the token leaf |
|
|
178
|
+
| `core/modules/better-auth/core-better-auth.registry.ts` | 🆕 the token-service leaf |
|
|
179
|
+
| `core/modules/better-auth/core-better-auth.module.ts` | takes tokens from the constants leaf; delegates the token-service lookup to the registry |
|
|
180
|
+
| `core/modules/better-auth/core-better-auth.service.ts` | takes tokens from the constants leaf |
|
|
181
|
+
| `core/modules/better-auth/better-auth-roles.guard.ts` | reads the registry instead of importing the module |
|
|
182
|
+
| `core/modules/better-auth/index.ts` | exports the constants leaf (the registry is deliberately **not** exported — it is module-internal) |
|
|
183
|
+
|
|
184
|
+
**Set 2 — core helpers** (this is what takes `restricted.decorator` off its cycles)
|
|
185
|
+
|
|
186
|
+
| File | Change |
|
|
187
|
+
|------|--------|
|
|
188
|
+
| `core/common/helpers/id.helper.ts` | 🆕 the ID cluster (`equalIds`, `getIncludedIds`, `getStringIds`, `getObjectIds`) |
|
|
189
|
+
| `core/common/helpers/clone.helper.ts` | 🆕 `clone`, `deepFreeze` |
|
|
190
|
+
| `core/common/helpers/db.helper.ts` | ID cluster removed; **re-exports it** from `id.helper` |
|
|
191
|
+
| `core/common/helpers/input.helper.ts` | `clone`/`deepFreeze` removed; **re-exports them** from `clone.helper`; takes `equalIds` from `id.helper` |
|
|
192
|
+
| `core/common/services/config.service.ts` | takes `clone`/`deepFreeze` from `clone.helper` |
|
|
193
|
+
| `core/common/decorators/restricted.decorator.ts` | takes the ID helpers from `id.helper`; its three exports become hoisted `function` declarations |
|
|
194
|
+
|
|
195
|
+
**Set 3 — filter inputs**
|
|
196
|
+
|
|
197
|
+
| File | Change |
|
|
198
|
+
|------|--------|
|
|
199
|
+
| `core/common/inputs/filter.input.ts` | now declares **both** `CombinedFilterInput` (first) and `FilterInput` — the order is load-bearing |
|
|
200
|
+
| `core/common/inputs/combined-filter.input.ts` | reduced to a re-export shim |
|
|
201
|
+
|
|
202
|
+
**Set 4 — AI module** (22 DI tokens + the type that closed the last AI cycle)
|
|
203
|
+
|
|
204
|
+
| File | Change |
|
|
205
|
+
|------|--------|
|
|
206
|
+
| `core/modules/ai/core-ai.constants.ts` | 🆕 all 22 `AI_*_MODEL` / `AI_*_CLASS` tokens |
|
|
207
|
+
| `core/modules/ai/interfaces/ai-interaction-record.interface.ts` | 🆕 `AiInteractionRecord` |
|
|
208
|
+
| `core/modules/ai/services/*.service.ts` (11 files) | tokens removed; each **re-exports its own** from the constants leaf |
|
|
209
|
+
| `core/modules/ai/services/core-ai.service.ts` | `AiInteractionRecord` removed; **re-exports it** from the interface leaf |
|
|
210
|
+
| `core/modules/ai/services/core-ai-interaction.service.ts` | takes the type from the interface leaf — no longer imports `core-ai.service` at all |
|
|
211
|
+
| `core/modules/ai/index.ts` | exports the interface leaf |
|
|
212
|
+
|
|
213
|
+
> If your project registered custom AI models via these tokens, nothing changes —
|
|
214
|
+
> the values are unchanged and every old import path still resolves.
|
|
215
|
+
|
|
216
|
+
**Set 5 — TUS module**
|
|
217
|
+
|
|
218
|
+
| File | Change |
|
|
219
|
+
|------|--------|
|
|
220
|
+
| `core/modules/tus/tus.constants.ts` | 🆕 `TUS_CONFIG` |
|
|
221
|
+
| `core/modules/tus/tus.module.ts` | token removed; **re-exports it** from the leaf |
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
> ### Do not "clean up" the re-export lines
|
|
226
|
+
>
|
|
227
|
+
> `db.helper.ts`, `input.helper.ts`, `combined-filter.input.ts`, `core-better-auth.module.ts`,
|
|
228
|
+
> `core-better-auth.service.ts`, `tus.module.ts`, `core-ai.service.ts` and all eleven
|
|
229
|
+
> `ai/services/*.service.ts` files now carry `export { … } from './…'` lines that look
|
|
230
|
+
> exactly like dead code.
|
|
231
|
+
>
|
|
232
|
+
> They are not. They are the *entire* backward-compatibility layer: this package has no
|
|
233
|
+
> `exports` map, so consumers deep-import these files directly, and deleting one line
|
|
234
|
+
> breaks every one of them — **with nothing turning red**, because the symbol is still
|
|
235
|
+
> exported from the package root.
|
|
236
|
+
>
|
|
237
|
+
> The framework pins them with a test (`tests/unit/import-cycle-invariants.spec.ts`) for
|
|
238
|
+
> exactly this reason. Keep the equivalent lines in your vendored copy.
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Also fixed: `CombinedFilterInput` crashed on a direct import
|
|
243
|
+
|
|
244
|
+
Same bug class, different module. `FilterInput` and `CombinedFilterInput` lived in
|
|
245
|
+
two files that imported each other, and `FilterInput` referenced
|
|
246
|
+
`CombinedFilterInput` **eagerly** — in a decorator argument and in the `design:type`
|
|
247
|
+
metadata `emitDecoratorMetadata` emits. Under SWC:
|
|
248
|
+
|
|
249
|
+
```
|
|
250
|
+
require('.../core/common/inputs/combined-filter.input.js')
|
|
251
|
+
→ ReferenceError: Cannot access 'CombinedFilterInput' before initialization
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
This only stayed hidden because importing from the package root pulls `filter.input`
|
|
255
|
+
in first. A **deep import** of `combined-filter.input` — plausible in vendor mode or
|
|
256
|
+
in a unit test — hit the crash.
|
|
257
|
+
|
|
258
|
+
Both classes now live in `filter.input.ts` (declaration order matters), and
|
|
259
|
+
`combined-filter.input.ts` re-exports `CombinedFilterInput`. **Every existing import
|
|
260
|
+
path still resolves**, including deep imports of either file.
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Also fixed (security): `Secure` could be stripped from session cookies
|
|
265
|
+
|
|
266
|
+
If a project sets `betterAuth.options.advanced.defaultCookieAttributes` — for cookie
|
|
267
|
+
partitioning, a custom domain, anything — that object **wholesale-replaced** the
|
|
268
|
+
framework's own `{ secure: true }`, because the merge was shallow. On an `https://`
|
|
269
|
+
baseURL the result was session cookies without the `Secure` attribute, forwarded
|
|
270
|
+
verbatim by BetterAuth's native handlers (2FA verify, social callback, magic link).
|
|
271
|
+
No error, no warning.
|
|
272
|
+
|
|
273
|
+
```ts
|
|
274
|
+
// Before 11.27.7 — on an https baseURL:
|
|
275
|
+
betterAuth: { options: { advanced: { defaultCookieAttributes: { partitioned: true } } } }
|
|
276
|
+
// → Set-Cookie: iam.session_token=…; HttpOnly; SameSite=Lax ← Secure GONE
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
The merge is now deep for that one key: `secure: true` is the base and your keys
|
|
280
|
+
spread over it. An **explicit** `{ secure: false }` still wins — this guards against
|
|
281
|
+
silent clobbering, not against a deliberate choice.
|
|
282
|
+
|
|
283
|
+
**No action required.** If you set `defaultCookieAttributes` and run on HTTPS, the
|
|
284
|
+
fix applies automatically on update.
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## New: SWC regression guard
|
|
289
|
+
|
|
290
|
+
The bug had the worst possible failure profile — **it passed a fully green CI and
|
|
291
|
+
crashed only for consumers.** `nest build` uses `tsc`, and vitest runs SWC through
|
|
292
|
+
Vite's module runner, whose getter-based live bindings tolerate import cycles. So
|
|
293
|
+
neither the build nor 2000+ tests could see it.
|
|
294
|
+
|
|
295
|
+
A new check step closes that hole:
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
pnpm run check:swc-tdz
|
|
299
|
+
# = nest build -b swc -p tsconfig.swc-tdz.json && node scripts/check-swc-tdz.mjs
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
It compiles with SWC to CommonJS and loads **every compiled module as its own entry
|
|
303
|
+
point** under Node's CJS loader — the exact path that fails.
|
|
304
|
+
|
|
305
|
+
Loading only the package barrel is *not* sufficient, and that is not a theoretical
|
|
306
|
+
point: whether such a cycle throws depends on which module the graph is entered
|
|
307
|
+
through. The `CombinedFilterInput` crash above was invisible to a barrel-only load,
|
|
308
|
+
because the barrel happens to pull `filter.input` in first. Requiring each file
|
|
309
|
+
separately is what surfaces it.
|
|
310
|
+
|
|
311
|
+
It builds into its own throwaway directory (`dist-swc-tdz/`, removed on success,
|
|
312
|
+
kept on failure so you can inspect the emit), so it never touches your real `dist/`.
|
|
313
|
+
It is wired into `check:raw` — ahead of the test step, so a cycle fails in seconds
|
|
314
|
+
rather than after the full suite — and into the CI workflow.
|
|
315
|
+
|
|
316
|
+
### Copying it into your own project
|
|
317
|
+
|
|
318
|
+
**Worth doing if you build or run with SWC** (`nest start -b swc`, `start:dev:swc`):
|
|
319
|
+
it costs a few seconds, needs no database, and is the only thing that catches this
|
|
320
|
+
bug class.
|
|
321
|
+
|
|
322
|
+
Note that `scripts/` is **not** part of the published npm package, so you cannot
|
|
323
|
+
copy it out of `node_modules`. Take the three pieces from the repository:
|
|
324
|
+
|
|
325
|
+
- [`scripts/check-swc-tdz.mjs`](https://github.com/lenneTech/nest-server/blob/develop/scripts/check-swc-tdz.mjs)
|
|
326
|
+
- [`tsconfig.swc-tdz.json`](https://github.com/lenneTech/nest-server/blob/develop/tsconfig.swc-tdz.json)
|
|
327
|
+
- the `check:swc-tdz` script entry in `package.json`, plus `dist-swc-tdz` in `.gitignore`
|
|
328
|
+
|
|
329
|
+
Then add `pnpm run check:swc-tdz` to your own `check` chain (before the tests, so it
|
|
330
|
+
fails fast) and to CI.
|
|
331
|
+
|
|
332
|
+
> **Vendor-mode projects should treat this as required, not optional.** You copy
|
|
333
|
+
> `src/core/` into your own tree, where a local edit can re-introduce exactly this
|
|
334
|
+
> kind of cycle — and your `tsc` build and your test suite will both stay green while
|
|
335
|
+
> it does.
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## Compatibility Notes
|
|
340
|
+
|
|
341
|
+
| Pattern | Status |
|
|
342
|
+
|---------|--------|
|
|
343
|
+
| Importing tokens from `@lenne.tech/nest-server` (package root) | ✅ Unchanged |
|
|
344
|
+
| Deep-importing tokens from `core-better-auth.module` / `.service` | ✅ Works, now `@deprecated` |
|
|
345
|
+
| `@Inject('BETTER_AUTH_INSTANCE')` as a string literal | ✅ Unchanged (values pinned by test) |
|
|
346
|
+
| Custom `{ provide: BETTER_AUTH_INSTANCE, useValue: ... }` overrides | ✅ Unchanged |
|
|
347
|
+
| Extending `BetterAuthRolesGuard` | ✅ Unchanged public behavior |
|
|
348
|
+
| `CoreBetterAuthModule.getTokenServiceInstance()` | ✅ Unchanged (now delegates to the registry) |
|
|
349
|
+
| Building with `tsc` (default) | ✅ Was never affected |
|
|
350
|
+
| Building with SWC | ✅ **Fixed** |
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
## Troubleshooting
|
|
355
|
+
|
|
356
|
+
**`ReferenceError: Cannot access 'BETTER_AUTH_INSTANCE' before initialization`**
|
|
357
|
+
You are still on ≤ 11.27.6 with an SWC build. Update to 11.27.7.
|
|
358
|
+
|
|
359
|
+
**Vendor mode: `Cannot find module './core-better-auth.constants'`**
|
|
360
|
+
The sync did not create the new leaf file(s). Re-run the core update and confirm
|
|
361
|
+
both `core-better-auth.constants.ts` and `core-better-auth.registry.ts` exist in
|
|
362
|
+
`src/core/modules/better-auth/`.
|
|
363
|
+
|
|
364
|
+
**Deprecation warnings on the token imports**
|
|
365
|
+
Expected. Switch the import to the package root (`@lenne.tech/nest-server`) or to
|
|
366
|
+
`core-better-auth.constants`. No behavior change either way.
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## Module Documentation
|
|
371
|
+
|
|
372
|
+
- [BetterAuth README](../src/core/modules/better-auth/README.md)
|
|
373
|
+
- [BetterAuth Integration Checklist](../src/core/modules/better-auth/INTEGRATION-CHECKLIST.md)
|
|
374
|
+
- [BetterAuth Customization](../src/core/modules/better-auth/CUSTOMIZATION.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/nest-server",
|
|
3
|
-
"version": "11.27.
|
|
3
|
+
"version": "11.27.7",
|
|
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",
|
|
@@ -23,9 +23,10 @@
|
|
|
23
23
|
"build:dev": "pnpm run build",
|
|
24
24
|
"c": "pnpm run check",
|
|
25
25
|
"check": "node scripts/check.mjs",
|
|
26
|
-
"check:raw": "pnpm audit && pnpm run format:check && pnpm run lint && pnpm test && pnpm run build && bash scripts/check-server-start.sh",
|
|
27
|
-
"check:fix": "pnpm install && pnpm audit --fix && pnpm run format && pnpm run lint:fix && pnpm test && pnpm run build && bash scripts/check-server-start.sh",
|
|
28
|
-
"check:naf": "pnpm install && pnpm run format && pnpm run lint:fix && pnpm test && pnpm run build && bash scripts/check-server-start.sh",
|
|
26
|
+
"check:raw": "pnpm audit && pnpm run format:check && pnpm run lint && pnpm run check:swc-tdz && pnpm test && pnpm run build && bash scripts/check-server-start.sh",
|
|
27
|
+
"check:fix": "pnpm install && pnpm audit --fix && pnpm run format && pnpm run lint:fix && pnpm run check:swc-tdz && pnpm test && pnpm run build && bash scripts/check-server-start.sh",
|
|
28
|
+
"check:naf": "pnpm install && pnpm run format && pnpm run lint:fix && pnpm run check:swc-tdz && pnpm test && pnpm run build && bash scripts/check-server-start.sh",
|
|
29
|
+
"check:swc-tdz": "nest build -b swc -p tsconfig.swc-tdz.json && node scripts/check-swc-tdz.mjs",
|
|
29
30
|
"cf": "pnpm run check:fix",
|
|
30
31
|
"cnaf": "pnpm run check:naf",
|
|
31
32
|
"docs": "pnpm run docs:ci && open http://127.0.0.1:8080/ && open ./public/index.html && compodoc -p tsconfig.json -s ",
|
|
@@ -48,8 +49,9 @@
|
|
|
48
49
|
"start:dev:swc": "nest start -b swc -w --type-check",
|
|
49
50
|
"start:local": "NODE_ENV=local nodemon",
|
|
50
51
|
"start:local:swc": "NODE_ENV=local nest start -b swc -w --type-check",
|
|
51
|
-
"test": "pnpm run vitest",
|
|
52
|
-
"test:ci": "pnpm run vitest:ci",
|
|
52
|
+
"test": "pnpm run vitest:unit && pnpm run vitest",
|
|
53
|
+
"test:ci": "pnpm run vitest:unit && pnpm run vitest:ci",
|
|
54
|
+
"test:cov": "pnpm run vitest:unit:cov && pnpm run vitest:cov",
|
|
53
55
|
"test:e2e": "pnpm run vitest",
|
|
54
56
|
"prepack": "pnpm run prestart:prod",
|
|
55
57
|
"prepublishOnly": "pnpm run lint && pnpm run test:ci",
|
|
@@ -59,6 +61,7 @@
|
|
|
59
61
|
"vitest:cov": "NODE_ENV=e2e vitest run --coverage --config vitest-e2e.config.ts",
|
|
60
62
|
"vitest:watch": "NODE_ENV=e2e vitest --config vitest-e2e.config.ts",
|
|
61
63
|
"vitest:unit": "vitest run --config vitest.config.ts",
|
|
64
|
+
"vitest:unit:cov": "vitest run --coverage --config vitest.config.ts",
|
|
62
65
|
"test:unit:watch": "vitest --config vitest.config.ts",
|
|
63
66
|
"test:types": "tsc --noEmit --skipLibCheck -p tests/types/tsconfig.json",
|
|
64
67
|
"test:cleanup": "find tests -type f \\( -name '*.txt' -o -name '*.bin' \\) -not -name '.gitkeep' -delete && echo 'Test artifacts cleaned up'",
|
|
@@ -72,7 +75,7 @@
|
|
|
72
75
|
"url": "https://github.com/lenneTech/nest-server/issues"
|
|
73
76
|
},
|
|
74
77
|
"engines": {
|
|
75
|
-
"node": ">=
|
|
78
|
+
"node": ">= 22"
|
|
76
79
|
},
|
|
77
80
|
"dependencies": {
|
|
78
81
|
"@apollo/server": "5.5.1",
|
|
@@ -181,101 +184,5 @@
|
|
|
181
184
|
"watch": {
|
|
182
185
|
"build:dev": "src"
|
|
183
186
|
},
|
|
184
|
-
"packageManager": "pnpm@
|
|
185
|
-
"pnpm": {
|
|
186
|
-
"//overrides": {
|
|
187
|
-
"axios@<1.16.0": "Security: Multiple CVEs in axios <1.15.2 (SSRF via NO_PROXY, prototype pollution, header injection, CRLF injection in form-data, XSRF leakage, auth bypass, response tampering, no_proxy IP alias bypass, streamed upload/response bypass, toFormData DoS, null byte injection) - transitive via @getbrevo/brevo and node-mailjet. Remove when @getbrevo/brevo and node-mailjet ship axios>=1.16.0",
|
|
188
|
-
"fast-uri@<3.1.2": "Security: host confusion (GHSA-3vp4-mxqf-vmh4) and path traversal (GHSA-q4mq-mw7v-xq57) in fast-uri <3.1.2 - transitive via @compodoc/compodoc>@angular-devkit/schematics>@angular-devkit/core>ajv",
|
|
189
|
-
"@babel/plugin-transform-modules-systemjs@>=7.12.0 <7.29.4": "Security: prototype pollution-based variable shadowing (GHSA-7p7r-hpq8-6w8q) generates unsafe code - transitive via @compodoc/compodoc>@babel/preset-env",
|
|
190
|
-
"minimatch@<3.1.5": "Security: RegExp DoS (GHSA-p8p7-x288-28g6) - transitive via @getbrevo/brevo>rewire>eslint",
|
|
191
|
-
"minimatch@>=9.0.0 <9.0.9": "Security: RegExp DoS - transitive via @nestjs/cli>@swc/cli",
|
|
192
|
-
"minimatch@>=10.0.0 <10.2.5": "Security: RegExp DoS - transitive via @nestjs/apollo>ts-morph>@ts-morph/common and nodemon",
|
|
193
|
-
"ajv@<6.14.0": "Security: prototype pollution - transitive via @getbrevo/brevo>rewire>eslint",
|
|
194
|
-
"ajv@>=7.0.0-alpha.0 <8.18.0": "Security: prototype pollution - transitive via @nestjs/cli>@angular-devkit",
|
|
195
|
-
"undici@>=7.0.0 <7.28.0": "Security: various CVEs <7.28.0 (incl. high) - transitive via @compodoc/compodoc>cheerio + better-auth",
|
|
196
|
-
"piscina@<4.9.3": "Security: high CVE in piscina <4.9.3 - transitive via the build/test toolchain",
|
|
197
|
-
"@babel/core@<7.29.6": "Security: @babel/core <7.29.6 advisory - transitive via @compodoc/compodoc>@babel/preset-env",
|
|
198
|
-
"handlebars@>=4.0.0 <4.7.9": "Security: prototype pollution (GHSA-q42p-pg8m-cqh6) - transitive via @compodoc/compodoc",
|
|
199
|
-
"brace-expansion@<1.1.13": "Security: RegExp DoS - transitive via eslint>minimatch",
|
|
200
|
-
"brace-expansion@>=4.0.0 <5.0.6": "Security: RegExp DoS - Large numeric range defeats brace expansion (GHSA-jxxr-4gwj-5jf2) - transitive via nodemon>minimatch and @ts-morph/common>minimatch and @compodoc/compodoc>glob>minimatch",
|
|
201
|
-
"picomatch@<2.3.2": "Security: ReDoS - transitive via @nestjs/graphql>fast-glob>micromatch and @compodoc/compodoc>chokidar",
|
|
202
|
-
"picomatch@>=4.0.0 <4.0.4": "Security: ReDoS - transitive via vitest and vite",
|
|
203
|
-
"path-to-regexp@>=8.0.0 <8.4.2": "Security: ReDoS (GHSA-rhx6-c78j-4q9w) - transitive via express>router",
|
|
204
|
-
"kysely@>=0.26.0 <0.28.17": "Security: JSON-path traversal injection via unsanitized input (SQL injection) - transitive via better-auth>@better-auth/passkey>@better-auth/core",
|
|
205
|
-
"@protobufjs/utf8@<=1.1.0": "Security: overlong UTF-8 decoding - transitive via @apollo/server>@apollo/usage-reporting-protobuf",
|
|
206
|
-
"ws@>=8.0.0 <8.21.0": "Security: Memory exhaustion DoS + uninitialized memory disclosure (GHSA-96hv-2xvq-fx4p) - transitive via @nestjs/graphql",
|
|
207
|
-
"ws@>=7.0.0 <7.5.11": "Security: Memory exhaustion DoS in ws 7.x (GHSA-96hv-2xvq-fx4p) - transitive via @nestjs/graphql>subscriptions-transport-ws",
|
|
208
|
-
"qs@>=6.11.1 <=6.15.1": "Security: remotely triggerable DoS in qs.stringify with comma-format arrays (GHSA-q8mj-m7cp-5q26) - transitive via @compodoc/compodoc>body-parser",
|
|
209
|
-
"lodash@>=4.0.0 <4.18.0": "Security: CVE in lodash@4.17.x - transitive via @nestjs/graphql. 4.18.1 is the latest patched version",
|
|
210
|
-
"defu@<=6.1.6": "Security: prototype pollution via __proto__ key - transitive via better-auth",
|
|
211
|
-
"follow-redirects@<=1.15.11": "Security: Custom Authentication Headers leak on cross-domain redirect (GHSA-r4q5-vmmm-2653) - transitive via axios>@getbrevo/brevo and axios>node-mailjet",
|
|
212
|
-
"uuid@<14.0.0": "Security: Missing buffer bounds check in v3/v5/v6 (GHSA-w5hq-g745-h8pq) - transitive via @compodoc/compodoc and @compodoc/compodoc>@compodoc/live-server>http-auth",
|
|
213
|
-
"postcss@<8.5.10": "Security: XSS via Unescaped </style> in CSS Stringify Output (GHSA-qx2v-qp2m-jg93) - transitive via vite. Remove when vite ships with postcss>=8.5.10",
|
|
214
|
-
"form-data@<4.0.6": "Security: CRLF injection via unescaped multipart field names/filenames (GHSA-hmw2-7cc7-3qxx) - transitive via @getbrevo/brevo>axios and node-mailjet>axios",
|
|
215
|
-
"vite@>=8.0.0 <8.0.16": "Security: fs.deny bypass on Windows alternate paths + file read CVEs - transitive via better-auth>vitest",
|
|
216
|
-
"hono@<4.12.25": "Security: multiple CVEs <4.12.25 (prototype pollution, bodyLimit/Vary bypass, JWT NumericDate) - transitive via @nestjs/terminus>prisma>@prisma/dev",
|
|
217
|
-
"nodemailer@<9.0.1": "Security: email/header injection CVEs <9.0.1 - direct dependency",
|
|
218
|
-
"multer@<2.2.0": "Security: unhandled multipart errors / DoS <2.2.0 - transitive via @nestjs/platform-express",
|
|
219
|
-
"js-yaml@<4.2.0": "Security: special-character handling / prototype pollution (patched in 4.2.0; 4.1.2 was never published) - transitive via @nestjs/swagger",
|
|
220
|
-
"@xhmikosr/decompress@<11.1.3": "Security: archive extraction can create files/links outside the target directory (GHSA-mp2f-45pm-3cg9, critical) - transitive via @swc/cli>@xhmikosr/bin-wrapper>@xhmikosr/downloader; @swc/cli 0.8.1 is already the latest release and still resolves the vulnerable range, so an override is the only fix"
|
|
221
|
-
},
|
|
222
|
-
"overrides": {
|
|
223
|
-
"axios@<1.16.0": "1.16.0",
|
|
224
|
-
"fast-uri@<3.1.2": "3.1.2",
|
|
225
|
-
"@babel/plugin-transform-modules-systemjs@>=7.12.0 <7.29.4": "7.29.4",
|
|
226
|
-
"minimatch@<3.1.5": "3.1.5",
|
|
227
|
-
"minimatch@>=9.0.0 <9.0.9": "9.0.9",
|
|
228
|
-
"minimatch@>=10.0.0 <10.2.5": "10.2.5",
|
|
229
|
-
"ajv@<6.14.0": "6.14.0",
|
|
230
|
-
"ajv@>=7.0.0-alpha.0 <8.18.0": "8.18.0",
|
|
231
|
-
"undici@>=7.0.0 <7.28.0": "7.28.0",
|
|
232
|
-
"piscina@<4.9.3": "4.9.3",
|
|
233
|
-
"@babel/core@<7.29.6": "7.29.6",
|
|
234
|
-
"handlebars@>=4.0.0 <4.7.9": "4.7.9",
|
|
235
|
-
"brace-expansion@<1.1.13": "1.1.13",
|
|
236
|
-
"brace-expansion@>=4.0.0 <5.0.6": "5.0.6",
|
|
237
|
-
"picomatch@<2.3.2": "2.3.2",
|
|
238
|
-
"picomatch@>=4.0.0 <4.0.4": "4.0.4",
|
|
239
|
-
"path-to-regexp@>=8.0.0 <8.4.2": "8.4.2",
|
|
240
|
-
"kysely@>=0.26.0 <0.28.17": "0.28.17",
|
|
241
|
-
"@protobufjs/utf8@<=1.1.0": "1.1.1",
|
|
242
|
-
"ws@>=8.0.0 <8.21.0": "8.21.0",
|
|
243
|
-
"ws@>=7.0.0 <7.5.11": "7.5.11",
|
|
244
|
-
"qs@>=6.11.1 <=6.15.1": "6.15.2",
|
|
245
|
-
"lodash@>=4.0.0 <4.18.0": "4.18.1",
|
|
246
|
-
"defu@<=6.1.6": "6.1.7",
|
|
247
|
-
"follow-redirects@<=1.15.11": "1.16.0",
|
|
248
|
-
"uuid@<14.0.0": "14.0.0",
|
|
249
|
-
"postcss@<8.5.10": "8.5.12",
|
|
250
|
-
"esbuild@>=0.17.0 <0.28.1": "0.28.1",
|
|
251
|
-
"form-data@<4.0.6": "4.0.6",
|
|
252
|
-
"vite@>=8.0.0 <8.0.16": "8.0.16",
|
|
253
|
-
"hono@<4.12.25": "4.12.25",
|
|
254
|
-
"nodemailer@<9.0.1": "9.0.1",
|
|
255
|
-
"multer@<2.2.0": "2.2.0",
|
|
256
|
-
"js-yaml@<4.2.0": "4.2.0",
|
|
257
|
-
"@xhmikosr/decompress@<11.1.3": "11.1.3"
|
|
258
|
-
},
|
|
259
|
-
"//peerDependencyRules": "allowedVersions: deps lag behind our newer majors (graphql-upload wants @types/express@^4, the deprecated apollo playground plugin wants @apollo/server@^4) — both work with our v5. ignoreMissing: browser-only vis-network peers pulled in transitively via yuml-diagram (server-side UML generation never renders, so these are not needed).",
|
|
260
|
-
"peerDependencyRules": {
|
|
261
|
-
"allowedVersions": {
|
|
262
|
-
"@apollo/server": "5",
|
|
263
|
-
"@types/express": "5"
|
|
264
|
-
},
|
|
265
|
-
"ignoreMissing": [
|
|
266
|
-
"@egjs/hammerjs",
|
|
267
|
-
"keycharm",
|
|
268
|
-
"vis-data",
|
|
269
|
-
"vis-util"
|
|
270
|
-
]
|
|
271
|
-
},
|
|
272
|
-
"onlyBuiltDependencies": [
|
|
273
|
-
"bcrypt",
|
|
274
|
-
"@swc/core",
|
|
275
|
-
"esbuild",
|
|
276
|
-
"@nestjs/core",
|
|
277
|
-
"@compodoc/compodoc",
|
|
278
|
-
"@apollo/protobufjs"
|
|
279
|
-
]
|
|
280
|
-
}
|
|
187
|
+
"packageManager": "pnpm@11.13.0"
|
|
281
188
|
}
|
|
@@ -1,10 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NOTE ON `export function` VS `export const` (do not "modernize" these to arrow functions).
|
|
3
|
+
*
|
|
4
|
+
* `Restricted`, `getRestricted` and `checkRestricted` are declared as FUNCTION DECLARATIONS on
|
|
5
|
+
* purpose. This file sits on an import cycle:
|
|
6
|
+
*
|
|
7
|
+
* restricted.decorator → helpers/db.helper → helpers/input.helper → restricted.decorator
|
|
8
|
+
*
|
|
9
|
+
* so when `input.helper`'s module body runs, THIS module is still mid-evaluation. A `const` arrow is
|
|
10
|
+
* a temporal-dead-zone binding: any evaluation-time read of it from `input.helper` (a top-level
|
|
11
|
+
* alias, an `@Restricted`-decorated class, `design:type` metadata) would throw under SWC → CommonJS:
|
|
12
|
+
*
|
|
13
|
+
* ReferenceError: Cannot access 'checkRestricted' before initialization
|
|
14
|
+
*
|
|
15
|
+
* Function declarations are HOISTED and fully initialized before any module body runs, so they are
|
|
16
|
+
* immune. `input.helper` today only calls `checkRestricted` from inside a function body, which is
|
|
17
|
+
* why nothing has crashed — but that is one careless top-level line away, in the file that drives
|
|
18
|
+
* field-level access control. The hoisting removes the hazard rather than relying on vigilance.
|
|
19
|
+
*
|
|
20
|
+
* The proper fix is to break the cycle (extract the ID helpers out of `db.helper` into a leaf), and
|
|
21
|
+
* that is worth doing. Until then, `pnpm run check:swc-tdz` is the mechanical guard.
|
|
22
|
+
* See .claude/rules/architecture.md → "DI Token Placement (SWC-Safe)".
|
|
23
|
+
*/
|
|
1
24
|
import { UnauthorizedException } from '@nestjs/common';
|
|
2
25
|
import 'reflect-metadata';
|
|
3
26
|
import _ = require('lodash');
|
|
4
27
|
|
|
5
28
|
import { ProcessType } from '../enums/process-type.enum';
|
|
6
29
|
import { RoleEnum } from '../enums/role.enum';
|
|
7
|
-
|
|
30
|
+
// Import from the id.helper LEAF, never from db.helper: db.helper imports input.helper, which
|
|
31
|
+
// imports this file back — that cycle is what the extraction removed. See id.helper's docblock.
|
|
32
|
+
import { equalIds, getIncludedIds } from '../helpers/id.helper';
|
|
8
33
|
import { RequestContext } from '../services/request-context.service';
|
|
9
34
|
import { RequireAtLeastOne } from '../types/required-at-least-one.type';
|
|
10
35
|
import { checkRoleAccess } from '../../modules/tenant/core-tenant.helpers';
|
|
@@ -40,9 +65,9 @@ export type RestrictedType = (
|
|
|
40
65
|
* properties of the processed item, which is specified by the value of `memberOf`
|
|
41
66
|
* Via processType the restriction can be set for input or output only
|
|
42
67
|
*/
|
|
43
|
-
export
|
|
68
|
+
export function Restricted(...rolesOrMember: RestrictedType): ClassDecorator & PropertyDecorator {
|
|
44
69
|
return Reflect.metadata(restrictedMetaKey, rolesOrMember);
|
|
45
|
-
}
|
|
70
|
+
}
|
|
46
71
|
|
|
47
72
|
/**
|
|
48
73
|
* Cache for Restricted metadata — decorators are static, metadata never changes at runtime.
|
|
@@ -60,7 +85,7 @@ const restrictedMetadataCache = new WeakMap<object, Map<string, RestrictedType>>
|
|
|
60
85
|
/**
|
|
61
86
|
* Get restricted data for (property of) object
|
|
62
87
|
*/
|
|
63
|
-
export
|
|
88
|
+
export function getRestricted(object: unknown, propertyKey?: string): RestrictedType {
|
|
64
89
|
if (!object) {
|
|
65
90
|
return null;
|
|
66
91
|
}
|
|
@@ -94,13 +119,13 @@ export const getRestricted = (object: unknown, propertyKey?: string): Restricted
|
|
|
94
119
|
|
|
95
120
|
classCache.set(cacheKey, metadata);
|
|
96
121
|
return metadata;
|
|
97
|
-
}
|
|
122
|
+
}
|
|
98
123
|
|
|
99
124
|
/**
|
|
100
125
|
* Check data for restricted properties (properties with `Restricted` decorator)
|
|
101
126
|
* For special Roles and member of group checking the dbObject must be set in options
|
|
102
127
|
*/
|
|
103
|
-
export
|
|
128
|
+
export function checkRestricted(
|
|
104
129
|
data: any,
|
|
105
130
|
user: {
|
|
106
131
|
emailVerified?: any;
|
|
@@ -125,7 +150,7 @@ export const checkRestricted = (
|
|
|
125
150
|
throwError?: boolean;
|
|
126
151
|
} = {},
|
|
127
152
|
processedObjects: WeakSet<object> = new WeakSet(),
|
|
128
|
-
)
|
|
153
|
+
) {
|
|
129
154
|
// Act like Roles handling: checkObjectItself = false & mergeRoles = true
|
|
130
155
|
// For Input: throwError = true
|
|
131
156
|
// For Output: throwError = false
|
|
@@ -394,4 +419,4 @@ export const checkRestricted = (
|
|
|
394
419
|
|
|
395
420
|
// Return processed data
|
|
396
421
|
return data;
|
|
397
|
-
}
|
|
422
|
+
}
|