@lenne.tech/nest-server 11.21.3 → 11.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/.claude/rules/architecture.md +79 -0
  2. package/.claude/rules/better-auth.md +262 -0
  3. package/.claude/rules/configurable-features.md +308 -0
  4. package/.claude/rules/core-modules.md +205 -0
  5. package/.claude/rules/framework-compatibility.md +79 -0
  6. package/.claude/rules/migration-guides.md +149 -0
  7. package/.claude/rules/module-deprecation.md +214 -0
  8. package/.claude/rules/module-inheritance.md +97 -0
  9. package/.claude/rules/package-management.md +112 -0
  10. package/.claude/rules/role-system.md +146 -0
  11. package/.claude/rules/testing.md +120 -0
  12. package/.claude/rules/versioning.md +53 -0
  13. package/CLAUDE.md +174 -0
  14. package/FRAMEWORK-API.md +231 -0
  15. package/dist/core/common/interfaces/server-options.interface.d.ts +10 -0
  16. package/dist/core/modules/error-code/error-code.module.js.map +1 -1
  17. package/dist/core.module.d.ts +3 -3
  18. package/dist/core.module.js +17 -4
  19. package/dist/core.module.js.map +1 -1
  20. package/dist/server/modules/file/file-info.model.d.ts +1 -5
  21. package/dist/server/modules/user/user.model.d.ts +1 -5
  22. package/dist/server/server.module.js +6 -6
  23. package/dist/server/server.module.js.map +1 -1
  24. package/dist/tsconfig.build.tsbuildinfo +1 -1
  25. package/docs/REQUEST-LIFECYCLE.md +1256 -0
  26. package/docs/error-codes.md +446 -0
  27. package/migration-guides/11.10.x-to-11.11.x.md +266 -0
  28. package/migration-guides/11.11.x-to-11.12.x.md +323 -0
  29. package/migration-guides/11.12.x-to-11.13.0.md +612 -0
  30. package/migration-guides/11.13.x-to-11.14.0.md +348 -0
  31. package/migration-guides/11.14.x-to-11.15.0.md +262 -0
  32. package/migration-guides/11.15.0-to-11.15.3.md +118 -0
  33. package/migration-guides/11.15.x-to-11.16.0.md +497 -0
  34. package/migration-guides/11.16.x-to-11.17.0.md +130 -0
  35. package/migration-guides/11.17.x-to-11.18.0.md +393 -0
  36. package/migration-guides/11.18.x-to-11.19.0.md +151 -0
  37. package/migration-guides/11.19.x-to-11.20.0.md +170 -0
  38. package/migration-guides/11.20.x-to-11.21.0.md +216 -0
  39. package/migration-guides/11.21.0-to-11.21.1.md +194 -0
  40. package/migration-guides/11.21.1-to-11.21.2.md +114 -0
  41. package/migration-guides/11.21.2-to-11.21.3.md +175 -0
  42. package/migration-guides/11.21.x-to-11.22.0.md +224 -0
  43. package/migration-guides/11.22.0-to-11.22.1.md +105 -0
  44. package/migration-guides/11.3.x-to-11.4.x.md +233 -0
  45. package/migration-guides/11.6.x-to-11.7.x.md +394 -0
  46. package/migration-guides/11.7.x-to-11.8.x.md +318 -0
  47. package/migration-guides/11.8.x-to-11.9.x.md +322 -0
  48. package/migration-guides/11.9.x-to-11.10.x.md +571 -0
  49. package/migration-guides/TEMPLATE.md +113 -0
  50. package/package.json +25 -18
  51. package/src/core/common/interfaces/server-options.interface.ts +83 -16
  52. package/src/core/modules/better-auth/CUSTOMIZATION.md +24 -17
  53. package/src/core/modules/better-auth/INTEGRATION-CHECKLIST.md +5 -5
  54. package/src/core/modules/error-code/INTEGRATION-CHECKLIST.md +42 -12
  55. package/src/core/modules/error-code/error-code.module.ts +4 -9
  56. package/src/core.module.ts +52 -10
  57. package/src/server/server.module.ts +7 -9
@@ -0,0 +1,130 @@
1
+ # Migration Guide: 11.16.x → 11.17.0
2
+
3
+ ## Overview
4
+
5
+ | Category | Details |
6
+ |----------|---------|
7
+ | **Breaking Changes** | None |
8
+ | **New Features** | Permissions Report Module, Configurable endpoint path |
9
+ | **Bugfixes** | None |
10
+ | **Migration Effort** | < 5 minutes (optional feature) |
11
+
12
+ ---
13
+
14
+ ## Quick Migration (No Breaking Changes)
15
+
16
+ ```bash
17
+ # Update package
18
+ npm install @lenne.tech/nest-server@11.17.0
19
+
20
+ # Verify build
21
+ npm run build
22
+
23
+ # Run tests
24
+ npm test
25
+ ```
26
+
27
+ ---
28
+
29
+ ## What's New in 11.17.0
30
+
31
+ ### 1. Permissions Report Module
32
+
33
+ A development tool that scans your project for `@Roles`, `@Restricted`, and `securityCheck()` usage, generating an interactive HTML dashboard at runtime.
34
+
35
+ **Setup (optional):**
36
+
37
+ ```typescript
38
+ // config.env.ts - local/development only
39
+ permissions: true,
40
+ ```
41
+
42
+ This adds the following endpoints to your server:
43
+
44
+ | Method | Path | Description |
45
+ |--------|------|-------------|
46
+ | `GET` | `/permissions` | Interactive HTML dashboard |
47
+ | `GET` | `/permissions/json` | JSON report with stats |
48
+ | `GET` | `/permissions/markdown` | Markdown report |
49
+ | `POST` | `/permissions/rescan` | Force rescan |
50
+
51
+ **Features:**
52
+ - Lazy scanning (only on first request)
53
+ - File watcher auto-invalidates cache on `.ts` file changes
54
+ - Coverage metrics (endpoint coverage, security coverage)
55
+ - Warning detection (missing `@Roles`, `@Restricted`, `securityCheck()`)
56
+ - Role-based access control (admin-only by default)
57
+
58
+ **Advanced configuration:**
59
+
60
+ ```typescript
61
+ // Custom role
62
+ permissions: { role: 'S_EVERYONE' },
63
+
64
+ // No authentication
65
+ permissions: { role: false },
66
+
67
+ // Custom endpoint path
68
+ permissions: { path: 'admin/permissions' },
69
+
70
+ // Explicitly disabled
71
+ permissions: { enabled: false },
72
+ ```
73
+
74
+ ### 2. Standalone Permissions Scanner
75
+
76
+ The scanning logic has been extracted into `permissions-scanner.ts` as a standalone module with no NestJS dependencies. This enables:
77
+
78
+ - The `lt server permissions` CLI command to use the same scanner via dynamic import
79
+ - External tools to import `scanPermissions()` directly from `@lenne.tech/nest-server`
80
+
81
+ ```typescript
82
+ import { scanPermissions, findProjectRoot } from '@lenne.tech/nest-server';
83
+
84
+ const projectRoot = findProjectRoot();
85
+ const report = scanPermissions(projectRoot, {
86
+ log: (msg) => console.log(msg),
87
+ warn: (msg) => console.warn(msg),
88
+ });
89
+ ```
90
+
91
+ ---
92
+
93
+ ## Detailed Migration Steps
94
+
95
+ ### Step 1: Update Package
96
+
97
+ ```bash
98
+ npm install @lenne.tech/nest-server@11.17.0
99
+ ```
100
+
101
+ ### Step 2: Adopt New Features (Optional)
102
+
103
+ Add `permissions: true` to your `config.env.ts` in local/development environments. See the [Permissions README](../src/core/modules/permissions/README.md) for details.
104
+
105
+ ---
106
+
107
+ ## Compatibility Notes
108
+
109
+ - The permissions module is entirely opt-in. Existing projects are unaffected.
110
+ - The `lt server permissions` CLI command now requires `@lenne.tech/nest-server >= 11.17.0` in the target project.
111
+
112
+ ---
113
+
114
+ ## Module Documentation
115
+
116
+ ### Permissions Report
117
+
118
+ - **README:** [src/core/modules/permissions/README.md](../src/core/modules/permissions/README.md)
119
+ - **Integration Checklist:** [src/core/modules/permissions/INTEGRATION-CHECKLIST.md](../src/core/modules/permissions/INTEGRATION-CHECKLIST.md)
120
+ - **Key Files:**
121
+ - `permissions-scanner.ts` - Standalone AST scanning (shared with CLI)
122
+ - `core-permissions.service.ts` - Caching, file watching, HTML generation
123
+ - `core-permissions.controller.ts` - REST endpoints
124
+ - `core-permissions.module.ts` - DynamicModule with forRoot()
125
+
126
+ ---
127
+
128
+ ## References
129
+
130
+ - [nest-server-starter](https://github.com/lenneTech/nest-server-starter) (reference implementation)
@@ -0,0 +1,393 @@
1
+ # Migration Guide: 11.17.x → 11.18.0
2
+
3
+ ## Overview
4
+
5
+ | Category | Details |
6
+ |----------|---------|
7
+ | **Breaking Changes** | None (NestJS patch update `11.1.13` → `11.1.16` requires matching versions) |
8
+ | **New Features** | Safety Net Architecture: automatic security without CrudService.process() |
9
+ | **Dependency Updates** | NestJS 11.1.16, apollo-server-core removed (−151 packages), 21 packages updated |
10
+ | **Migration Effort** | ~5 minutes (update NestJS packages + verify) |
11
+
12
+ ---
13
+
14
+ ## Quick Migration
15
+
16
+ All Safety Net features are **enabled by default** and fully backward compatible. No code changes required.
17
+
18
+ However, 11.18.0 updates NestJS core packages to `11.1.16`. Projects **must** update their NestJS packages to match, otherwise pnpm will install duplicate copies with incompatible TypeScript types (e.g. `Types have separate declarations of a private property 'logger'`).
19
+
20
+ ```bash
21
+ # 1. Update nest-server
22
+ pnpm add @lenne.tech/nest-server@11.18.0
23
+
24
+ # 2. Update NestJS packages to match (required!)
25
+ pnpm add @nestjs/common@11.1.16 @nestjs/core@11.1.16 @nestjs/platform-express@11.1.16
26
+ pnpm add -D @nestjs/testing@11.1.16
27
+
28
+ # 3. Verify build
29
+ pnpm run build
30
+
31
+ # 4. Run tests
32
+ pnpm test
33
+ ```
34
+
35
+ > **Why?** `@lenne.tech/nest-server` declares NestJS packages in `dependencies` with exact versions. If your project uses a different patch version, pnpm creates duplicate installations which TypeScript treats as incompatible types.
36
+
37
+ ---
38
+
39
+ ## What's New in 11.18.0
40
+
41
+ ### Safety Net Architecture
42
+
43
+ Previously, security guarantees (password hashing, role protection, secret removal, field filtering) only worked when using `CrudService.process()`. Developers bypassing `process()` with direct Mongoose calls (`this.mainDbModel.findOne()`, `.aggregate()`, etc.) could accidentally expose sensitive data or store plaintext passwords.
44
+
45
+ **11.18.0 introduces automatic security at the framework level**, ensuring protection works regardless of how data is accessed or written.
46
+
47
+ ### 1. Mongoose Password Hashing Plugin
48
+
49
+ Automatically hashes passwords on all write operations (`save`, `findOneAndUpdate`, `updateOne`, `updateMany`).
50
+
51
+ - Detects already-hashed values (BCrypt pattern) to prevent double-hashing
52
+ - Supports SHA256 pre-hashing (matching the existing `prepareInput` behavior)
53
+ - Configurable skip patterns for sentinel values (e.g. `!LOCKED:REQUIRES_PASSWORD_RESET`)
54
+
55
+ ```typescript
56
+ // config.env.ts - enabled by default, examples for customization:
57
+
58
+ // Default: enabled
59
+ security: {
60
+ mongoosePasswordPlugin: true,
61
+ }
62
+
63
+ // With skip patterns for sentinel values
64
+ security: {
65
+ mongoosePasswordPlugin: {
66
+ skipPatterns: ['^!LOCKED:'],
67
+ },
68
+ }
69
+
70
+ // Disable entirely
71
+ security: {
72
+ mongoosePasswordPlugin: false,
73
+ }
74
+ ```
75
+
76
+ ### 2. Mongoose Role Guard Plugin
77
+
78
+ Prevents unauthorized users from escalating roles via direct database operations. Only users with ADMIN role (or configured allowed roles) can assign roles to other users.
79
+
80
+ - Uses `RequestContext` (AsyncLocalStorage) to access the current user
81
+ - System operations without request context (e.g. migrations, seeds) are allowed through
82
+ - No-user requests (e.g. `signUp`) are allowed through (`currentUser` is `undefined`)
83
+ - Configurable for custom role hierarchies
84
+ - Programmatic bypass via `RequestContext.runWithBypassRoleGuard()` for authorized service code
85
+
86
+ ```typescript
87
+ // config.env.ts - enabled by default, examples for customization:
88
+
89
+ // Default: only ADMIN can assign roles
90
+ security: {
91
+ mongooseRoleGuardPlugin: true,
92
+ }
93
+
94
+ // Allow additional roles to assign roles
95
+ security: {
96
+ mongooseRoleGuardPlugin: {
97
+ allowedRoles: ['ORGA', 'COMPANY_ADMIN'],
98
+ },
99
+ }
100
+
101
+ // Programmatic bypass for authorized service operations (e.g. HR_MANAGER creating users with roles):
102
+ import { RequestContext } from '@lenne.tech/nest-server';
103
+
104
+ await RequestContext.runWithBypassRoleGuard(async () => {
105
+ await this.mainDbModel.findByIdAndUpdate(userId, { roles: ['EMPLOYEE'] });
106
+ });
107
+
108
+ // Also works with CrudService.process() via force: true (automatically bypasses the plugin)
109
+ ```
110
+
111
+ ### 3. Mongoose Audit Fields Plugin
112
+
113
+ Automatically sets `createdBy` and `updatedBy` fields on save/update operations using the current user from `RequestContext`.
114
+
115
+ ```typescript
116
+ // config.env.ts - enabled by default
117
+
118
+ // Disable if not needed
119
+ security: {
120
+ mongooseAuditFieldsPlugin: false,
121
+ }
122
+ ```
123
+
124
+ ### 4. ResponseModelInterceptor
125
+
126
+ Auto-converts plain objects and Mongoose documents into model instances with `securityCheck()` and correct constructor metadata. This ensures `@Restricted` field filtering and `securityCheck()` work even when `CrudService.process()` is bypassed.
127
+
128
+ **Model class resolution order:**
129
+ 1. Explicit `@ResponseModel(ModelClass)` decorator (for REST)
130
+ 2. GraphQL `TypeMetadataStorage` lookup (automatic for `@Query`/`@Mutation` return types)
131
+ 3. Swagger `@ApiOkResponse` / `@ApiCreatedResponse` type (automatic for REST)
132
+ 4. No conversion (existing interceptors work as before)
133
+
134
+ Results are cached per route handler for zero-cost subsequent lookups.
135
+
136
+ ```typescript
137
+ // config.env.ts - enabled by default
138
+
139
+ // Enable with debug warnings (logs when auto-conversion happens)
140
+ security: {
141
+ responseModelInterceptor: { debug: true },
142
+ }
143
+
144
+ // Disable entirely
145
+ security: {
146
+ responseModelInterceptor: false,
147
+ }
148
+ ```
149
+
150
+ **For REST controllers**, you can use the `@ResponseModel()` decorator to explicitly specify the model class:
151
+
152
+ ```typescript
153
+ import { ResponseModel } from '@lenne.tech/nest-server';
154
+
155
+ @ResponseModel(User)
156
+ @Get(':id')
157
+ async getUser(@Param('id') id: string): Promise<User> {
158
+ // Even if this returns a plain object, the interceptor will convert it
159
+ return this.mainDbModel.findById(id).exec();
160
+ }
161
+ ```
162
+
163
+ ### 5. TranslateResponseInterceptor
164
+
165
+ Automatically applies `_translations` to response objects based on the `Accept-Language` header. Ensures translations work even when `CrudService.process()` is bypassed.
166
+
167
+ - Includes early bailout: skips recursive traversal when no `_translations` are present
168
+ - Zero overhead for non-translated responses
169
+
170
+ ```typescript
171
+ // config.env.ts - enabled by default
172
+
173
+ // Disable entirely
174
+ security: {
175
+ translateResponseInterceptor: false,
176
+ }
177
+ ```
178
+
179
+ ### 6. Fallback Secret Removal
180
+
181
+ `CheckSecurityInterceptor` now includes a configurable fallback that removes known secret fields from all responses, regardless of whether the response is a model instance.
182
+
183
+ ```typescript
184
+ // config.env.ts - enabled by default
185
+
186
+ // Default secret fields
187
+ security: {
188
+ secretFields: ['password', 'verificationToken', 'passwordResetToken', 'refreshTokens', 'tempTokens'],
189
+ }
190
+
191
+ // Custom secret fields
192
+ security: {
193
+ secretFields: ['password', 'apiKey', 'internalToken'],
194
+ }
195
+ ```
196
+
197
+ ### 7. RequestContext Service
198
+
199
+ New `RequestContext` service using Node.js `AsyncLocalStorage` provides the current user and request language in any context — including Mongoose hooks — without dependency injection.
200
+
201
+ ```typescript
202
+ import { RequestContext } from '@lenne.tech/nest-server';
203
+
204
+ // In any service, helper, or Mongoose hook:
205
+ const currentUser = RequestContext.getCurrentUser();
206
+ const language = RequestContext.getLanguage();
207
+ ```
208
+
209
+ ### 8. ModelRegistry Service
210
+
211
+ Central registry mapping Mongoose model names to CoreModel classes. Auto-populated when `ModuleService` is constructed. Used internally by `ResponseModelInterceptor`.
212
+
213
+ ```typescript
214
+ import { ModelRegistry } from '@lenne.tech/nest-server';
215
+
216
+ // Lookup a model class by Mongoose model name
217
+ const UserClass = ModelRegistry.getModelClass('User');
218
+ ```
219
+
220
+ ### 9. ModuleService Helper Methods
221
+
222
+ Two new helper methods for services that use direct Mongoose queries:
223
+
224
+ ```typescript
225
+ // processResult(): Simplified post-processing (population + prepareOutput)
226
+ const doc = await this.mainDbModel.findById(id).exec();
227
+ return this.processResult(doc, serviceOptions);
228
+
229
+ // applyTranslationInput(): Translation-aware input processing
230
+ const oldDoc = await this.mainDbModel.findById(id).lean();
231
+ input = this.applyTranslationInput(input, oldDoc, serviceOptions.language);
232
+ ```
233
+
234
+ ---
235
+
236
+ ## Configuration Reference
237
+
238
+ All new features follow the "enabled by default, opt-out via `false`" pattern:
239
+
240
+ | Config Path | Type | Default | Description |
241
+ |-------------|------|---------|-------------|
242
+ | `security.mongoosePasswordPlugin` | `boolean \| { skipPatterns }` | `true` | Auto password hashing |
243
+ | `security.mongooseRoleGuardPlugin` | `boolean \| { allowedRoles }` | `true` | Role escalation prevention |
244
+ | `security.mongooseAuditFieldsPlugin` | `boolean` | `true` | Auto createdBy/updatedBy |
245
+ | `security.responseModelInterceptor` | `boolean \| { debug }` | `true` | Plain→Model auto-conversion |
246
+ | `security.translateResponseInterceptor` | `boolean` | `true` | Auto translation application |
247
+ | `security.secretFields` | `string[]` | `['password', ...]` | Global secret field removal |
248
+ | `security.checkSecurityInterceptor.removeSecretFields` | `boolean` | `true` | Fallback secret removal |
249
+ | `security.checkSecurityInterceptor.secretFields` | `string[]` | `['password', ...]` | Interceptor-specific secret fields |
250
+
251
+ ---
252
+
253
+ ## Compatibility Notes
254
+
255
+ ### Existing CrudService Usage
256
+
257
+ **No changes required.** All existing code using `CrudService.process()` continues to work exactly as before. The Safety Net is purely additive — it catches cases that previously had no protection.
258
+
259
+ ### Double-Hashing Prevention
260
+
261
+ The password plugin detects already-hashed values using BCrypt pattern matching (`/^\$2[aby]\$\d+\$/`). If `CrudService.process()` already hashes a password via `prepareInput()`, the plugin will skip it. No double-hashing occurs.
262
+
263
+ ### Double-Mapping Prevention
264
+
265
+ The `ResponseModelInterceptor` checks `instanceof` and the `_objectAlreadyCheckedForRestrictions` flag. If `CrudService.process()` already mapped and checked an object, the interceptor skips it. No duplicate processing.
266
+
267
+ ### Direct Mongoose Usage (Advanced)
268
+
269
+ Projects that intentionally use direct Mongoose calls now get automatic security for free. For best results:
270
+
271
+ - **Output:** Return plain documents — the `ResponseModelInterceptor` handles conversion
272
+ - **Input:** Passwords are hashed automatically, roles are protected automatically
273
+ - **Audit fields:** `createdBy`/`updatedBy` are set automatically when `RequestContext` is available
274
+ - **Translations:** Use `this.applyTranslationInput()` before writes, responses are translated automatically
275
+
276
+ ### Performance
277
+
278
+ K6 benchmarks (10 VUs, 30s) show negligible overhead:
279
+
280
+ | Operation | Overhead vs Baseline |
281
+ |-----------|---------------------|
282
+ | signUp (bcrypt) | < 1% |
283
+ | signIn (bcrypt) | < 1% |
284
+ | getUser | ~2% (< 0.1ms absolute) |
285
+ | updateUser | ~7% (< 0.2ms absolute) |
286
+ | REST getUser | ~14% (~5ms absolute) |
287
+ | **Total throughput** | **-1.6%** |
288
+
289
+ ---
290
+
291
+ ## Troubleshooting
292
+
293
+ ### Sentinel password values are being hashed
294
+
295
+ If your application uses sentinel values for password locking (e.g. `!LOCKED:REQUIRES_PASSWORD_RESET`), configure skip patterns:
296
+
297
+ ```typescript
298
+ security: {
299
+ mongoosePasswordPlugin: {
300
+ skipPatterns: ['^!LOCKED:'],
301
+ },
302
+ }
303
+ ```
304
+
305
+ ### Roles are empty after creating users in a service
306
+
307
+ The Role Guard Plugin blocks role assignments from non-admin users. This affects services where a logged-in non-admin user creates other users with roles (e.g. HR systems, team management).
308
+
309
+ **Option A: Programmatic bypass** (for specific service operations):
310
+ ```typescript
311
+ import { RequestContext } from '@lenne.tech/nest-server';
312
+
313
+ // Wrap the operation — current user context is preserved
314
+ await RequestContext.runWithBypassRoleGuard(async () => {
315
+ await this.mainDbModel.create({ email, roles: ['EMPLOYEE'] });
316
+ });
317
+ ```
318
+
319
+ **Option B: CrudService force mode** (bypasses role guard automatically):
320
+ ```typescript
321
+ return this.process(
322
+ async () => this.mainDbModel.findByIdAndUpdate(id, { roles }),
323
+ { serviceOptions, force: true },
324
+ );
325
+ ```
326
+
327
+ **Option C: Config-based** (permanently allow specific roles to assign roles):
328
+ ```typescript
329
+ security: {
330
+ mongooseRoleGuardPlugin: {
331
+ allowedRoles: ['ORGA', 'HR_MANAGER'],
332
+ },
333
+ }
334
+ ```
335
+
336
+ > **Note:** `signUp` without a logged-in user is NOT affected — when no `currentUser` exists, the plugin allows role changes.
337
+
338
+ ### ResponseModelInterceptor not converting REST responses
339
+
340
+ For REST controllers, the interceptor resolves model types via Swagger metadata or the `@ResponseModel()` decorator. If neither is present, no auto-conversion occurs. Add the decorator explicitly:
341
+
342
+ ```typescript
343
+ @ResponseModel(User)
344
+ @Get(':id')
345
+ async getUser(@Param('id') id: string): Promise<User> { ... }
346
+ ```
347
+
348
+ ### Debug: Which responses are being auto-converted?
349
+
350
+ Enable debug mode to see warnings when the interceptor converts plain objects:
351
+
352
+ ```typescript
353
+ security: {
354
+ responseModelInterceptor: { debug: true },
355
+ }
356
+ ```
357
+
358
+ ---
359
+
360
+ ## New Exports
361
+
362
+ The following new exports are available from `@lenne.tech/nest-server`:
363
+
364
+ ```typescript
365
+ // Decorators
366
+ export { ResponseModel } from '@lenne.tech/nest-server';
367
+
368
+ // Interceptors
369
+ export { ResponseModelInterceptor } from '@lenne.tech/nest-server';
370
+ export { TranslateResponseInterceptor } from '@lenne.tech/nest-server';
371
+
372
+ // Plugins
373
+ export { mongoosePasswordPlugin } from '@lenne.tech/nest-server';
374
+ export { mongooseRoleGuardPlugin } from '@lenne.tech/nest-server';
375
+ export { mongooseAuditFieldsPlugin } from '@lenne.tech/nest-server';
376
+
377
+ // Services
378
+ export { ModelRegistry } from '@lenne.tech/nest-server';
379
+ export { RequestContext } from '@lenne.tech/nest-server';
380
+
381
+ // Middleware
382
+ export { RequestContextMiddleware } from '@lenne.tech/nest-server';
383
+
384
+ // Helpers
385
+ export { resolveResponseModelClass } from '@lenne.tech/nest-server';
386
+ ```
387
+
388
+ ---
389
+
390
+ ## References
391
+
392
+ - [nest-server-starter](https://github.com/lenneTech/nest-server-starter) (reference implementation)
393
+ - [Configurable Features Pattern](../.claude/rules/configurable-features.md)
@@ -0,0 +1,151 @@
1
+ # Migration Guide: 11.18.x → 11.19.0
2
+
3
+ ## Overview
4
+
5
+ | Category | Details |
6
+ |----------|---------|
7
+ | **Breaking Changes** | REST controller path prefix `api/` removed from ErrorCode and SystemSetup endpoints |
8
+ | **New Features** | None |
9
+ | **Bugfixes** | None |
10
+ | **Migration Effort** | Minimal (~2 minutes) - update proxy config and/or hardcoded fetch URLs |
11
+
12
+ ---
13
+
14
+ ## Quick Migration
15
+
16
+ ```bash
17
+ # Update package
18
+ npm install @lenne.tech/nest-server@11.19.0
19
+
20
+ # Verify build
21
+ npm run build
22
+
23
+ # Run tests
24
+ npm test
25
+ ```
26
+
27
+ ---
28
+
29
+ ## Breaking Changes
30
+
31
+ ### 1. REST Endpoint Paths Changed (Removed `api/` Prefix)
32
+
33
+ The `api/` prefix has been removed from two controller route paths to avoid conflicts with the Nuxt frontend proxy, which uses `/api/...` to forward requests to the backend.
34
+
35
+ **Affected endpoints:**
36
+
37
+ | Before | After |
38
+ |--------|-------|
39
+ | `GET /api/i18n/errors/:locale` | `GET /i18n/errors/:locale` |
40
+ | `GET /api/i18n/errors/codes` | `GET /i18n/errors/codes` |
41
+ | `GET /api/system-setup/status` | `GET /system-setup/status` |
42
+ | `POST /api/system-setup/init` | `POST /system-setup/init` |
43
+
44
+ **Why:** The Nuxt frontend proxy intercepts all `/api/...` requests and forwards them to the backend. When backend controllers also use `/api/...` as a route prefix, the paths conflict and cause issues with CORS and cookies during local development.
45
+
46
+ All other controllers (`auth`, `iam`, `files`, `tus`, `users`, etc.) already used paths without the `api/` prefix and are unaffected.
47
+
48
+ ---
49
+
50
+ ## Detailed Migration Steps
51
+
52
+ ### Step 1: Update Package
53
+
54
+ ```bash
55
+ npm install @lenne.tech/nest-server@11.19.0
56
+ ```
57
+
58
+ ### Step 2: Update Custom Controllers (If Applicable)
59
+
60
+ If your project has a custom controller extending `CoreErrorCodeController` or `CoreSystemSetupController`, update the `@Controller()` decorator:
61
+
62
+ **ErrorCode Controller:**
63
+
64
+ ```typescript
65
+ // Before
66
+ @Controller('api/i18n/errors')
67
+ export class ErrorCodeController { ... }
68
+
69
+ // After
70
+ @Controller('i18n/errors')
71
+ export class ErrorCodeController { ... }
72
+ ```
73
+
74
+ **SystemSetup Controller:**
75
+
76
+ ```typescript
77
+ // Before
78
+ @Controller('api/system-setup')
79
+ export class SystemSetupController extends CoreSystemSetupController { ... }
80
+
81
+ // After
82
+ @Controller('system-setup')
83
+ export class SystemSetupController extends CoreSystemSetupController { ... }
84
+ ```
85
+
86
+ ### Step 3: Update Frontend Fetch Calls
87
+
88
+ If your frontend makes direct fetch calls to these endpoints (without the Nuxt proxy), update the URLs:
89
+
90
+ ```typescript
91
+ // Before
92
+ const status = await fetch('/api/system-setup/status');
93
+ const errors = await fetch('/api/i18n/errors/de');
94
+
95
+ // After (direct backend calls)
96
+ const status = await fetch('/system-setup/status');
97
+ const errors = await fetch('/i18n/errors/de');
98
+
99
+ // If using Nuxt proxy (no change needed - proxy maps /api/* automatically)
100
+ const status = await fetch('/api/system-setup/status'); // proxy strips /api/
101
+ ```
102
+
103
+ ### Step 4: Update Reverse Proxy / Nginx Config (If Applicable)
104
+
105
+ If your deployment uses a reverse proxy with explicit route rules for these endpoints, update accordingly.
106
+
107
+ ---
108
+
109
+ ## Compatibility Notes
110
+
111
+ - **Nuxt proxy users:** If your Nuxt frontend uses the `/api/...` proxy (default in nuxt-extensions), no frontend changes are needed. The proxy strips the `/api/` prefix before forwarding to the backend.
112
+ - **Direct API consumers:** Any client calling the backend directly (e.g., mobile apps, scripts, Postman collections) must update the endpoint URLs.
113
+ - **Other endpoints unaffected:** `auth`, `iam`, `files`, `tus`, `users`, `avatar`, `health-check`, and `permissions` endpoints remain unchanged.
114
+
115
+ ---
116
+
117
+ ## Troubleshooting
118
+
119
+ ### Endpoints return 404 after update
120
+
121
+ **Cause:** Still using the old `/api/...` paths.
122
+
123
+ **Solution:** Remove the `api/` prefix from the endpoint URL:
124
+ - `/api/i18n/errors/de` → `/i18n/errors/de`
125
+ - `/api/system-setup/status` → `/system-setup/status`
126
+
127
+ ### Custom ErrorCode controller not working
128
+
129
+ **Cause:** Custom controller still uses `@Controller('api/i18n/errors')`.
130
+
131
+ **Solution:** Update the decorator to `@Controller('i18n/errors')`.
132
+
133
+ ---
134
+
135
+ ## Module Documentation
136
+
137
+ ### ErrorCode Module
138
+
139
+ - **README:** [src/core/modules/error-code/](../src/core/modules/error-code/)
140
+ - **Integration Checklist:** [INTEGRATION-CHECKLIST.md](../src/core/modules/error-code/INTEGRATION-CHECKLIST.md)
141
+
142
+ ### System Setup Module
143
+
144
+ - **README:** [src/core/modules/system-setup/README.md](../src/core/modules/system-setup/README.md)
145
+ - **Integration Checklist:** [INTEGRATION-CHECKLIST.md](../src/core/modules/system-setup/INTEGRATION-CHECKLIST.md)
146
+
147
+ ---
148
+
149
+ ## References
150
+
151
+ - [nest-server-starter](https://github.com/lenneTech/nest-server-starter) (reference implementation)