@nodii/telemetry 0.11.0 → 0.12.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/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +56 -7
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +78 -23
- package/dist/logger.js.map +1 -1
- package/dist/redaction.d.ts +40 -4
- package/dist/redaction.d.ts.map +1 -1
- package/dist/redaction.js +76 -12
- package/dist/redaction.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export { initTelemetry } from "./init.js";
|
|
2
2
|
export { forceFlush, getOtlpAdapterHandle, installOtlpAdapter, shutdownOtlpAdapter, } from "./otlp-adapter.js";
|
|
3
3
|
export type { OtlpAdapterHandle, OtlpAdapterConfig } from "./otlp-adapter.js";
|
|
4
|
-
export { logger } from "./logger.js";
|
|
4
|
+
export { logger, createLogger } from "./logger.js";
|
|
5
|
+
export type { NodiiLogger, LoggerOptions, LogSink, ErrSerializer, } from "./logger.js";
|
|
5
6
|
export { tracer, withSpanAttributes, getSagaTracer } from "./tracer.js";
|
|
6
7
|
export { getActiveSpan } from "./active-span.js";
|
|
7
8
|
export type { ActiveSpanRef } from "./active-span.js";
|
|
@@ -17,7 +18,8 @@ export type { ConfigureTelemetryOptions } from "./configure.js";
|
|
|
17
18
|
export { intent, IntentTypeNotRegistered } from "./intent.js";
|
|
18
19
|
export { agentInvocable, readAgentRegistry, AGENT_INVOCABLE_METADATA, } from "./agent-invocable.js";
|
|
19
20
|
export { getContext, requireContext, withContext, } from "./context.js";
|
|
20
|
-
export { isPiiFieldName, redactString, redactFields, PII_FIELD_NAMES, } from "./redaction.js";
|
|
21
|
+
export { isPiiFieldName, redactString, redactFields, isLuhnValid, scrubPanString, PII_FIELD_NAMES, } from "./redaction.js";
|
|
22
|
+
export type { RedactionConfig } from "./redaction.js";
|
|
21
23
|
export { uuidv7, isUuidv7 } from "./uuid.js";
|
|
22
24
|
export { TelemetryNotInitialized } from "./types.js";
|
|
23
25
|
export type { ActorType, AgentInvocableAuthTier, AgentInvocableConfig, AgentInvocableIdempotency, AgentInvocableMode, AgentInvocableRateLimit, AgentInvocableSideEffect, AutoInstrumentationConfig, ErrorHandlingConfig, ExportFailureReason, InitTelemetryConfig, IntentTypeDefinition, IntentTypeRegistry, LogEnvelope, LogLevel, MetricFamily, MetricVocabularyEntry, MetricVocabularyRegistry, NodiiContext, OtlpAuthConfig, OtlpTokenProvider, ResourceAttributes, SamplingConfig, } from "./types.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
// type NodiiContext } from '@nodii/telemetry';
|
|
24
24
|
export { initTelemetry } from "./init.js";
|
|
25
25
|
export { forceFlush, getOtlpAdapterHandle, installOtlpAdapter, shutdownOtlpAdapter, } from "./otlp-adapter.js";
|
|
26
|
-
export { logger } from "./logger.js";
|
|
26
|
+
export { logger, createLogger } from "./logger.js";
|
|
27
27
|
export { tracer, withSpanAttributes, getSagaTracer } from "./tracer.js";
|
|
28
28
|
export { getActiveSpan } from "./active-span.js";
|
|
29
29
|
export { forensicParentValue, parseTraceparent, resolveSpanParent, } from "./traceparent.js";
|
|
@@ -34,7 +34,7 @@ export { configureTelemetry } from "./configure.js";
|
|
|
34
34
|
export { intent, IntentTypeNotRegistered } from "./intent.js";
|
|
35
35
|
export { agentInvocable, readAgentRegistry, AGENT_INVOCABLE_METADATA, } from "./agent-invocable.js";
|
|
36
36
|
export { getContext, requireContext, withContext, } from "./context.js";
|
|
37
|
-
export { isPiiFieldName, redactString, redactFields, PII_FIELD_NAMES, } from "./redaction.js";
|
|
37
|
+
export { isPiiFieldName, redactString, redactFields, isLuhnValid, scrubPanString, PII_FIELD_NAMES, } from "./redaction.js";
|
|
38
38
|
export { uuidv7, isUuidv7 } from "./uuid.js";
|
|
39
39
|
export { TelemetryNotInitialized } from "./types.js";
|
|
40
40
|
export { DEFAULT_SAMPLING_CONFIG, METRIC_FAMILIES, AGENT_INVOCABLE_SIDE_EFFECTS, REPLICA_CONSUMER_VOCABULARY, } from "./types.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,EAAE;AACF,0EAA0E;AAC1E,EAAE;AACF,0EAA0E;AAC1E,yEAAyE;AACzE,4EAA4E;AAC5E,2EAA2E;AAC3E,4EAA4E;AAC5E,wEAAwE;AACxE,EAAE;AACF,wEAAwE;AACxE,oEAAoE;AACpE,uEAAuE;AACvE,8DAA8D;AAC9D,mDAAmD;AACnD,EAAE;AACF,oEAAoE;AACpE,gBAAgB;AAChB,EAAE;AACF,oEAAoE;AACpE,gEAAgE;AAChE,0DAA0D;AAE1D,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,EAAE;AACF,0EAA0E;AAC1E,EAAE;AACF,0EAA0E;AAC1E,yEAAyE;AACzE,4EAA4E;AAC5E,2EAA2E;AAC3E,4EAA4E;AAC5E,wEAAwE;AACxE,EAAE;AACF,wEAAwE;AACxE,oEAAoE;AACpE,uEAAuE;AACvE,8DAA8D;AAC9D,mDAAmD;AACnD,EAAE;AACF,oEAAoE;AACpE,gBAAgB;AAChB,EAAE;AACF,oEAAoE;AACpE,gEAAgE;AAChE,0DAA0D;AAE1D,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAOnD,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAWjD,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAS5E,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,wBAAwB,EACxB,gCAAgC,EAChC,yBAAyB,EACzB,cAAc,EACd,eAAe,EACf,8BAA8B,EAC9B,KAAK,EACL,iBAAiB,EACjB,cAAc,GACf,MAAM,YAAY,CAAC;AAYpB,OAAO,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAAE,MAAM,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,UAAU,EACV,cAAc,EACd,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,cAAc,EACd,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AA0BrD,OAAO,EACL,uBAAuB,EACvB,eAAe,EACf,4BAA4B,EAC5B,2BAA2B,GAC5B,MAAM,YAAY,CAAC"}
|
package/dist/logger.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type RedactionConfig } from "./redaction.js";
|
|
1
2
|
import type { LogEnvelope } from "./types.js";
|
|
2
3
|
/** A sink that consumes formed log envelopes. Default = JSON to stdio. */
|
|
3
4
|
export type LogSink = (envelope: LogEnvelope, fields: Record<string, unknown>) => void;
|
|
@@ -9,11 +10,59 @@ export type LogSink = (envelope: LogEnvelope, fields: Record<string, unknown>) =
|
|
|
9
10
|
export declare function _setLogSink(s: LogSink): void;
|
|
10
11
|
/** Test-only restore. */
|
|
11
12
|
export declare function _resetLogSinkForTests(): void;
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Serializes an Error into a plain record for structured logging. The
|
|
15
|
+
* factory accepts a custom one (`errSerializer`) so a service can match
|
|
16
|
+
* its pino-era shape; the default mirrors pino's `{ type, message,
|
|
17
|
+
* stack }`. The serialized object still flows through D15 redaction.
|
|
18
|
+
*/
|
|
19
|
+
export type ErrSerializer = (err: Error) => Record<string, unknown>;
|
|
20
|
+
/**
|
|
21
|
+
* B3 logger options (drift f2336404 / req 6e0dc381). A service builds a
|
|
22
|
+
* logger matching its needs via {@link createLogger} instead of
|
|
23
|
+
* self-rolling pino. All fields optional; omitting all of them yields
|
|
24
|
+
* the legacy 4-method singleton behaviour.
|
|
25
|
+
*/
|
|
26
|
+
export interface LoggerOptions {
|
|
27
|
+
/** Base bindings merged into every line's fields (e.g. `{ component }`). */
|
|
28
|
+
readonly bindings?: Record<string, unknown>;
|
|
29
|
+
/** Extra redaction (REDACT_PATHS + Luhn PAN scrub). */
|
|
30
|
+
readonly redaction?: RedactionConfig;
|
|
31
|
+
/** Custom destination sink. Default: JSON to stdout/stderr. */
|
|
32
|
+
readonly sink?: LogSink;
|
|
33
|
+
/** Custom Error serializer for the `err` field. */
|
|
34
|
+
readonly errSerializer?: ErrSerializer;
|
|
35
|
+
}
|
|
36
|
+
/** The D13/D14 logger surface, extended with B3 child/redact. */
|
|
37
|
+
export interface NodiiLogger {
|
|
38
|
+
debug(msg: string, fields?: Record<string, unknown>): void;
|
|
39
|
+
info(msg: string, fields?: Record<string, unknown>): void;
|
|
40
|
+
warn(msg: string, fields?: Record<string, unknown>): void;
|
|
41
|
+
error(msg: string, fields?: Record<string, unknown>): void;
|
|
42
|
+
/**
|
|
43
|
+
* Returns a child logger that carries `bindings` on every emitted
|
|
44
|
+
* line, merged under (overridden by) per-call fields. The parent is
|
|
45
|
+
* unaffected. Child bindings stack with the parent's.
|
|
46
|
+
*/
|
|
47
|
+
child(bindings: Record<string, unknown>): NodiiLogger;
|
|
48
|
+
/**
|
|
49
|
+
* Returns a logger that additionally masks `paths` (REDACT_PATHS) on
|
|
50
|
+
* top of the D2 PII list. Additive with any existing redaction config.
|
|
51
|
+
*/
|
|
52
|
+
redact(paths: readonly string[]): NodiiLogger;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* B3 factory (drift f2336404 / req 6e0dc381). Construct a logger with
|
|
56
|
+
* base bindings, a custom destination sink, a custom Error serializer,
|
|
57
|
+
* and extra redaction (REDACT_PATHS + Luhn PAN scrub) — so a service
|
|
58
|
+
* adopts the SDK logger instead of self-rolling pino, WITHOUT losing
|
|
59
|
+
* D15 PII redaction.
|
|
60
|
+
*/
|
|
61
|
+
export declare function createLogger(options?: LoggerOptions): NodiiLogger;
|
|
62
|
+
/**
|
|
63
|
+
* D13/D14 logger. Envelope fields are SDK-injected; do not supply them.
|
|
64
|
+
* This is the default instance (no bindings, default redaction + sink);
|
|
65
|
+
* `.child()` / `.redact()` derive configured loggers from it.
|
|
66
|
+
*/
|
|
67
|
+
export declare const logger: NodiiLogger;
|
|
19
68
|
//# sourceMappingURL=logger.d.ts.map
|
package/dist/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAmBA,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,WAAW,EAAY,MAAM,YAAY,CAAC;AAExD,0EAA0E;AAC1E,MAAM,MAAM,OAAO,GAAG,CACpB,QAAQ,EAAE,WAAW,EACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,IAAI,CAAC;AAIV;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,IAAI,CAE5C;AAED,yBAAyB;AACzB,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAgBD;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAMpE;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,uDAAuD;IACvD,QAAQ,CAAC,SAAS,CAAC,EAAE,eAAe,CAAC;IACrC,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,mDAAmD;IACnD,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;CACxC;AAED,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC3D,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC1D,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC1D,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC3D;;;;OAIG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,CAAC;IACtD;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW,CAAC;CAC/C;AA6GD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,aAAkB,GAAG,WAAW,CAOrE;AAED;;;;GAIG;AACH,eAAO,MAAM,MAAM,EAAE,WAA4B,CAAC"}
|
package/dist/logger.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import { getActiveSpan } from "./active-span.js";
|
|
17
17
|
import { getContext } from "./context.js";
|
|
18
18
|
import { requireTelemetry } from "./init.js";
|
|
19
|
-
import { attemptRedactFields, attemptRedactString } from "./redaction.js";
|
|
19
|
+
import { attemptRedactFields, attemptRedactString, } from "./redaction.js";
|
|
20
20
|
import { incSdkCounter } from "./sdk-counters.js";
|
|
21
21
|
let sink = defaultJsonSink;
|
|
22
22
|
/**
|
|
@@ -42,20 +42,31 @@ function defaultJsonSink(envelope, fields) {
|
|
|
42
42
|
process.stdout.write(`${line}\n`);
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
-
function
|
|
45
|
+
function defaultErrSerializer(err) {
|
|
46
|
+
return { type: err.name, message: err.message, stack: err.stack };
|
|
47
|
+
}
|
|
48
|
+
function emit(opts, level, msg, callFields) {
|
|
46
49
|
const cfg = requireTelemetry();
|
|
47
50
|
const ctx = getContext();
|
|
48
|
-
//
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
+
// Merge base bindings (child stack) under per-call fields. An `err`
|
|
52
|
+
// value that is an Error is serialized via the (possibly custom)
|
|
53
|
+
// serializer BEFORE redaction so the serialized shape is scrubbed too.
|
|
54
|
+
const merged = { ...opts.bindings, ...callFields };
|
|
55
|
+
if (merged.err instanceof Error) {
|
|
56
|
+
merged.err = opts.errSerializer(merged.err);
|
|
57
|
+
}
|
|
58
|
+
// D15 redaction (fail-closed) + B3 config. Run BOTH passes before
|
|
59
|
+
// forming the envelope; if either throws, drop the line + bump.
|
|
60
|
+
const msgResult = attemptRedactString(msg, opts.redaction);
|
|
51
61
|
if (!msgResult.ok) {
|
|
52
62
|
incSdkCounter("telemetry.sdk.redaction_failure_total", {
|
|
53
63
|
reason: msgResult.reason,
|
|
54
64
|
});
|
|
55
65
|
return;
|
|
56
66
|
}
|
|
57
|
-
const
|
|
58
|
-
|
|
67
|
+
const hasFields = Object.keys(merged).length > 0;
|
|
68
|
+
const fieldsResult = hasFields
|
|
69
|
+
? attemptRedactFields(merged, opts.redaction)
|
|
59
70
|
: { ok: true, redacted: {} };
|
|
60
71
|
if (!fieldsResult.ok) {
|
|
61
72
|
incSdkCounter("telemetry.sdk.redaction_failure_total", {
|
|
@@ -79,21 +90,65 @@ function emit(level, msg, fields) {
|
|
|
79
90
|
span_id: span?.span_id ?? null,
|
|
80
91
|
intent_id: ctx?.intent_id ?? null,
|
|
81
92
|
};
|
|
82
|
-
sink(
|
|
93
|
+
// Per-logger sink overrides the module-global sink (factory
|
|
94
|
+
// destination); otherwise fall through to the installed global sink
|
|
95
|
+
// (which the OTel adapter swaps in TS-12).
|
|
96
|
+
const target = opts.sink ?? sink;
|
|
97
|
+
target(envelope, fieldsResult.redacted);
|
|
98
|
+
}
|
|
99
|
+
function mergeRedaction(base, extraPaths) {
|
|
100
|
+
return {
|
|
101
|
+
extraPaths: [...(base?.extraPaths ?? []), ...extraPaths],
|
|
102
|
+
scrubPan: base?.scrubPan,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function makeLogger(opts) {
|
|
106
|
+
return {
|
|
107
|
+
debug(msg, fields) {
|
|
108
|
+
emit(opts, "debug", msg, fields);
|
|
109
|
+
},
|
|
110
|
+
info(msg, fields) {
|
|
111
|
+
emit(opts, "info", msg, fields);
|
|
112
|
+
},
|
|
113
|
+
warn(msg, fields) {
|
|
114
|
+
emit(opts, "warn", msg, fields);
|
|
115
|
+
},
|
|
116
|
+
error(msg, fields) {
|
|
117
|
+
emit(opts, "error", msg, fields);
|
|
118
|
+
},
|
|
119
|
+
child(bindings) {
|
|
120
|
+
return makeLogger({
|
|
121
|
+
...opts,
|
|
122
|
+
bindings: { ...opts.bindings, ...bindings },
|
|
123
|
+
});
|
|
124
|
+
},
|
|
125
|
+
redact(paths) {
|
|
126
|
+
return makeLogger({
|
|
127
|
+
...opts,
|
|
128
|
+
redaction: mergeRedaction(opts.redaction, paths),
|
|
129
|
+
});
|
|
130
|
+
},
|
|
131
|
+
};
|
|
83
132
|
}
|
|
84
|
-
/**
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
}
|
|
133
|
+
/**
|
|
134
|
+
* B3 factory (drift f2336404 / req 6e0dc381). Construct a logger with
|
|
135
|
+
* base bindings, a custom destination sink, a custom Error serializer,
|
|
136
|
+
* and extra redaction (REDACT_PATHS + Luhn PAN scrub) — so a service
|
|
137
|
+
* adopts the SDK logger instead of self-rolling pino, WITHOUT losing
|
|
138
|
+
* D15 PII redaction.
|
|
139
|
+
*/
|
|
140
|
+
export function createLogger(options = {}) {
|
|
141
|
+
return makeLogger({
|
|
142
|
+
bindings: options.bindings ? { ...options.bindings } : {},
|
|
143
|
+
redaction: options.redaction,
|
|
144
|
+
sink: options.sink,
|
|
145
|
+
errSerializer: options.errSerializer ?? defaultErrSerializer,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* D13/D14 logger. Envelope fields are SDK-injected; do not supply them.
|
|
150
|
+
* This is the default instance (no bindings, default redaction + sink);
|
|
151
|
+
* `.child()` / `.redact()` derive configured loggers from it.
|
|
152
|
+
*/
|
|
153
|
+
export const logger = createLogger();
|
|
99
154
|
//# sourceMappingURL=logger.js.map
|
package/dist/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,EAAE;AACF,OAAO;AACP,sDAAsD;AACtD,EAAE;AACF,qEAAqE;AACrE,qEAAqE;AACrE,gEAAgE;AAChE,qEAAqE;AACrE,wCAAwC;AACxC,qEAAqE;AACrE,EAAE;AACF,oEAAoE;AACpE,qEAAqE;AACrE,wCAAwC;AAExC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
|
package/dist/redaction.d.ts
CHANGED
|
@@ -13,6 +13,42 @@ export declare const PII_FIELD_NAMES: readonly string[];
|
|
|
13
13
|
* beyond `toLowerCase()`).
|
|
14
14
|
*/
|
|
15
15
|
export declare function isPiiFieldName(key: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* B3 redaction config (drift f2336404 / req 6e0dc381). Extends the
|
|
18
|
+
* canonical D15 passes with caller-supplied options so a service (e.g.
|
|
19
|
+
* billing) can adopt the SDK logger instead of self-rolling pino:
|
|
20
|
+
*
|
|
21
|
+
* - `extraPaths` — additional field names (REDACT_PATHS) masked to
|
|
22
|
+
* `[REDACTED]` on top of the D2 PII list. Case-insensitive bare-key
|
|
23
|
+
* match, same semantics as `PII_FIELD_NAMES`.
|
|
24
|
+
* - `scrubPan` — when true (default), a Luhn-VALIDATED PAN scrubber
|
|
25
|
+
* masks card-number-like digit runs in strings, but ONLY if they
|
|
26
|
+
* pass the Luhn checksum. This is stricter (and safer against
|
|
27
|
+
* over-redaction) than the loose `credit_card` regex: a 16-digit
|
|
28
|
+
* run that fails Luhn is left intact.
|
|
29
|
+
*
|
|
30
|
+
* The config is purely additive — `undefined` reproduces the legacy
|
|
31
|
+
* v0.1.0 behaviour byte-for-byte.
|
|
32
|
+
*/
|
|
33
|
+
export interface RedactionConfig {
|
|
34
|
+
/** Extra field names to mask (REDACT_PATHS), on top of the D2 list. */
|
|
35
|
+
readonly extraPaths?: readonly string[];
|
|
36
|
+
/** Luhn-validated PAN scrub on string values. Default: true. */
|
|
37
|
+
readonly scrubPan?: boolean;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Luhn checksum. Returns true iff the digit string passes the Luhn
|
|
41
|
+
* (mod-10) check used by real card PANs. Used by the PAN scrubber so a
|
|
42
|
+
* non-card digit run (an order id, a phone-less numeric token) is NOT
|
|
43
|
+
* masked — preventing the over-redaction the loose regex causes.
|
|
44
|
+
*/
|
|
45
|
+
export declare function isLuhnValid(digits: string): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Mask Luhn-valid PAN-shaped digit runs in a string. A run is masked to
|
|
48
|
+
* `[REDACTED]` ONLY when its bare digits pass `isLuhnValid`; non-Luhn
|
|
49
|
+
* runs of the same length are left untouched (no over-redaction).
|
|
50
|
+
*/
|
|
51
|
+
export declare function scrubPanString(s: string): string;
|
|
16
52
|
/**
|
|
17
53
|
* Redacts an arbitrary record by replacing values whose keys match the
|
|
18
54
|
* D2 PII list with `[REDACTED]`. Nested records are walked recursively.
|
|
@@ -23,13 +59,13 @@ export declare function isPiiFieldName(key: string): boolean;
|
|
|
23
59
|
* object (e.g. circular reference encountered via JSON.stringify
|
|
24
60
|
* elsewhere) the caller wraps this in `attemptRedaction()` to catch.
|
|
25
61
|
*/
|
|
26
|
-
export declare function redactFields(input: Record<string, unknown
|
|
62
|
+
export declare function redactFields(input: Record<string, unknown>, cfg?: RedactionConfig): Record<string, unknown>;
|
|
27
63
|
/**
|
|
28
64
|
* Apply the D15 regex pass to a string. Returns the redacted string.
|
|
29
65
|
* Each pattern that fires replaces its match with [REDACTED]; multiple
|
|
30
66
|
* matches per string are all replaced.
|
|
31
67
|
*/
|
|
32
|
-
export declare function redactString(s: string): string;
|
|
68
|
+
export declare function redactString(s: string, cfg?: RedactionConfig): string;
|
|
33
69
|
/**
|
|
34
70
|
* Fail-closed wrapper. Returns:
|
|
35
71
|
* - `{ ok: true, redacted }` when redaction succeeded.
|
|
@@ -46,6 +82,6 @@ export type RedactionResult<T> = {
|
|
|
46
82
|
ok: false;
|
|
47
83
|
reason: string;
|
|
48
84
|
};
|
|
49
|
-
export declare function attemptRedactFields(input: Record<string, unknown
|
|
50
|
-
export declare function attemptRedactString(s: string): RedactionResult<string>;
|
|
85
|
+
export declare function attemptRedactFields(input: Record<string, unknown>, cfg?: RedactionConfig): RedactionResult<Record<string, unknown>>;
|
|
86
|
+
export declare function attemptRedactString(s: string, cfg?: RedactionConfig): RedactionResult<string>;
|
|
51
87
|
//# sourceMappingURL=redaction.d.ts.map
|
package/dist/redaction.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redaction.d.ts","sourceRoot":"","sources":["../src/redaction.ts"],"names":[],"mappings":"AAaA;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAyCnC,CAAC;AAwCX;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"redaction.d.ts","sourceRoot":"","sources":["../src/redaction.ts"],"names":[],"mappings":"AAaA;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAyCnC,CAAC;AAwCX;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAuBD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAgBnD;AAOD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAKhD;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,GAAG,CAAC,EAAE,eAAe,GACpB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGzB;AA2BD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,eAAe,GAAG,MAAM,CAErE;AAiBD;;;;;;;;GAQG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,CAAC,CAAA;CAAE,GACzB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,GAAG,CAAC,EAAE,eAAe,GACpB,eAAe,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAS1C;AAED,wBAAgB,mBAAmB,CACjC,CAAC,EAAE,MAAM,EACT,GAAG,CAAC,EAAE,eAAe,GACpB,eAAe,CAAC,MAAM,CAAC,CASzB"}
|
package/dist/redaction.js
CHANGED
|
@@ -103,6 +103,56 @@ const REGEX_PATTERNS = [
|
|
|
103
103
|
export function isPiiFieldName(key) {
|
|
104
104
|
return PII_FIELD_SET.has(key.toLowerCase());
|
|
105
105
|
}
|
|
106
|
+
function resolveConfig(cfg) {
|
|
107
|
+
const extraSet = new Set();
|
|
108
|
+
if (cfg?.extraPaths) {
|
|
109
|
+
for (const p of cfg.extraPaths)
|
|
110
|
+
extraSet.add(p.toLowerCase());
|
|
111
|
+
}
|
|
112
|
+
// PAN scrub defaults ON. It only ever masks Luhn-valid runs, so it is
|
|
113
|
+
// safe to enable by default for the configurable layer.
|
|
114
|
+
const scrubPan = cfg?.scrubPan ?? true;
|
|
115
|
+
return { extraSet, scrubPan };
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Luhn checksum. Returns true iff the digit string passes the Luhn
|
|
119
|
+
* (mod-10) check used by real card PANs. Used by the PAN scrubber so a
|
|
120
|
+
* non-card digit run (an order id, a phone-less numeric token) is NOT
|
|
121
|
+
* masked — preventing the over-redaction the loose regex causes.
|
|
122
|
+
*/
|
|
123
|
+
export function isLuhnValid(digits) {
|
|
124
|
+
if (!/^\d+$/.test(digits) || digits.length < 12 || digits.length > 19) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
let sum = 0;
|
|
128
|
+
let double = false;
|
|
129
|
+
for (let i = digits.length - 1; i >= 0; i--) {
|
|
130
|
+
let d = digits.charCodeAt(i) - 48;
|
|
131
|
+
if (double) {
|
|
132
|
+
d *= 2;
|
|
133
|
+
if (d > 9)
|
|
134
|
+
d -= 9;
|
|
135
|
+
}
|
|
136
|
+
sum += d;
|
|
137
|
+
double = !double;
|
|
138
|
+
}
|
|
139
|
+
return sum % 10 === 0;
|
|
140
|
+
}
|
|
141
|
+
// PAN candidate: 12–19 digits, optionally grouped by single spaces or
|
|
142
|
+
// dashes (the common `4111 1111 1111 1111` / `4111-1111-...` shapes).
|
|
143
|
+
// We extract the bare digits, Luhn-check them, and only mask on a pass.
|
|
144
|
+
const PAN_CANDIDATE_RE = /\b\d(?:[ -]?\d){11,18}\b/g;
|
|
145
|
+
/**
|
|
146
|
+
* Mask Luhn-valid PAN-shaped digit runs in a string. A run is masked to
|
|
147
|
+
* `[REDACTED]` ONLY when its bare digits pass `isLuhnValid`; non-Luhn
|
|
148
|
+
* runs of the same length are left untouched (no over-redaction).
|
|
149
|
+
*/
|
|
150
|
+
export function scrubPanString(s) {
|
|
151
|
+
return s.replace(PAN_CANDIDATE_RE, (match) => {
|
|
152
|
+
const bare = match.replace(/[ -]/g, "");
|
|
153
|
+
return isLuhnValid(bare) ? REDACTED : match;
|
|
154
|
+
});
|
|
155
|
+
}
|
|
106
156
|
/**
|
|
107
157
|
* Redacts an arbitrary record by replacing values whose keys match the
|
|
108
158
|
* D2 PII list with `[REDACTED]`. Nested records are walked recursively.
|
|
@@ -113,26 +163,30 @@ export function isPiiFieldName(key) {
|
|
|
113
163
|
* object (e.g. circular reference encountered via JSON.stringify
|
|
114
164
|
* elsewhere) the caller wraps this in `attemptRedaction()` to catch.
|
|
115
165
|
*/
|
|
116
|
-
export function redactFields(input) {
|
|
166
|
+
export function redactFields(input, cfg) {
|
|
167
|
+
const resolved = resolveConfig(cfg);
|
|
168
|
+
return redactFieldsResolved(input, resolved);
|
|
169
|
+
}
|
|
170
|
+
function redactFieldsResolved(input, resolved) {
|
|
117
171
|
const out = {};
|
|
118
172
|
for (const [k, v] of Object.entries(input)) {
|
|
119
|
-
if (isPiiFieldName(k)) {
|
|
173
|
+
if (isPiiFieldName(k) || resolved.extraSet.has(k.toLowerCase())) {
|
|
120
174
|
out[k] = REDACTED;
|
|
121
175
|
continue;
|
|
122
176
|
}
|
|
123
|
-
out[k] = redactValue(v);
|
|
177
|
+
out[k] = redactValue(v, resolved);
|
|
124
178
|
}
|
|
125
179
|
return out;
|
|
126
180
|
}
|
|
127
|
-
function redactValue(v) {
|
|
181
|
+
function redactValue(v, resolved) {
|
|
128
182
|
if (v === null || v === undefined)
|
|
129
183
|
return v;
|
|
130
184
|
if (typeof v === "string")
|
|
131
|
-
return
|
|
185
|
+
return redactStringResolved(v, resolved);
|
|
132
186
|
if (Array.isArray(v))
|
|
133
|
-
return v.map(redactValue);
|
|
187
|
+
return v.map((e) => redactValue(e, resolved));
|
|
134
188
|
if (typeof v === "object") {
|
|
135
|
-
return
|
|
189
|
+
return redactFieldsResolved(v, resolved);
|
|
136
190
|
}
|
|
137
191
|
return v;
|
|
138
192
|
}
|
|
@@ -141,16 +195,26 @@ function redactValue(v) {
|
|
|
141
195
|
* Each pattern that fires replaces its match with [REDACTED]; multiple
|
|
142
196
|
* matches per string are all replaced.
|
|
143
197
|
*/
|
|
144
|
-
export function redactString(s) {
|
|
198
|
+
export function redactString(s, cfg) {
|
|
199
|
+
return redactStringResolved(s, resolveConfig(cfg));
|
|
200
|
+
}
|
|
201
|
+
function redactStringResolved(s, resolved) {
|
|
145
202
|
let out = s;
|
|
203
|
+
// PAN-Luhn scrub runs FIRST: it's stricter than the loose credit_card
|
|
204
|
+
// regex (Luhn-validated), so masking valid PANs here leaves the regex
|
|
205
|
+
// pass to catch the remaining looser shapes without double work on the
|
|
206
|
+
// already-masked bytes.
|
|
207
|
+
if (resolved.scrubPan) {
|
|
208
|
+
out = scrubPanString(out);
|
|
209
|
+
}
|
|
146
210
|
for (const { re } of REGEX_PATTERNS) {
|
|
147
211
|
out = out.replace(re, REDACTED);
|
|
148
212
|
}
|
|
149
213
|
return out;
|
|
150
214
|
}
|
|
151
|
-
export function attemptRedactFields(input) {
|
|
215
|
+
export function attemptRedactFields(input, cfg) {
|
|
152
216
|
try {
|
|
153
|
-
return { ok: true, redacted: redactFields(input) };
|
|
217
|
+
return { ok: true, redacted: redactFields(input, cfg) };
|
|
154
218
|
}
|
|
155
219
|
catch (err) {
|
|
156
220
|
return {
|
|
@@ -159,9 +223,9 @@ export function attemptRedactFields(input) {
|
|
|
159
223
|
};
|
|
160
224
|
}
|
|
161
225
|
}
|
|
162
|
-
export function attemptRedactString(s) {
|
|
226
|
+
export function attemptRedactString(s, cfg) {
|
|
163
227
|
try {
|
|
164
|
-
return { ok: true, redacted: redactString(s) };
|
|
228
|
+
return { ok: true, redacted: redactString(s, cfg) };
|
|
165
229
|
}
|
|
166
230
|
catch (err) {
|
|
167
231
|
return {
|
package/dist/redaction.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redaction.js","sourceRoot":"","sources":["../src/redaction.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,uDAAuD;AACvD,yCAAyC;AACzC,EAAE;AACF,2DAA2D;AAC3D,yEAAyE;AACzE,wEAAwE;AACxE,sEAAsE;AACtE,kEAAkE;AAClE,8BAA8B;AAE9B,MAAM,QAAQ,GAAG,YAAY,CAAC;AAE9B;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAsB;IAChD,UAAU;IACV,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,cAAc;IACd,eAAe;IACf,UAAU;IACV,SAAS;IACT,QAAQ;IACR,aAAa;IACb,eAAe;IACf,YAAY;IACZ,QAAQ;IACR,eAAe;IACf,KAAK;IACL,QAAQ;IACR,KAAK;IACL,SAAS;IACT,aAAa;IACb,aAAa;IACb,KAAK;IACL,MAAM;IACN,gBAAgB;IAChB,gBAAgB;IAChB,OAAO;IACP,cAAc;IACd,QAAQ;IACR,OAAO;IACP,eAAe;IACf,SAAS;IACT,QAAQ;IACR,aAAa;IACb,KAAK;IACL,KAAK;IACL,eAAe;IACf,YAAY;IACZ,WAAW;IACX,WAAW;IACX,UAAU;IACV,iBAAiB;CACT,CAAC;AAEX,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;AAE3E;;;;;;;GAOG;AACH,MAAM,cAAc,GAA4C;IAC9D,uEAAuE;IACvE;QACE,IAAI,EAAE,KAAK;QACX,EAAE,EAAE,wDAAwD;KAC7D;IACD,wEAAwE;IACxE;QACE,IAAI,EAAE,aAAa;QACnB,EAAE,EAAE,yBAAyB;KAC9B;IACD,mBAAmB;IACnB;QACE,IAAI,EAAE,OAAO;QACb,EAAE,EAAE,mDAAmD;KACxD;IACD,yBAAyB;IACzB;QACE,IAAI,EAAE,KAAK;QACX,EAAE,EAAE,wBAAwB;KAC7B;IACD,6EAA6E;IAC7E;QACE,IAAI,EAAE,YAAY;QAClB,EAAE,EAAE,yBAAyB;KAC9B;CACO,CAAC;AAEX;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,OAAO,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAC1B,KAA8B;
|
|
1
|
+
{"version":3,"file":"redaction.js","sourceRoot":"","sources":["../src/redaction.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nodii/telemetry",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Substrate observability library for the Nodii microservice stack — OTel wrapper, log envelope, intent lifecycle, audit signal, agent registry, context propagation. Spec: planning hub docKey=telemetry.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|