Bundles the prior autonomous-session output that was sitting unstaged: - Em-dash sweep across src/ + tests/ (en-dash/em-dash to hyphen, ~2280 instances) - country-flag-icons rollout (CountryFlag component, replaces emoji glyphs that never rendered on Windows; lazy-loads the 3x2 SVG index as a single chunk after the per-subpath dynamic-import approach silently failed in webpack) - Admin IA Phase 1+2: 7-domain regroup, 41 to 38 pages, /admin/berths index, redirects (ocr to ai, reports to dashboard, invitations to users), docs/admin-ia-proposal.md - Per-template email tester (registry + endpoint + UI on Email admin page) - Cancel-document mode picker (delete-from-Documenso vs keep-for-audit) - Dashboard PDF report: 25 widgets, SVG charts, date-range picker, 11 resolvers - Customize-widgets per-region sortables at xl+ (charts/rails/feed); single flat sortable below xl when the layout stacks; per-viewport saved orders - Audit doc updates capturing each shipped item - Lint fixes: react-compiler immutability in DonutChart (reduce instead of let-reassign), set-state-in-effect disables in CountryFlag and UploadForSigning preview-bytes effect, unused 'confirm' destructures in interest contract + reservation tabs, unescaped apostrophe in test-template card copy
75 lines
2.3 KiB
TypeScript
75 lines
2.3 KiB
TypeScript
import pino from 'pino';
|
|
|
|
import { getRequestContext } from '@/lib/request-context';
|
|
|
|
export const logger = pino({
|
|
level: process.env.LOG_LEVEL ?? 'info',
|
|
/**
|
|
* Mix the active request context (request id, port id, user id) into
|
|
* EVERY log line emitted within an API request - this is what makes
|
|
* the super-admin error inspector usable: paste a request id into the
|
|
* search and every log line that fired during that request comes back
|
|
* keyed to it. Outside a request (queue jobs, scheduled tasks) the
|
|
* mixin returns an empty object so the log line is unchanged.
|
|
*/
|
|
mixin() {
|
|
const ctx = getRequestContext();
|
|
if (!ctx) return {};
|
|
return {
|
|
requestId: ctx.requestId,
|
|
portId: ctx.portId || undefined,
|
|
userId: ctx.userId || undefined,
|
|
};
|
|
},
|
|
redact: {
|
|
paths: [
|
|
'password',
|
|
'token',
|
|
'secret',
|
|
'accessKey',
|
|
'secretKey',
|
|
'creditCard',
|
|
'*.password',
|
|
'*.token',
|
|
'*.secret',
|
|
'*.accessKey',
|
|
'*.secretKey',
|
|
// Encrypted credential blobs surface in storage / smtp config logs
|
|
// unintentionally; redact them defensively even though they're
|
|
// already AES-encrypted at rest.
|
|
'*.secretKeyEncrypted',
|
|
'*.smtpPassEncrypted',
|
|
'*.imapPassEncrypted',
|
|
'*.proxyHmacSecretEncrypted',
|
|
// HTTP authorization headers (Bearer tokens, Basic creds) leak via
|
|
// err.config.headers on http-client error logs.
|
|
'*.headers.authorization',
|
|
'*.headers.Authorization',
|
|
'*.headers["x-documenso-secret"]',
|
|
'*.config.headers.Authorization',
|
|
'*.config.headers.authorization',
|
|
// Cookie headers can carry session tokens.
|
|
'*.headers.cookie',
|
|
'*.headers.Cookie',
|
|
// Two-level nesting for things like `req.headers.authorization` or
|
|
// `cfg.s3.secretKeyEncrypted`.
|
|
'*.*.password',
|
|
'*.*.token',
|
|
'*.*.secret',
|
|
'*.*.secretKeyEncrypted',
|
|
'*.*.headers.authorization',
|
|
'*.*.headers.Authorization',
|
|
],
|
|
censor: '[REDACTED]',
|
|
},
|
|
transport:
|
|
process.env.NODE_ENV !== 'production'
|
|
? { target: 'pino-pretty', options: { colorize: true } }
|
|
: undefined,
|
|
serializers: {
|
|
err: pino.stdSerializers.err,
|
|
req: pino.stdSerializers.req,
|
|
res: pino.stdSerializers.res,
|
|
},
|
|
});
|