@bymax-one/nest-logger 1.4.1 → 1.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -11,6 +11,163 @@ heading here.
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [1.4.3] - 2026-10-31
15
+
16
+ ### Added
17
+
18
+ - `LOGGER_REDACTOR_TOKEN`, `REDACT_COMMON_FIELDS` and `isValidTraceId` are exported from the package
19
+ root. The token is the injection point of `PinoLoggerService`'s redactor, so a consumer composing
20
+ its own providers can now name it. `REDACT_COMMON_FIELDS` is the name list the
21
+ default redactor matches, and `DEFAULT_REDACT_PATHS` is built from it, so extending the defaults no
22
+ longer means copying the names. `isValidTraceId` is the check the trace mixin already applies.
23
+ `sanitizeError` stays internal: its output shape is not a contract this release commits to.
24
+
25
+ ### Deprecated
26
+
27
+ - `@LogContext(name)` is marked `@deprecated`. It records a label as class metadata and nothing in
28
+ the package reads it, so the label has never been applied. `@InjectLogger(MyClass.name)` is the
29
+ working equivalent. `shouldUseAsNestLogger` was already deprecated and is unchanged.
30
+
31
+ ### Fixed
32
+
33
+ - **A custom `timestamp` can no longer break the log line or add fields to it.** Pino inserts the
34
+ value into the JSON line verbatim, and the library wrapped it in quotes without encoding it, so a
35
+ quote, a backslash or a newline in the returned string produced invalid JSON for every entry, and a
36
+ crafted value such as `","injected":"x` added a field. The value is now encoded as a JSON string,
37
+ and `time` carries exactly what the function returned.
38
+
39
+ ### Breaking
40
+
41
+ - **`http.excludePaths` now excludes `/health/live` and `/health/ready` by default**, the probes of
42
+ `@bymax-one/nest-core`, so the defaults are `/health`, `/health/live`, `/health/ready` and
43
+ `/metrics`. A probe hit every few seconds drowned the record (8272 of 8274 entries on one
44
+ deployment). Each default is an exact, anchored path, so a route such as `/health/other` is still
45
+ logged.
46
+ - **Options are validated more strictly at bootstrap**, each rejection naming the option and, where
47
+ there is a value to show, what was received. Added checks: `maxEntrySizeBytes` must be a finite number (a `NaN` or `Infinity`
48
+ made the size gate never trip); `isGlobal`, `shouldDisableDefaultRedact` and the `http` and `otel`
49
+ switches must be booleans (the string `'false'` is truthy); `redactCensor` a string; `timestamp` a
50
+ function; `redactPaths` an array of non-empty strings; `serializers` an object of functions;
51
+ `destinations` an array whose entries have a `write` method, a non-empty `name` and function hooks;
52
+ `http` and `otel` objects; `http.excludePaths` an array of `RegExp` (a pattern from another realm,
53
+ such as a `vm` context, is accepted); `http.tenantIdHeader` and the
54
+ three `otel.*Field` names non-empty strings; `otel.fieldFormat` `'camelCase'` or `'snake_case'`
55
+ (an unknown value silently behaved as `camelCase`).
56
+ - **`PrettyDevDestination` refuses to initialize when `NODE_ENV` is `production`.** The 0.1.0 entry
57
+ said it was auto-disabled in production, and nothing did that: registered there it rendered ANSI
58
+ colour through a main-thread transform into the log stream. It now fails at `onInit()` with a
59
+ message naming the cause; the registry reports `LOGGER_DESTINATION_INIT_FAILED` on stderr, later
60
+ writes to it are dropped, and when it is the only destination entries go to stdout as raw NDJSON.
61
+ Only the exact value `production` refuses.
62
+
63
+ #### Apply to a consumer
64
+
65
+ - A deployment whose own `/health/live` or `/health/ready` route should stay in the log now sets
66
+ `http.excludePaths` itself. A value replaces the defaults, and `[/^\/health$/, /^\/metrics$/]`
67
+ restores the previous list.
68
+ - An application that passed a value of the wrong kind, such as `http: { isEnabled: 'false' }` or a
69
+ destination without a `name`, now fails at bootstrap with a message naming the option, where it
70
+ previously booted with that value ignored or misread. Correct the value.
71
+ - A deployment that registers `PrettyDevDestination` with `NODE_ENV=production` now gets raw JSON on
72
+ stdout and one stderr line instead of coloured output. Register it only outside production, for
73
+ example `...(process.env.NODE_ENV === 'production' ? [] : [new PrettyDevDestination()])`, and keep
74
+ `DefaultStdoutDestination` in the list.
75
+
76
+ ### Documentation
77
+
78
+ - The error catalog listed codes that nothing in the library emits (for example
79
+ `LOGGER_INVALID_OPTIONS` and `LOGGER_OTEL_API_UNAVAILABLE`), and described them as thrown. A thrown
80
+ error carries a message, not a code, so the catalog now separates the message each thrown error
81
+ starts with from the log keys the library writes. It also gains the errors it omitted and the real
82
+ surface of a missing `@opentelemetry/api`, a `LOGGER_BOOTSTRAP_WARNING` with
83
+ `reason: 'OTEL_API_UNAVAILABLE'`.
84
+ `readme-error-catalog.spec.ts` scans every throw site in `src` and fails when a row and the code
85
+ disagree in either direction.
86
+ - The README documents the injection tokens and the exported helpers, the `useClass` and
87
+ `useExisting` forms of `forRootAsync`, the rules the request-id middleware applies to an inbound
88
+ `x-request-id` and tenant header (a value that fails them is replaced, not cleaned), and that a
89
+ Fastify adapter is not supported.
90
+ - `forRootAsync` does not register the exception filter, which `forRoot` does, and the README now
91
+ says so under the async example, in the options table and in the `http` option JSDoc. Measured with
92
+ the same failing controller on both paths: with `http.isEnabled`, `forRootAsync` emits the access
93
+ log (`HTTP_REQUEST_START`, `_CLIENT_ERROR`, `_SERVER_ERROR`) and the real error reaches its terminal
94
+ entry, but not `HTTP_EXCEPTION_HANDLED` or `HTTP_EXCEPTION_UNHANDLED`; the 500 response is
95
+ identical. Registering `{ provide: APP_FILTER, useClass: HttpExceptionFilter }` yields them. The
96
+ difference is deliberate, and a spec pins the behaviour and the remedy.
97
+ - `ILogDestination` JSDoc: `write` no longer says a failing destination "may be temporarily
98
+ skipped". Nothing skips a destination that initialized: every failed entry is dropped for it and
99
+ reported, and it keeps receiving entries. Only one whose `onInit()` failed receives none.
100
+ `minLevel` says it can only narrow what the module `level` lets through.
101
+ - The README prose and tables are corrected against the code; that correction touches no source file.
102
+ - The options table gave `level` a default of `'info'`. Outside `NODE_ENV=production` the default
103
+ is `'debug'`. It now lists the options it omitted: `isGlobal`, `serializers`, `timestamp`, the
104
+ deprecated `shouldUseAsNestLogger`, and `otel.traceIdField`, `otel.spanIdField` and
105
+ `otel.traceFlagsField`.
106
+ - `DefaultStdoutDestination` was called "always active". It is the default sink only while
107
+ `destinations` is empty, as the Destinations section already said. A destination whose
108
+ `onInit()` rejects was described as staying in the write fan-out. It is removed from the fan-out
109
+ and from shutdown.
110
+ - The architecture diagram showed `info(logKey, msg, context, metadata)`; the third parameter is
111
+ `userId`. It named a `composedMixin()` that does not exist (the function is
112
+ `createTraceContextMixin`) and put `userId` in the scope `RequestIdMiddleware` opens, which holds
113
+ `requestId` and `tenantId`.
114
+ - The tech stack badges now read pnpm 11 and tsup 9. The URL normalization lists name ULID and
115
+ nanoid segments as well as UUID and numeric ones. The `LogContextService` table lists `get()`.
116
+ The last two HTTP log keys sit inside their table.
117
+ - The Pino throughput figures are attributed to Pino's own benchmarks, the `Scope.REQUEST` cost
118
+ to NestJS's estimate, and the EPIPE guard note names its one exception, `pino-pretty`'s own
119
+ stream.
120
+ - The resource identity example passed `process.env.POD_UID` to `service.instanceId`, which does
121
+ not compile under `exactOptionalPropertyTypes` because the value can be `undefined`. It now reads
122
+ `process.env.POD_UID!`.
123
+
124
+ ### Tests
125
+
126
+ - `readme-options.spec.ts` parses the three option tables in the README and checks every default
127
+ against the defaults the module applies, and checks that the tables list exactly the options the
128
+ module resolves, so a default that drifts, or an option added without a row, fails the suite.
129
+
130
+ ## [1.4.2] - 2026-10-30
131
+
132
+ No breaking changes. Dependency and build-tooling maintenance only. No source file under `src/` changes and the
133
+ runtime JavaScript in `dist/` is byte-identical to `1.4.1`.
134
+
135
+ ### Security
136
+
137
+ - Raise the pnpm override floors for transitive devDependencies that resolved to versions
138
+ with new advisories: `body-parser` `^2.4.0` (GHSA-27r3-jxmh-p828, DoS on trailing bytes after a
139
+ compressed body), `multer` `^2.5.0` (GHSA-q7qp-rjg7-q26m, DoS from a pending async
140
+ `fileFilter`), `qs` `^6.16.1` (GHSA-6pq8-jhm2-2vcw, `qs.stringify` DoS) and `zod` `^4.6.6`
141
+ (GHSA-mrhx-c7xc-m3w5, memory exhaustion on oversized collections). Dev-only: the published
142
+ package has zero runtime dependencies.
143
+ - Ignore GHSA-gcqx-w48m-w2h4 (`deepmerge` <= 4.3.1, prototype poisoning in `mergeObject`) in
144
+ `osv-scanner.toml` until 2027-01-27. No patched release exists, and `deepmerge` is reached
145
+ only through `jest-config`, a devDependency. Remove the entry when a fixed `deepmerge` ships
146
+ or jest drops it.
147
+
148
+ ### Changed
149
+
150
+ - Build with `tsup` 9 (devDependency, was 8.5). The published `.mjs` and `.cjs` bundles are
151
+ byte-identical; the `.d.ts` and `.d.cts` files re-emit type exports as a separate
152
+ `export type { … }` statement instead of inline `type` modifiers, which declares the same
153
+ public surface. `attw` reports no problems and the bundle-size budgets hold.
154
+ - Resolve `@opentelemetry/api` to 1.10.0 in the lockfile (was 1.9.1), so the test suite runs
155
+ against the current API release. The `^1.9.0` range in `package.json`, devDependency and peer
156
+ alike, is unchanged.
157
+ - Bump `github/codeql-action/upload-sarif` to 4.39.1 in the Scorecard workflow. CI only; nothing
158
+ ships.
159
+
160
+ ### Documentation
161
+
162
+ - The runtime bundles are unchanged, and the type declarations were regenerated by `tsup` 9.
163
+ - The 1.0.1 and 1.0.8 release notes are corrected: 1.0.8 now records the id-safe charset
164
+ validation of inbound `x-request-id` and tenant ids that it already shipped.
165
+
166
+ #### Apply to a consumer
167
+
168
+ No action required. There is no new public API, no peer range changed, and the runtime JavaScript
169
+ is byte-identical to `1.4.1`; only the grouping of type exports in the declaration files differs.
170
+
14
171
  ## [1.4.1] - 2026-10-23
15
172
 
16
173
  No breaking changes.
@@ -1699,8 +1856,9 @@ identical to `1.0.8`, and nothing changed but the version number.
1699
1856
 
1700
1857
  ## [1.0.8] - 2026-08-10
1701
1858
 
1702
- Remediation of a local audit's redaction, attribution and correlation-id findings. No API
1703
- changed; the fixes are in the default redact set, the acting-user resolution and the docs.
1859
+ Remediation of a local audit's redaction, attribution and correlation-id findings. The public
1860
+ API is unchanged; the fixes are in the default redact set, the acting-user resolution, the
1861
+ correlation-id validation and the docs.
1704
1862
 
1705
1863
  ### Fixed
1706
1864
 
@@ -1712,6 +1870,14 @@ changed; the fixes are in the default redact set, the acting-user resolution and
1712
1870
  exception filter now resolve the acting user as `sub ?? id`, so a JWT principal (every
1713
1871
  `@bymax-one/nest-auth` token) is attributed to its subject rather than an ORM `id` when a
1714
1872
  principal carries both.
1873
+ - **Inbound correlation and tenant ids are confined to an id-safe charset.** The inbound
1874
+ `x-request-id` and tenant-id header values are now accepted only when they are drawn from an
1875
+ id-safe character set and fit the length bound; anything else (control bytes, whitespace,
1876
+ markup characters) is rejected. A rejected request id is replaced by a generated one (when
1877
+ `shouldGenerateRequestId` is on) and a rejected tenant id is omitted. The request id is echoed
1878
+ on the `x-request-id` response header and both ids are stored in the log context, so this keeps
1879
+ a client from planting a control byte or markup fragment in the logs and the header of every
1880
+ request it makes.
1715
1881
 
1716
1882
  ### Documentation
1717
1883
 
@@ -1956,11 +2122,11 @@ published `dist/` is identical — no runtime behaviour changes for consumers.
1956
2122
  Dev-only: the published package has zero runtime dependencies.
1957
2123
  - Force `qs` to `^6.15.3` (via `pnpm.overrides`) to clear GHSA-q8mj-m7cp-5q26
1958
2124
  (`qs.stringify` DoS). `typed-rest-client`, pulled in by Stryker, pins `qs` at
1959
- the affected `6.15.1` exactly, so no dependency refresh could resolve it
2125
+ the affected `6.15.1` exactly, so no dependency refresh could resolve it.
1960
2126
  - Pin every third-party and GitHub-owned action to a full commit SHA, with the
1961
2127
  release tag kept as a trailing comment so Dependabot can still bump them. The
1962
2128
  org's own `bymaxone/.github` reusable workflows and composite action stay on
1963
- the `@v1` moving tag by design, so shared-pipeline fixes keep propagating
2129
+ the `@v1` moving tag by design, so shared-pipeline fixes keep propagating.
1964
2130
 
1965
2131
  ### Changed
1966
2132
 
@@ -2026,7 +2192,9 @@ published `dist/` is identical — no runtime behaviour changes for consumers.
2026
2192
  - Professional CI suite: `ci.yml`, `bench.yml`, `codeql.yml`, `scorecard.yml`,
2027
2193
  `release.yml`, Dependabot, and issue templates
2028
2194
 
2029
- [Unreleased]: https://github.com/bymaxone/nest-logger/compare/v1.4.1...HEAD
2195
+ [Unreleased]: https://github.com/bymaxone/nest-logger/compare/v1.4.3...HEAD
2196
+ [1.4.3]: https://github.com/bymaxone/nest-logger/compare/v1.4.2...v1.4.3
2197
+ [1.4.2]: https://github.com/bymaxone/nest-logger/compare/v1.4.1...v1.4.2
2030
2198
  [1.4.1]: https://github.com/bymaxone/nest-logger/compare/v1.4.0...v1.4.1
2031
2199
  [1.4.0]: https://github.com/bymaxone/nest-logger/compare/v1.3.1...v1.4.0
2032
2200
  [1.3.1]: https://github.com/bymaxone/nest-logger/compare/v1.3.0...v1.3.1