Fix/redaction and core bugs#88
Merged
Merged
Conversation
added 8 commits
June 8, 2026 20:42
…top-level keys pathToRegExp joined every segment with a literal `\.`, so `**.password` compiled to `/^.*\.password$/` — which requires a dot before `password` and therefore never matched a bare top-level `password` key. The JSDoc states `**` means "zero or more segments", so a top-level key (zero leading segments) must match. This was a PII leak: a top-level `password`/`token`/etc. under autoDetect stayed raw. `**` now absorbs the adjacent separator into an optional group, so it can collapse to zero segments at either end (`**.x`, `x.**`) and in the middle (`a.**.b` matches `a.b`). Consecutive `**` are coalesced. Segment boundaries are still respected (`**.password` does not match `passwordHint`).
…s set
_hasRedact short-circuited applyRedaction to a no-op unless redact.paths or
redact.patterns was non-empty. A config of `redact: { autoDetect: 'aggressive' }`
with no explicit paths/patterns left the flag false, so redaction never ran and
all PII (passwords, emails, JWTs, …) was logged raw. autoDetect injects its
built-in PII paths/patterns at redaction time, so it must also set the flag.
SamplingConfig docs guarantee "ERROR and WARN default to 1.0 even when a lower global rate is set, unless you explicitly override them here." ALWAYS_EMIT_LEVELS listed only error and fatal, so WARN was sampled at the global rate — silently dropping warnings during incidents at low sample rates. Added warn to the set; an explicit perLevel.warn override still disables the guarantee as documented.
child(context, data) stored the merged fields in contextData, but the hot-path merge in log() is gated on _hasContextData — which was initialised to false and never set true. Every field passed to child() (e.g. serviceVersion, region) was silently dropped from all logs. A redaction test passed only because the secret contextData was never emitted at all. child() now sets the flag and also inherits the parent's bound fields so nested children carry context.
…failure
Two plugin contract bugs:
1. runOnLog had no error isolation, while every sibling hook (onInit, onError,
onShutdown) swallows errors. A plugin throwing in onLog rejected the whole
log() call — and since logger.info() is usually not awaited, that surfaced as
an unhandled rejection that can crash the process. onLog errors are now caught
and the chain continues with the previous entry; documented in the JSDoc.
2. The onError hook ("called when a transport write fails") was never invoked —
runOnError had zero call sites, so the documented alerting use case was dead.
output() now calls runOnError in the transport-failure catch, then still falls
through to the stdout/stderr fallback so the log is not lost.
… stderr Three ConsoleTransport contract bugs: - JSON mode used JSON.stringify(obj, null, 2), emitting multi-line pretty JSON that breaks line-based log collectors; the docs promise "compact JSON mode". Now single-line. - The level field was printed without sanitize() while message/context/traceId were sanitized. Custom levels are user-controlled, so an ANSI/control sequence in a level name could inject into the operator terminal (CWE-117). Level is now sanitized too. - warn was written to stdout though the class doc says stderr handles error/warn. warn now routes to stderr.
traceparent is the highest-priority default propagation header and documented as W3C/OTel, but extractTraceId returned the whole header value (00-<traceId>-<spanId>-<flags>) as the trace ID, so correlation with upstream OTel-instrumented services was broken. Now the 32-hex traceId segment is parsed out when the value is a well-formed traceparent; non-W3C values pass through unchanged for backward compatibility.
…s exist flushOnExit guarded handler registration on process.listenerCount(signal) === 0, so whenever any other SIGTERM/SIGINT listener existed (NestJS, Express, app code — the common case) logixia attached nothing and the documented flush-on-exit silently never ran, losing the last logs on deploy. Signals support multiple listeners, so logixia now registers its own handler unconditionally; the shutdownHandlerRegistered flag keeps it idempotent, and resetShutdownHandlers detaches exactly our handler. Updated the test that codified the old skip.
size-limit report 📦
|
|
🎉 This issue has been resolved in version 1.10.2. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request
📋 Description
What does this PR do?
Why is this change needed?
Related Issues
🔄 Type of Change
🧪 Testing
Test Coverage
Test Details
Manual Testing
📖 Documentation
🔍 Code Quality
📦 Dependencies
🚀 Performance
🔒 Security
📱 Compatibility
🎃 Hacktoberfest
📸 Screenshots/Examples
Before
After
Code Example
🔗 Additional Context
Deployment Notes
Rollback Plan
Future Considerations
✅ Reviewer Checklist
📝 Notes for Reviewers
🙏 Acknowledgments
Thank you for contributing to Logixia! 🚀