@authuser/nest 0.2.1 → 1.0.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/CHANGELOG.md CHANGED
@@ -5,6 +5,48 @@ This project uses [Semantic Versioning](https://semver.org/).
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [1.0.0] - 2026-09-03
9
+
10
+ ### Added
11
+
12
+ - Establish and document the stable 1.x public API contract.
13
+ - Add dynamic liveness and dependency-readiness checks with safe 503 failures.
14
+ - Return validated correlation IDs through a configurable response header.
15
+ - Verify the packed artifact from clean ESM and CommonJS consumers.
16
+ - Add cross-platform CI, release automation, contribution policies, a threat model,
17
+ and a production checklist.
18
+
19
+ ### Security
20
+
21
+ - Hide every 5xx exception message and log the original cause server-side.
22
+ - Remove query strings from error paths and request logs by default.
23
+ - Validate incoming request IDs instead of trusting Fastify's header passthrough.
24
+ - Reject invalid internal paths, overlapping Swagger routes, and invalid correlation
25
+ header names.
26
+ - Add tests for JSON prototype/constructor poisoning, body limits, handler deadlines,
27
+ shared rate-limit stores, and sensitive-data exposure.
28
+
29
+ ### Changed
30
+
31
+ - Make Nest and Fastify logging independently configurable. Setting
32
+ `observability.logger: false` no longer disables the Nest logger; use
33
+ `nest.logger: false` for that behavior.
34
+ - Add an explicit CommonJS export condition while retaining the native ESM build.
35
+ - Mark the entry point side effect so bundlers preserve `reflect-metadata` setup.
36
+ - Raise enforced coverage thresholds to 95% statements/lines/functions and 85%
37
+ branches.
38
+
39
+ ## [0.2.2] - 2026-09-03
40
+
41
+ ### Added
42
+
43
+ - Add optional standard Nest formatting for Fastify and HTTP request logs.
44
+
45
+ ### Fixed
46
+
47
+ - Compile the development example with TypeScript so Nest dependency-injection
48
+ metadata is preserved while watching files.
49
+
8
50
  ## [0.2.1] - 2026-09-03
9
51
 
10
52
  ### Changed
package/README.md CHANGED
@@ -6,6 +6,7 @@
6
6
  <p align="center">
7
7
  <a href="https://www.npmjs.com/package/@authuser/nest"><img alt="npm" src="https://img.shields.io/npm/v/%40authuser%2Fnest?style=flat-square"></a>
8
8
  <a href="https://www.npmjs.com/package/@authuser/nest"><img alt="downloads" src="https://img.shields.io/npm/dm/%40authuser%2Fnest?style=flat-square"></a>
9
+ <a href="https://github.com/authuser-org/nest/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/authuser-org/nest/actions/workflows/ci.yml/badge.svg"></a>
9
10
  <img alt="Node 22.12+" src="https://img.shields.io/badge/node-%3E%3D22.12-339933?style=flat-square&logo=node.js&logoColor=white">
10
11
  <img alt="NestJS 12" src="https://img.shields.io/badge/NestJS-12-E0234E?style=flat-square&logo=nestjs&logoColor=white">
11
12
  <img alt="Fastify 5" src="https://img.shields.io/badge/Fastify-5-black?style=flat-square&logo=fastify">
@@ -30,6 +31,10 @@ intact while removing repetitive bootstrap code.
30
31
  rate limiting.
31
32
  - Finite request, handler, header and connection timeouts.
32
33
  - Sensitive authorization, cookie and set-cookie log fields are redacted by default.
34
+ - Query strings are omitted from logs and error paths unless explicitly enabled.
35
+ - JSON logging by default, with an optional standard Nest console format.
36
+ - Correlated request IDs are validated and returned in `x-request-id`.
37
+ - Dynamic liveness and readiness checks fail closed with HTTP 503.
33
38
  - OpenAPI is optional at runtime. Its code is dynamically imported only when enabled.
34
39
  - HTTP QUERY (RFC 10008) passes through Nest 12/Fastify 5 and is included in CORS defaults.
35
40
  - Native ESM, strict declarations and a TypeScript 7 toolchain.
@@ -83,6 +88,9 @@ That application has Helmet, rate limiting, safe request IDs, strict validation,
83
88
  a 1 MiB body limit, finite timeouts and graceful shutdown hooks. Cross-origin
84
89
  requests are not enabled implicitly.
85
90
 
91
+ `1.x` follows Semantic Versioning: documented public exports and option behavior only
92
+ change incompatibly in a new major version. See the [API stability policy](https://github.com/authuser-org/nest/blob/main/docs/api-stability.md).
93
+
86
94
  ## Presets
87
95
 
88
96
  | Preset | Intended use | Enabled by default |
@@ -137,6 +145,25 @@ openApi: { enabled: true, preHandler: protectInternalRoute },
137
145
  health: { enabled: true, preHandler: protectInternalRoute },
138
146
  ```
139
147
 
148
+ ### Liveness and readiness
149
+
150
+ ```ts
151
+ health: {
152
+ enabled: true,
153
+ check: () => ({ status: 'live' }),
154
+ readiness: {
155
+ path: '/ready',
156
+ check: async () => {
157
+ await database.ping();
158
+ return { status: 'ready' };
159
+ },
160
+ },
161
+ }
162
+ ```
163
+
164
+ A thrown health check is logged internally and returned as a generic HTTP 503. Do
165
+ not include credentials, topology or personal data in successful health responses.
166
+
140
167
  ## Configuration examples
141
168
 
142
169
  ### CORS allowlist
@@ -178,7 +205,8 @@ await configureHttpApp(app, {
178
205
  ```
179
206
 
180
207
  Call `configureHttpApp` before `app.init()` or `app.listen()` so Fastify can register
181
- its plugins and routes.
208
+ its plugins and routes. When supplying your own adapter, request-ID generation and
209
+ network limits remain adapter responsibilities; `createApp` configures those safely.
182
210
 
183
211
  ## Public API
184
212
 
@@ -186,13 +214,16 @@ its plugins and routes.
186
214
  - `configureHttpApp(app, options)` — configure an existing Fastify-based Nest app.
187
215
  - `Public()` and `Roles(...roles)` — metadata helpers for your own guards.
188
216
  - `HttpExceptionFilter` — the default safe JSON exception filter.
217
+ - Public TypeScript contracts for configuration, health checks and error responses.
189
218
 
190
219
  The decorators intentionally do not provide authentication. Authentication policy
191
220
  belongs to the consuming application; pretending otherwise would create a dangerous
192
221
  security boundary.
193
222
 
194
223
  See the [complete option reference](https://github.com/authuser-org/nest/blob/main/docs/configuration.md), the
195
- [security model](https://github.com/authuser-org/nest/blob/main/docs/security.md), and the [performance guide](https://github.com/authuser-org/nest/blob/main/docs/performance.md).
224
+ [security model](https://github.com/authuser-org/nest/blob/main/docs/security.md), the
225
+ [production checklist](https://github.com/authuser-org/nest/blob/main/docs/production.md), and the
226
+ [performance guide](https://github.com/authuser-org/nest/blob/main/docs/performance.md).
196
227
 
197
228
  ## Performance notes
198
229
 
@@ -224,6 +255,8 @@ required integrations as normal dependencies. See the
224
255
  ```bash
225
256
  npm install
226
257
  npm run check
258
+ npm run test:coverage
259
+ npm run test:package
227
260
  ```
228
261
 
229
262
  An executable API and an importable Postman collection are available in the
package/SECURITY.md ADDED
@@ -0,0 +1,17 @@
1
+ # Security policy
2
+
3
+ ## Supported versions
4
+
5
+ Security fixes are provided for the latest minor release. Until version 1.0, a
6
+ security fix may include a documented breaking change when that is the safest
7
+ course.
8
+
9
+ Only maintained Node.js release lines accepted by `package.json` are supported.
10
+
11
+ ## Report a vulnerability
12
+
13
+ Do not open a public issue. Send a private report to `security@authuser.es` with
14
+ the affected version, reproduction steps and expected impact. You should receive
15
+ an acknowledgement within three business days.
16
+
17
+ Never include production credentials or personal data in a report.
package/SUPPORT.md ADDED
@@ -0,0 +1,11 @@
1
+ # Support
2
+
3
+ The latest `1.x` minor release receives bug and security fixes. Supported Node, Nest
4
+ and Fastify ranges are declared in `package.json`.
5
+
6
+ Use GitHub Issues for reproducible bugs and focused feature proposals. Include the
7
+ package version, Node version, package manager, minimal reproduction and relevant
8
+ sanitized logs. General Nest or Fastify usage questions should use their respective
9
+ community support channels.
10
+
11
+ Report vulnerabilities privately according to [SECURITY.md](./SECURITY.md).
@@ -1 +1 @@
1
- {"version":3,"file":"configure-http-app.d.ts","sourceRoot":"","sources":["../src/configure-http-app.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAKvE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE1D,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,sBAAsB,EAC3B,KAAK,GAAE,uBAA4B,GAClC,OAAO,CAAC,sBAAsB,CAAC,CAgEjC"}
1
+ {"version":3,"file":"configure-http-app.d.ts","sourceRoot":"","sources":["../src/configure-http-app.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAKvE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAG1D,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,sBAAsB,EAC3B,KAAK,GAAE,uBAA4B,GAClC,OAAO,CAAC,sBAAsB,CAAC,CA+EjC"}
@@ -53,13 +53,37 @@ export async function configureHttpApp(app, input = {}) {
53
53
  return payload;
54
54
  });
55
55
  }
56
+ if (options.observability.requestIdResponseHeader !== false) {
57
+ const header = options.observability.requestIdResponseHeader;
58
+ fastify.addHook('onRequest', async (request, reply) => {
59
+ reply.header(header, request.id);
60
+ });
61
+ }
56
62
  if (options.health.enabled) {
57
63
  fastify.get(options.health.path, {
58
64
  config: { rateLimit: false },
59
65
  ...(options.health.preHandler ? { preHandler: options.health.preHandler } : {}),
60
- }, async (_request, reply) => reply.send(options.health.response));
66
+ }, healthHandler(options.health.check, options.health.response));
67
+ }
68
+ if (options.health.readiness !== false) {
69
+ const readiness = options.health.readiness;
70
+ fastify.get(readiness.path, {
71
+ config: { rateLimit: false },
72
+ ...(readiness.preHandler ? { preHandler: readiness.preHandler } : {}),
73
+ }, healthHandler(readiness.check, { status: 'ready' }));
61
74
  }
62
75
  await registerOpenApi(app, fastify, options.openApi);
63
76
  return app;
64
77
  }
78
+ function healthHandler(check, fallback) {
79
+ return async (request, reply) => {
80
+ try {
81
+ return reply.send(check ? await check(request) : fallback);
82
+ }
83
+ catch (error) {
84
+ request.log.error({ err: error }, 'Health check failed');
85
+ return reply.status(503).send({ status: 'unavailable' });
86
+ }
87
+ };
88
+ }
65
89
  //# sourceMappingURL=configure-http-app.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"configure-http-app.js","sourceRoot":"","sources":["../src/configure-http-app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"configure-http-app.js","sourceRoot":"","sources":["../src/configure-http-app.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"create-app.d.ts","sourceRoot":"","sources":["../src/create-app.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,0BAA0B,CAAC;AAGlC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAInD,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAmC1F"}
1
+ {"version":3,"file":"create-app.d.ts","sourceRoot":"","sources":["../src/create-app.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,0BAA0B,CAAC;AAIlC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAInD,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAwC1F"}
@@ -3,14 +3,19 @@ import { LogController } from 'fastify';
3
3
  import { NestFactory } from '@nestjs/core';
4
4
  import { FastifyAdapter, } from '@nestjs/platform-fastify';
5
5
  import { configureHttpApp } from './configure-http-app.js';
6
+ import { NestFastifyLogger } from './nest-fastify.logger.js';
6
7
  import { resolveOptions } from './options.js';
7
8
  const SAFE_REQUEST_ID = /^[A-Za-z0-9._:-]{1,128}$/;
8
9
  export async function createApp(options) {
9
10
  const resolved = resolveOptions(options);
10
11
  const network = options.network ?? {};
11
12
  validateNetworkOptions(network);
13
+ const loggerOptions = resolved.observability.loggerFormat === 'nest'
14
+ && resolved.observability.logger !== false
15
+ ? { loggerInstance: new NestFastifyLogger(resolved.appName, resolved.observability.includeQueryString) }
16
+ : { logger: resolved.observability.logger };
12
17
  const adapter = new FastifyAdapter({
13
- logger: resolved.observability.logger,
18
+ ...loggerOptions,
14
19
  logController: new LogController({
15
20
  disableRequestLogging: !resolved.observability.requestLogging,
16
21
  }),
@@ -25,14 +30,12 @@ export async function createApp(options) {
25
30
  return503OnClosing: true,
26
31
  onProtoPoisoning: 'error',
27
32
  onConstructorPoisoning: 'error',
28
- requestIdHeader: 'x-request-id',
33
+ // Fastify trusts requestIdHeader verbatim; validate it ourselves in genReqId.
34
+ requestIdHeader: false,
29
35
  genReqId: safeRequestId,
30
36
  });
31
37
  adapter.getInstance().server.headersTimeout = network.headersTimeout ?? 30_000;
32
- const nestOptions = resolved.observability.logger === false
33
- ? { ...options.nest, logger: false }
34
- : { ...options.nest };
35
- const app = await NestFactory.create(options.rootModule, adapter, nestOptions);
38
+ const app = await NestFactory.create(options.rootModule, adapter, options.nest ?? {});
36
39
  return configureHttpApp(app, options);
37
40
  }
38
41
  function validateNetworkOptions(network) {
@@ -1 +1 @@
1
- {"version":3,"file":"create-app.js","sourceRoot":"","sources":["../src/create-app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"create-app.js","sourceRoot":"","sources":["../src/create-app.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"http-exception.filter.d.ts","sourceRoot":"","sources":["../src/http-exception.filter.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAIb,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAGxB,qBAAa,mBAAoB,YAAW,eAAe;IACzD,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI,CAqBnD;CACF"}
1
+ {"version":3,"file":"http-exception.filter.d.ts","sourceRoot":"","sources":["../src/http-exception.filter.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAIb,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAIxB,qBAAa,mBAAoB,YAAW,eAAe;IACzD,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI,CAwBnD;CACF"}
@@ -8,18 +8,21 @@ export class HttpExceptionFilter {
8
8
  const status = httpException?.getStatus() ?? HttpStatus.INTERNAL_SERVER_ERROR;
9
9
  const response = httpException?.getResponse();
10
10
  const details = typeof response === 'object' && response !== null ? response : {};
11
- const message = typeof response === 'string'
12
- ? response
13
- : getMessage(details) ?? (status === 500 ? 'Internal server error' : 'Request failed');
14
- if (status === 500)
11
+ const message = status >= 500
12
+ ? 'Internal server error'
13
+ : typeof response === 'string'
14
+ ? response
15
+ : getMessage(details) ?? 'Request failed';
16
+ if (status >= 500)
15
17
  request.log.error({ err: exception }, 'Unhandled request error');
16
- void reply.status(status).send({
18
+ const body = {
17
19
  statusCode: status,
18
20
  error: HttpStatus[status] ?? 'Error',
19
21
  message,
20
22
  requestId: request.id,
21
- path: request.url,
22
- });
23
+ path: request.url.split('?', 1)[0] ?? request.url,
24
+ };
25
+ void reply.status(status).send(body);
23
26
  }
24
27
  }
25
28
  Catch()(HttpExceptionFilter);
@@ -1 +1 @@
1
- {"version":3,"file":"http-exception.filter.js","sourceRoot":"","sources":["../src/http-exception.filter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http-exception.filter.js","sourceRoot":"","sources":["../src/http-exception.filter.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -3,5 +3,5 @@ export { configureHttpApp } from './configure-http-app.js';
3
3
  export { createApp } from './create-app.js';
4
4
  export { Public, Roles, IS_PUBLIC_KEY, ROLES_KEY } from './decorators.js';
5
5
  export { HttpExceptionFilter } from './http-exception.filter.js';
6
- export type { CompressionOptions, ConfigureHttpAppOptions, CorsOptions, CreateAppOptions, HealthOptions, NetworkOptions, ObservabilityOptions, OpenApiOptions, RateLimitOptions, SecurityOptions, SecurityPreset, } from './types.js';
6
+ export type { CompressionOptions, ConfigureHttpAppOptions, CorsOptions, CreateAppOptions, HealthCheck, HealthOptions, HttpErrorResponse, NetworkOptions, ObservabilityOptions, OpenApiOptions, RateLimitOptions, ReadinessOptions, SecurityOptions, SecurityPreset, } from './types.js';
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,YAAY,EACV,kBAAkB,EAClB,uBAAuB,EACvB,WAAW,EACX,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,cAAc,GACf,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAE1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,YAAY,EACV,kBAAkB,EAClB,uBAAuB,EACvB,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,cAAc,GACf,MAAM,YAAY,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { Logger } from '@nestjs/common';
2
+ import type { FastifyBaseLogger, FastifyLogFn } from 'fastify';
3
+ import type { Bindings } from 'pino';
4
+ /** Adapts Fastify's structured logger contract to Nest's standard console logger. */
5
+ export declare class NestFastifyLogger implements FastifyBaseLogger {
6
+ private readonly context;
7
+ private readonly includeQueryString;
8
+ private readonly bindings;
9
+ private readonly logger;
10
+ level: string;
11
+ readonly info: FastifyLogFn;
12
+ readonly error: FastifyLogFn;
13
+ readonly debug: FastifyLogFn;
14
+ readonly fatal: FastifyLogFn;
15
+ readonly warn: FastifyLogFn;
16
+ readonly trace: FastifyLogFn;
17
+ readonly silent: FastifyLogFn;
18
+ constructor(context: string, includeQueryString?: boolean, bindings?: Bindings, logger?: Logger);
19
+ child(bindings: Bindings): FastifyBaseLogger;
20
+ private write;
21
+ }
22
+ //# sourceMappingURL=nest-fastify.logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nest-fastify.logger.d.ts","sourceRoot":"","sources":["../src/nest-fastify.logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAIrC,qFAAqF;AACrF,qBAAa,iBAAkB,YAAW,iBAAiB;IAYvD,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAdzB,KAAK,SAAU;IAEf,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAoD;IAC/E,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAqD;IACjF,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAqD;IACjF,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAqD;IACjF,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAoD;IAC/E,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAqD;IACjF,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAmB;IAEhD,YACmB,OAAO,EAAE,MAAM,EACf,kBAAkB,UAAQ,EAC1B,QAAQ,GAAE,QAAa,EACvB,MAAM,SAAsB,EAC3C;IAEJ,KAAK,CAAC,QAAQ,EAAE,QAAQ,GAAG,iBAAiB,CAO3C;IAED,OAAO,CAAC,KAAK;CAsBd"}
@@ -0,0 +1,73 @@
1
+ import { Logger } from '@nestjs/common';
2
+ /** Adapts Fastify's structured logger contract to Nest's standard console logger. */
3
+ export class NestFastifyLogger {
4
+ context;
5
+ includeQueryString;
6
+ bindings;
7
+ logger;
8
+ level = 'info';
9
+ info = (...args) => this.write('info', args);
10
+ error = (...args) => this.write('error', args);
11
+ debug = (...args) => this.write('debug', args);
12
+ fatal = (...args) => this.write('fatal', args);
13
+ warn = (...args) => this.write('warn', args);
14
+ trace = (...args) => this.write('trace', args);
15
+ silent = () => undefined;
16
+ constructor(context, includeQueryString = false, bindings = {}, logger = new Logger(context)) {
17
+ this.context = context;
18
+ this.includeQueryString = includeQueryString;
19
+ this.bindings = bindings;
20
+ this.logger = logger;
21
+ }
22
+ child(bindings) {
23
+ return new NestFastifyLogger(this.context, this.includeQueryString, { ...this.bindings, ...bindings }, this.logger);
24
+ }
25
+ write(level, args) {
26
+ const message = formatLogMessage(args, this.bindings, this.includeQueryString);
27
+ switch (level) {
28
+ case 'error':
29
+ this.logger.error(message);
30
+ break;
31
+ case 'fatal':
32
+ this.logger.fatal(message);
33
+ break;
34
+ case 'warn':
35
+ this.logger.warn(message);
36
+ break;
37
+ case 'debug':
38
+ this.logger.debug(message);
39
+ break;
40
+ case 'trace':
41
+ this.logger.verbose(message);
42
+ break;
43
+ default:
44
+ this.logger.log(message);
45
+ }
46
+ }
47
+ }
48
+ function formatLogMessage(args, bindings, includeQueryString) {
49
+ const data = isRecord(args[0]) ? args[0] : undefined;
50
+ const text = args.find((value) => typeof value === 'string') ?? 'Fastify event';
51
+ const details = [];
52
+ const request = data && isRecord(data.req) ? data.req : undefined;
53
+ const response = data && isRecord(data.res) ? data.res : undefined;
54
+ const error = data && isRecord(data.err) ? data.err : undefined;
55
+ if (typeof request?.method === 'string')
56
+ details.push(request.method);
57
+ if (typeof request?.url === 'string') {
58
+ details.push(includeQueryString ? request.url : request.url.split('?', 1)[0] ?? '');
59
+ }
60
+ if (typeof response?.statusCode === 'number')
61
+ details.push(`status=${response.statusCode}`);
62
+ if (typeof data?.responseTime === 'number')
63
+ details.push(`duration=${data.responseTime.toFixed(2)}ms`);
64
+ if (typeof bindings.reqId === 'string')
65
+ details.push(`requestId=${bindings.reqId}`);
66
+ if (typeof error?.message === 'string')
67
+ details.push(`error=${error.message}`);
68
+ return details.length > 0 ? `${text} — ${details.join(' ')}` : text;
69
+ }
70
+ function isRecord(value) {
71
+ return typeof value === 'object' && value !== null;
72
+ }
73
+ //# sourceMappingURL=nest-fastify.logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nest-fastify.logger.js","sourceRoot":"","sources":["../src/nest-fastify.logger.ts"],"names":[],"mappings":"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"}
package/dist/options.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { CompressionOptions, ConfigureHttpAppOptions, CorsOptions, HealthOptions, OpenApiOptions, RateLimitOptions, SecurityPreset } from './types.js';
1
+ import type { CompressionOptions, ConfigureHttpAppOptions, CorsOptions, HealthOptions, HealthCheck, OpenApiOptions, RateLimitOptions, SecurityPreset } from './types.js';
2
2
  export interface ResolvedOptions {
3
3
  appName: string;
4
4
  preset: SecurityPreset;
@@ -13,7 +13,18 @@ export interface ResolvedOptions {
13
13
  };
14
14
  compression: Required<CompressionOptions>;
15
15
  openApi: Required<Omit<OpenApiOptions, 'preHandler'>> & Pick<OpenApiOptions, 'preHandler'>;
16
- health: Required<Omit<HealthOptions, 'preHandler'>> & Pick<HealthOptions, 'preHandler'>;
16
+ health: {
17
+ enabled: boolean;
18
+ path: string;
19
+ response: Readonly<Record<string, unknown>>;
20
+ check?: HealthCheck;
21
+ preHandler?: HealthOptions['preHandler'];
22
+ readiness: false | {
23
+ path: string;
24
+ check: HealthCheck;
25
+ preHandler?: HealthOptions['preHandler'];
26
+ };
27
+ };
17
28
  observability: Required<NonNullable<ConfigureHttpAppOptions['observability']>>;
18
29
  shutdownHooks: boolean;
19
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,uBAAuB,EACvB,WAAW,EACX,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,cAAc,EACf,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,cAAc,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,uBAAuB,CAAC,YAAY,CAAC,CAAC;IAClD,UAAU,EAAE,uBAAuB,CAAC,YAAY,CAAC,CAAC;IAClD,QAAQ,EAAE;QACR,MAAM,EAAE,OAAO,CAAC;QAChB,qBAAqB,EAAE,OAAO,CAAC;QAC/B,IAAI,EAAE,KAAK,GAAG,WAAW,CAAC;QAC1B,SAAS,EAAE,KAAK,IAAG,QAAQ,CAAC,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,KAAK,GAAG,YAAY,GAAG,KAAK,CAAC,CAAC,GAAG,gBAAgB,CAAA,CAAC;KAClH,CAAC;IACF,WAAW,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC;IAC1C,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC,GAAG,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;IAC3F,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC,GAAG,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IACxF,aAAa,EAAE,QAAQ,CAAC,WAAW,CAAC,uBAAuB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAC/E,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,uBAAuB,GAAG,eAAe,CAqFhF"}
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,uBAAuB,EACvB,WAAW,EACX,aAAa,EACb,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,cAAc,EACf,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,cAAc,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,uBAAuB,CAAC,YAAY,CAAC,CAAC;IAClD,UAAU,EAAE,uBAAuB,CAAC,YAAY,CAAC,CAAC;IAClD,QAAQ,EAAE;QACR,MAAM,EAAE,OAAO,CAAC;QAChB,qBAAqB,EAAE,OAAO,CAAC;QAC/B,IAAI,EAAE,KAAK,GAAG,WAAW,CAAC;QAC1B,SAAS,EAAE,KAAK,IAAG,QAAQ,CAAC,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,KAAK,GAAG,YAAY,GAAG,KAAK,CAAC,CAAC,GAAG,gBAAgB,CAAA,CAAC;KAClH,CAAC;IACF,WAAW,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC;IAC1C,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC,GAAG,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;IAC3F,MAAM,EAAE;QACN,OAAO,EAAE,OAAO,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;QAC5C,KAAK,CAAC,EAAE,WAAW,CAAC;QACpB,UAAU,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;QACzC,SAAS,EAAE,KAAK,GAAG;YACjB,IAAI,EAAE,MAAM,CAAC;YACb,KAAK,EAAE,WAAW,CAAC;YACnB,UAAU,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;SAC1C,CAAC;KACH,CAAC;IACF,aAAa,EAAE,QAAQ,CAAC,WAAW,CAAC,uBAAuB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAC/E,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,uBAAuB,GAAG,eAAe,CAoGhF"}
package/dist/options.js CHANGED
@@ -7,6 +7,10 @@ export function resolveOptions(options) {
7
7
  const compressionInput = typeof options.compression === 'object' ? options.compression : {};
8
8
  const openApiInput = typeof options.openApi === 'object' ? options.openApi : {};
9
9
  const healthInput = typeof options.health === 'object' ? options.health : {};
10
+ const readinessInput = healthInput.readiness === false || healthInput.readiness === undefined
11
+ ? false
12
+ : healthInput.readiness;
13
+ const includeQueryString = options.observability?.includeQueryString ?? false;
10
14
  const openApiEnabled = typeof options.openApi === 'boolean'
11
15
  ? options.openApi
12
16
  : openApiInput.enabled ?? openApiInput.ui ?? isFull;
@@ -69,11 +73,22 @@ export function resolveOptions(options) {
69
73
  enabled: typeof options.health === 'boolean' ? options.health : healthInput.enabled ?? isFull,
70
74
  path: normalizePath(healthInput.path ?? '/health'),
71
75
  response: healthInput.response ?? { status: 'ok' },
76
+ ...(healthInput.check ? { check: healthInput.check } : {}),
72
77
  ...(healthInput.preHandler ? { preHandler: healthInput.preHandler } : {}),
78
+ readiness: readinessInput === false
79
+ ? false
80
+ : {
81
+ path: normalizePath(readinessInput.path ?? '/ready'),
82
+ check: readinessInput.check,
83
+ ...(readinessInput.preHandler ? { preHandler: readinessInput.preHandler } : {}),
84
+ },
73
85
  },
74
86
  observability: {
75
- logger: resolveLogger(options.observability?.logger ?? true),
87
+ logger: resolveLogger(options.observability?.logger ?? true, includeQueryString),
88
+ loggerFormat: options.observability?.loggerFormat ?? 'json',
76
89
  requestLogging: options.observability?.requestLogging ?? false,
90
+ includeQueryString,
91
+ requestIdResponseHeader: options.observability?.requestIdResponseHeader ?? 'x-request-id',
77
92
  responseTimeHeader: options.observability?.responseTimeHeader ?? false,
78
93
  },
79
94
  shutdownHooks: options.shutdownHooks ?? true,
@@ -92,17 +107,45 @@ const SENSITIVE_LOG_PATHS = [
92
107
  'req.headers.cookie',
93
108
  'res.headers["set-cookie"]',
94
109
  ];
95
- function resolveLogger(logger) {
110
+ function resolveLogger(logger, includeQueryString) {
96
111
  if (logger === false)
97
112
  return false;
113
+ const requestSerializer = (request) => ({
114
+ method: request.method,
115
+ url: safePath(typeof request.url === 'string' ? request.url : '', includeQueryString),
116
+ host: request.host,
117
+ remoteAddress: request.ip,
118
+ });
98
119
  if (logger === true) {
99
- return { redact: { paths: SENSITIVE_LOG_PATHS, censor: '[REDACTED]' } };
120
+ return {
121
+ redact: { paths: SENSITIVE_LOG_PATHS, censor: '[REDACTED]' },
122
+ serializers: { req: requestSerializer },
123
+ };
100
124
  }
101
- return logger.redact === undefined
102
- ? { ...logger, redact: { paths: SENSITIVE_LOG_PATHS, censor: '[REDACTED]' } }
103
- : logger;
125
+ return {
126
+ ...logger,
127
+ ...(logger.redact === undefined
128
+ ? { redact: { paths: SENSITIVE_LOG_PATHS, censor: '[REDACTED]' } }
129
+ : {}),
130
+ serializers: {
131
+ req: requestSerializer,
132
+ ...logger.serializers,
133
+ },
134
+ };
104
135
  }
105
136
  function validateResolvedOptions(options) {
137
+ if (options.appName.trim().length === 0 || options.appName.length > 128) {
138
+ throw new TypeError('Application name must contain 1 to 128 characters');
139
+ }
140
+ if (options.apiPrefix !== undefined && (options.apiPrefix.length > 1_024
141
+ || options.apiPrefix.includes('?')
142
+ || options.apiPrefix.includes('#')
143
+ || options.apiPrefix.includes('\0'))) {
144
+ throw new TypeError('API prefix must be a valid URL path prefix');
145
+ }
146
+ if (!Number.isSafeInteger(options.compression.threshold) || options.compression.threshold < 0) {
147
+ throw new TypeError('Compression threshold must be a non-negative safe integer');
148
+ }
106
149
  const cors = options.security.cors;
107
150
  if (cors !== false && cors.credentials === true && cors.origin === true) {
108
151
  throw new TypeError('CORS credentials cannot be combined with an unrestricted origin');
@@ -111,13 +154,28 @@ function validateResolvedOptions(options) {
111
154
  options.health.enabled ? options.health.path : undefined,
112
155
  options.openApi.enabled && options.openApi.json ? options.openApi.jsonPath : undefined,
113
156
  options.openApi.enabled && options.openApi.ui ? options.openApi.uiPath : undefined,
157
+ options.health.readiness !== false ? options.health.readiness.path : undefined,
114
158
  ].filter((path) => path !== undefined);
115
- if (new Set(paths).size !== paths.length) {
159
+ if (paths.some((path, index) => paths.some((other, otherIndex) => (index !== otherIndex && (path === other || path.startsWith(`${other}/`) || other.startsWith(`${path}/`)))))) {
116
160
  throw new TypeError('Health, OpenAPI JSON and Swagger UI paths must be unique');
117
161
  }
162
+ for (const path of paths)
163
+ validateInternalPath(path);
164
+ const requestIdHeader = options.observability.requestIdResponseHeader;
165
+ if (requestIdHeader !== false && !/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/.test(requestIdHeader)) {
166
+ throw new TypeError('Request ID response header must be a valid HTTP header name');
167
+ }
118
168
  const rateLimit = options.security.rateLimit;
119
169
  if (rateLimit !== false && typeof rateLimit.max === 'number' && (!Number.isFinite(rateLimit.max) || rateLimit.max <= 0)) {
120
170
  throw new TypeError('Rate limit max must be a positive number');
121
171
  }
122
172
  }
173
+ function validateInternalPath(path) {
174
+ if (path.length > 2_048 || path.includes('?') || path.includes('#') || path.includes('\0')) {
175
+ throw new TypeError(`Invalid internal route path: ${path}`);
176
+ }
177
+ }
178
+ function safePath(url, includeQueryString) {
179
+ return includeQueryString ? url : url.split('?', 1)[0] ?? '';
180
+ }
123
181
  //# sourceMappingURL=options.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { LoggerOptions } from 'pino';
2
2
  import type rateLimit from '@fastify/rate-limit';
3
3
  import type { Type, ValidationPipeOptions, VersioningOptions } from '@nestjs/common';
4
4
  import type { NestApplicationOptions } from '@nestjs/common/interfaces/nest-application-options.interface';
5
- import type { preHandlerHookHandler } from 'fastify';
5
+ import type { FastifyRequest, preHandlerHookHandler } from 'fastify';
6
6
  export type SecurityPreset = 'minimal' | 'secure' | 'full';
7
7
  export interface CorsOptions {
8
8
  /** No cross-origin requests are allowed by default. */
@@ -50,15 +50,38 @@ export interface HealthOptions {
50
50
  enabled?: boolean;
51
51
  path?: string;
52
52
  response?: Readonly<Record<string, unknown>>;
53
+ /** Dynamic liveness check. Throwing produces a safe HTTP 503 response. */
54
+ check?: HealthCheck;
53
55
  /** Fastify hook for restricting the health route. */
54
56
  preHandler?: preHandlerHookHandler;
57
+ /** Optional dependency-readiness endpoint. */
58
+ readiness?: false | ReadinessOptions;
59
+ }
60
+ export type HealthCheck = (request: FastifyRequest) => Readonly<Record<string, unknown>> | Promise<Readonly<Record<string, unknown>>>;
61
+ export interface ReadinessOptions {
62
+ path?: string;
63
+ check: HealthCheck;
64
+ preHandler?: preHandlerHookHandler;
55
65
  }
56
66
  export interface ObservabilityOptions {
57
- /** Fastify/Pino logging. False removes request logging overhead. */
67
+ /** Fastify logging. An options object configures the default Pino JSON logger. */
58
68
  logger?: boolean | LoggerOptions;
69
+ /** JSON is optimal for production ingestion; nest uses Nest's readable console format. */
70
+ loggerFormat?: 'json' | 'nest';
59
71
  requestLogging?: boolean;
72
+ /** Query strings may contain secrets or personal data and are omitted by default. */
73
+ includeQueryString?: boolean;
74
+ /** Response correlation header. False disables it. */
75
+ requestIdResponseHeader?: string | false;
60
76
  responseTimeHeader?: boolean;
61
77
  }
78
+ export interface HttpErrorResponse {
79
+ statusCode: number;
80
+ error: string;
81
+ message: unknown;
82
+ requestId: string;
83
+ path: string;
84
+ }
62
85
  export interface NetworkOptions {
63
86
  trustProxy?: boolean | string | string[];
64
87
  bodyLimit?: number;
@@ -86,6 +109,7 @@ export interface ConfigureHttpAppOptions {
86
109
  export interface CreateAppOptions extends ConfigureHttpAppOptions {
87
110
  rootModule: Type<unknown>;
88
111
  network?: NetworkOptions;
89
- nest?: Omit<NestApplicationOptions, 'logger'>;
112
+ /** Native Nest factory options, including an independent Nest logger. */
113
+ nest?: NestApplicationOptions;
90
114
  }
91
115
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ # API stability policy
2
+
3
+ Version 1 follows Semantic Versioning. The supported public API is the root export
4
+ documented in `README.md` and the TypeScript declarations reachable from it.
5
+
6
+ ## Compatibility guarantees
7
+
8
+ - Patch releases fix bugs and security issues without intentionally breaking valid
9
+ 1.x configurations.
10
+ - Minor releases may add optional exports, options and preset capabilities. Existing
11
+ explicit options retain their behavior.
12
+ - Removed or renamed APIs require a deprecation in a minor release and removal in
13
+ the next major release, except when continued behavior creates a critical security
14
+ vulnerability.
15
+ - Undocumented `dist/*` paths and internal classes are not public API.
16
+ - Node, Nest and Fastify support ranges are declared in `package.json`. Dropping a
17
+ supported major runtime requires a new package major version.
18
+
19
+ The stable runtime exports are `createApp`, `configureHttpApp`, `Public`, `Roles`,
20
+ their metadata keys, and `HttpExceptionFilter`. Exported configuration and response
21
+ types are part of the TypeScript contract.
22
+
23
+ ## Deprecation process
24
+
25
+ A deprecation is documented in the changelog and migration guide. When practical,
26
+ the previous behavior remains available throughout the current major release.
@@ -13,7 +13,7 @@ All settings are optional except `rootModule` when using `createApp`.
13
13
  | `versioning` | `false` | `true` for URI versioning, or Nest versioning options. |
14
14
  | `shutdownHooks` | `true` | Enable Nest shutdown signal hooks. |
15
15
  | `validation` | strict defaults | `false` or Nest `ValidationPipeOptions`. |
16
- | `nest` | `{}` | Extra `NestApplicationOptions` except logger. |
16
+ | `nest` | `{}` | Native `NestApplicationOptions`, including its independent logger. |
17
17
 
18
18
  Default validation uses `whitelist: true`, `forbidNonWhitelisted: true`, and
19
19
  `transform: false`. Transformation is off because implicit coercion costs work and
@@ -71,15 +71,56 @@ known payloads rather than automatically for every API.
71
71
 
72
72
  Set `openApi: false` to guarantee the documentation integration is never loaded.
73
73
 
74
- ## Health and observability
74
+ ## Health
75
75
 
76
76
  The full preset serves `{ "status": "ok" }` at `/health`. This is a liveness probe,
77
- not a dependency-readiness check. Supply a custom response or implement a Nest
78
- controller for deeper readiness logic. Use `health.preHandler` when the endpoint
79
- must not be public.
80
-
81
- Fastify's Pino logger is enabled, while per-request logging is disabled to reduce
82
- noise and overhead. Enable it with `observability.requestLogging`. The optional
83
- `responseTimeHeader` emits a standards-compatible `Server-Timing` value. Default
84
- logging redacts authorization, cookie and set-cookie fields. A custom Pino `redact`
85
- configuration overrides those defaults.
77
+ not a dependency-readiness check. `health.check` supplies a dynamic liveness result.
78
+ `health.readiness.check` adds a separate `/ready` endpoint for dependencies. A thrown
79
+ check returns only `{ "status": "unavailable" }` with HTTP 503 and logs the original
80
+ error internally. Health endpoints bypass the global rate limit so probes cannot
81
+ evict application traffic. Use `preHandler` when an endpoint must not be public.
82
+
83
+ | Option | Default | Description |
84
+ | --- | --- | --- |
85
+ | `health.enabled` | full preset only | Enable liveness. |
86
+ | `health.path` | `/health` | Liveness route. |
87
+ | `health.response` | `{ status: 'ok' }` | Static liveness response. |
88
+ | `health.check` | none | Dynamic liveness callback. |
89
+ | `health.preHandler` | none | Access-control hook for liveness. |
90
+ | `health.readiness` | `false` | Object containing a required `check`. |
91
+ | `health.readiness.path` | `/ready` | Readiness route. |
92
+ | `health.readiness.preHandler` | none | Access-control hook for readiness. |
93
+
94
+ ## Observability
95
+
96
+ Fastify's Pino JSON logger is enabled by default, while per-request logging is
97
+ disabled to reduce noise and overhead. Enable it with
98
+ `observability.requestLogging`. Set `observability.loggerFormat: 'nest'` for the
99
+ readable standard Nest console format; JSON remains recommended for production log
100
+ ingestion and maximum throughput. The Nest adapter only emits selected request
101
+ metadata and never serializes headers or bodies.
102
+
103
+ The optional `responseTimeHeader` emits a standards-compatible `Server-Timing`
104
+ value. Default JSON logging redacts authorization, cookie and set-cookie fields. A
105
+ custom Pino `redact` configuration overrides those defaults. Likewise, a custom
106
+ `serializers.req` replaces the safe request serializer, so redaction of URL data
107
+ then becomes the application's responsibility.
108
+
109
+ | Option | Default | Description |
110
+ | --- | --- | --- |
111
+ | `observability.logger` | `true` | `false`, or Pino configuration for JSON logs. |
112
+ | `observability.loggerFormat` | `json` | `json` or readable `nest`. |
113
+ | `observability.requestLogging` | `false` | Log request start and completion. |
114
+ | `observability.includeQueryString` | `false` | Include potentially sensitive query strings in request logs. |
115
+ | `observability.requestIdResponseHeader` | `x-request-id` | Correlation response header, or `false`. |
116
+ | `observability.responseTimeHeader` | `false` | Emit `Server-Timing`. |
117
+
118
+ The Fastify logger and Nest logger are independent. Disable both explicitly with
119
+ `observability.logger: false` and `nest.logger: false`.
120
+
121
+ ## Error response contract
122
+
123
+ Client-visible errors use the exported `HttpErrorResponse` shape: `statusCode`,
124
+ `error`, `message`, `requestId`, and `path`. Query strings never appear in `path`.
125
+ Every status from 500 through 599 receives the generic message `Internal server
126
+ error`; the original exception is available only in server logs.
package/docs/migration.md CHANGED
@@ -24,3 +24,15 @@ application and this package share one framework instance.
24
24
  `AuthuserModule` and `AUTHUSER_OPTIONS` were removed because their configuration was
25
25
  not connected to adapter creation. Configure the application exclusively through
26
26
  `createApp` or `configureHttpApp`.
27
+
28
+ ## Migrating from 0.x to 1.x
29
+
30
+ - `observability.logger: false` disables Fastify logging only. Use
31
+ `nest.logger: false` when Nest logs must also be disabled.
32
+ - Responses include `x-request-id` by default. Set
33
+ `observability.requestIdResponseHeader: false` to opt out.
34
+ - Request logs omit query strings by default. Set
35
+ `observability.includeQueryString: true` only after reviewing data exposure.
36
+ - All 5xx response messages are generic and error paths omit query strings.
37
+ - Internal route paths must be unique and cannot contain query strings or fragments.
38
+ - `health.check` and `health.readiness` provide dynamic probe callbacks.
@@ -17,6 +17,10 @@ trades bandwidth for CPU. OpenAPI generation happens at startup, and its modules
17
17
  not imported when disabled. Helmet, CORS, rate limiting and compression are also
18
18
  dynamically imported only when their configuration enables them.
19
19
 
20
+ Pino JSON is the production logging default. The Nest-formatted adapter prioritizes
21
+ human readability and is intended primarily for local development; benchmark it
22
+ before enabling per-request Nest logs on a high-throughput service.
23
+
20
24
  ## Reproducible baseline
21
25
 
22
26
  Run the dependency-free local regression benchmark:
@@ -30,6 +34,18 @@ Change duration and concurrency with `BENCHMARK_DURATION_MS` and
30
34
  minimal preset and the secure preset. Treat them as a regression signal rather than
31
35
  a production capacity promise.
32
36
 
37
+ The 1.0.0 release check on Node 22.14 with 100 local connections produced this
38
+ single-run baseline:
39
+
40
+ | Scenario | Requests/s | p50 | p99 | Errors |
41
+ | --- | ---: | ---: | ---: | ---: |
42
+ | Fastify raw | 30,703 | 3.23 ms | 3.73 ms | 0 |
43
+ | `@authuser/nest` minimal | 26,602 | 3.68 ms | 4.40 ms | 0 |
44
+ | `@authuser/nest` secure | 19,807 | 4.98 ms | 6.31 ms | 0 |
45
+
46
+ That run retained about 87% of raw Fastify throughput in `minimal` and 65% in
47
+ `secure`. It is a local regression reference, not a service capacity guarantee.
48
+
33
49
  ## Choosing a lower-level stack
34
50
 
35
51
  If profiling shows Nest itself is the bottleneck, raw Fastify is the closest smaller
@@ -0,0 +1,45 @@
1
+ # Production checklist
2
+
3
+ Use this list before exposing a service to untrusted traffic.
4
+
5
+ ## Application
6
+
7
+ - Start from the `secure` preset and document every disabled control.
8
+ - Authenticate and authorize sensitive routes with application guards.
9
+ - Keep `Public()` usage explicit and covered by authorization tests.
10
+ - Validate business rules, file uploads and data leaving persistence layers.
11
+ - Use `nest.logger` and `observability.logger` intentionally.
12
+
13
+ ## Network and edge
14
+
15
+ - Terminate TLS at a trusted edge and redirect plaintext traffic.
16
+ - Configure `network.trustProxy` only for known proxy addresses or networks.
17
+ - Apply an infrastructure-level request/body limit no larger than the application
18
+ limit where possible.
19
+ - Tune connection, header, request and handler timeouts against production latency.
20
+ - Use an upstream DDoS control for an internet-facing API.
21
+
22
+ ## Distributed operation
23
+
24
+ - Configure Redis or another shared `@fastify/rate-limit` store for multiple replicas.
25
+ - Give login, recovery and expensive routes stricter endpoint-specific limits.
26
+ - Keep liveness independent of downstream dependencies.
27
+ - Put database, queue and critical service checks in readiness.
28
+ - Ensure the orchestrator removes a replica when readiness returns 503.
29
+
30
+ ## Exposure and data
31
+
32
+ - Disable or protect Swagger UI and OpenAPI in production.
33
+ - Do not return credentials or topology from health checks.
34
+ - Keep secrets and personal data out of URLs and logs.
35
+ - Keep JSON log redaction enabled and extend it for application-specific fields.
36
+ - Add CSRF protection when browsers authenticate with ambient cookies.
37
+
38
+ ## Release
39
+
40
+ - Run `npm run check`, `npm run test:coverage`, `npm run test:package`, and
41
+ `npm run smoke --prefix example`.
42
+ - Review `npm audit --omit=dev` and dependency updates.
43
+ - Load-test realistic payloads through the production proxy and TLS path.
44
+ - Exercise shutdown while requests are active.
45
+ - Monitor latency percentiles, error rate, event-loop utilization and memory.
@@ -0,0 +1,28 @@
1
+ # Release process
2
+
3
+ ## Preparation
4
+
5
+ 1. Ensure `main` is green and the worktree is clean.
6
+ 2. Update `CHANGELOG.md` and the package version using Semantic Versioning.
7
+ 3. Run `npm run check`, `npm run test:coverage`, `npm run test:package`, and
8
+ `npm run smoke --prefix example`.
9
+ 4. Commit the release and create an annotated `vX.Y.Z` tag at that commit.
10
+ 5. Push the commit and tag.
11
+
12
+ ## Trusted publishing
13
+
14
+ Configure npm trusted publishing for:
15
+
16
+ - Organization/user: `authuser-org`
17
+ - Repository: `nest`
18
+ - Workflow: `.github/workflows/release.yml`
19
+ - Environment: `npm`
20
+
21
+ Create a GitHub Release from the version tag. The release workflow verifies that the
22
+ tag equals `package.json`, repeats all release checks, and publishes with npm
23
+ provenance through GitHub OIDC. No long-lived npm token should be stored in GitHub.
24
+
25
+ ## Verification
26
+
27
+ Confirm the npm version and provenance, install it into a clean project, and verify
28
+ that the GitHub tag resolves to the same commit used by the release workflow.
package/docs/security.md CHANGED
@@ -9,11 +9,14 @@ The secure preset establishes a baseline, not a complete application security mo
9
9
  - A one MiB default request-body limit.
10
10
  - Finite connection, request, handler and header timeouts.
11
11
  - Rate limiting by client IP.
12
- - Request IDs restricted to 128 safe characters before log propagation.
13
- - Generic internal errors; unexpected exceptions are logged server-side only.
12
+ - `createApp` request IDs restricted to 128 safe characters before log propagation.
13
+ - Correlation IDs returned to clients in a configurable response header.
14
+ - Generic 5xx errors; unexpected exceptions are logged server-side only.
14
15
  - CORS disabled until an allowlist is configured.
15
16
  - Sensitive authentication and cookie log fields redacted by default.
17
+ - Query strings excluded from default request logs and error response paths.
16
18
  - Optional pre-handler protection for documentation and health routes.
19
+ - Dynamic readiness checks that fail closed without exposing dependency errors.
17
20
 
18
21
  ## Application responsibilities
19
22
 
@@ -26,6 +29,9 @@ The secure preset establishes a baseline, not a complete application security mo
26
29
  - Use TLS at the load balancer or application edge.
27
30
  - Keep Node and dependencies patched and review `npm audit` output.
28
31
  - Avoid exposing Swagger UI and detailed readiness data publicly.
32
+ - Keep credentials, tokens and personal data out of URL query parameters.
33
+ - Preserve the default request serializer, or redact equivalent data in a custom
34
+ Pino `serializers.req` implementation.
29
35
  - Add CSRF protection when authentication relies on ambient cookies or sessions.
30
36
 
31
37
  `Public()` and `Roles()` only attach metadata. They do nothing until an application
@@ -0,0 +1,41 @@
1
+ # Threat model
2
+
3
+ `@authuser/nest` hardens the HTTP process boundary for a Nest application. It does
4
+ not establish user identity or decide whether a caller may access a business object.
5
+
6
+ ## Protected assets
7
+
8
+ - Availability of the Node process and its event loop.
9
+ - Confidentiality of request credentials and internal exception details.
10
+ - Integrity of parsed JSON objects and request correlation identifiers.
11
+ - Predictable application bootstrap and shutdown behavior.
12
+
13
+ ## Included mitigations
14
+
15
+ - Bounded bodies, parameters, sockets and finite timeouts reduce common resource
16
+ exhaustion paths.
17
+ - Prototype and constructor poisoning are rejected during JSON parsing.
18
+ - Helmet establishes browser-facing security headers.
19
+ - Strict DTO defaults reject unexpected properties.
20
+ - CORS is closed until explicitly configured.
21
+ - Rate limiting controls abusive clients per instance or shared store.
22
+ - Incoming request IDs are validated by `createApp` before they reach logs.
23
+ - Sensitive headers and query strings are excluded from default logs.
24
+ - All 5xx details and health-check failures are hidden from clients.
25
+
26
+ ## Explicitly out of scope
27
+
28
+ - Authentication, authorization, tenancy and object-level access control.
29
+ - TLS termination, WAF, network policy and volumetric DDoS protection.
30
+ - Database query construction, encryption, secret storage and key rotation.
31
+ - CSRF defenses for cookie-authenticated applications.
32
+ - Malware scanning, file validation and non-HTTP ingestion.
33
+
34
+ ## Trust assumptions
35
+
36
+ - Nest, Fastify and direct dependencies are kept on supported patched versions.
37
+ - `trustProxy` contains only infrastructure controlled by the operator.
38
+ - A distributed deployment uses a shared rate-limit store.
39
+ - Application code does not deliberately log or expose sensitive data.
40
+ - Applications calling `configureHttpApp` directly configure equivalent request-ID
41
+ and network limits on their own Fastify adapter.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@authuser/nest",
3
- "version": "0.2.1",
3
+ "version": "1.0.0",
4
4
  "description": "Secure, high-performance NestJS foundation powered by Fastify",
5
5
  "keywords": [
6
6
  "nestjs",
@@ -19,17 +19,23 @@
19
19
  ".": {
20
20
  "types": "./dist/index.d.ts",
21
21
  "import": "./dist/index.js",
22
+ "require": "./dist/index.js",
22
23
  "default": "./dist/index.js"
23
- }
24
+ },
25
+ "./package.json": "./package.json"
24
26
  },
25
27
  "files": [
26
28
  "dist",
27
29
  "docs",
28
30
  "README.md",
29
31
  "CHANGELOG.md",
32
+ "SECURITY.md",
33
+ "SUPPORT.md",
30
34
  "LICENSE"
31
35
  ],
32
- "sideEffects": false,
36
+ "sideEffects": [
37
+ "./dist/index.js"
38
+ ],
33
39
  "engines": {
34
40
  "node": ">=22.12"
35
41
  },
@@ -43,8 +49,10 @@
43
49
  "typecheck": "tsc -p tsconfig.json --noEmit",
44
50
  "test": "vitest run",
45
51
  "test:coverage": "vitest run --coverage",
52
+ "test:package": "npm run build && node scripts/verify-package.mjs",
46
53
  "benchmark": "npm run build && node benchmark/run.mjs",
47
54
  "prepack": "npm run clean && npm run build",
55
+ "prepublishOnly": "npm run check && npm run test:package",
48
56
  "check": "npm run typecheck && npm test && npm run build && npm pack --dry-run"
49
57
  },
50
58
  "dependencies": {