@nodii/telemetry 0.11.0 → 0.13.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 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";
@@ -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;AACrC,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,YAAY,EACV,oBAAoB,EACpB,IAAI,EACJ,QAAQ,EACR,WAAW,EACX,UAAU,EACV,UAAU,EACV,UAAU,GACX,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5E,YAAY,EACV,aAAa,EACb,WAAW,EACX,eAAe,EACf,UAAU,EACV,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,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;AACpB,YAAY,EACV,SAAS,EACT,UAAU,EACV,SAAS,EACT,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,YAAY,EACZ,WAAW,EACX,0BAA0B,GAC3B,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,YAAY,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAChE,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,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACrD,YAAY,EACV,SAAS,EACT,sBAAsB,EACtB,oBAAoB,EACpB,yBAAyB,EACzB,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,EACzB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,qBAAqB,EACrB,wBAAwB,EACxB,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,uBAAuB,EACvB,eAAe,EACf,4BAA4B,EAC5B,2BAA2B,GAC5B,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -8,6 +8,11 @@
8
8
  // that SET NodiiContext at the entry seam.
9
9
  // - @nodii/telemetry/outbox — Outbox emit + propagation-column adapter.
10
10
  // - @nodii/telemetry/drizzle — Drizzle audit_event schema fragments.
11
+ // - @nodii/telemetry/lambda — AWS Lambda lifecycle wrapper (C4 lock):
12
+ // cold-start init at module-load +
13
+ // force-flush-on-return so spans/metrics/
14
+ // logs survive the post-handler freeze.
15
+ // First consumer: s2s-auth-service.
11
16
  //
12
17
  // Not yet shipped (D44 § 6.5 lists them; no implementation exists yet —
13
18
  // they are tracked as follow-on requests, NOT advertised as vapor):
@@ -23,7 +28,7 @@
23
28
  // type NodiiContext } from '@nodii/telemetry';
24
29
  export { initTelemetry } from "./init.js";
25
30
  export { forceFlush, getOtlpAdapterHandle, installOtlpAdapter, shutdownOtlpAdapter, } from "./otlp-adapter.js";
26
- export { logger } from "./logger.js";
31
+ export { logger, createLogger } from "./logger.js";
27
32
  export { tracer, withSpanAttributes, getSagaTracer } from "./tracer.js";
28
33
  export { getActiveSpan } from "./active-span.js";
29
34
  export { forensicParentValue, parseTraceparent, resolveSpanParent, } from "./traceparent.js";
@@ -34,7 +39,7 @@ export { configureTelemetry } from "./configure.js";
34
39
  export { intent, IntentTypeNotRegistered } from "./intent.js";
35
40
  export { agentInvocable, readAgentRegistry, AGENT_INVOCABLE_METADATA, } from "./agent-invocable.js";
36
41
  export { getContext, requireContext, withContext, } from "./context.js";
37
- export { isPiiFieldName, redactString, redactFields, PII_FIELD_NAMES, } from "./redaction.js";
42
+ export { isPiiFieldName, redactString, redactFields, isLuhnValid, scrubPanString, PII_FIELD_NAMES, } from "./redaction.js";
38
43
  export { uuidv7, isUuidv7 } from "./uuid.js";
39
44
  export { TelemetryNotInitialized } from "./types.js";
40
45
  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;AACrC,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,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,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"}
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,0EAA0E;AAC1E,mEAAmE;AACnE,0EAA0E;AAC1E,wEAAwE;AACxE,oEAAoE;AACpE,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"}
@@ -0,0 +1,77 @@
1
+ import type { InitTelemetryConfig, MetricFamily } from "../types.js";
2
+ /**
3
+ * A minimal structural AWS Lambda handler. We intentionally do NOT depend
4
+ * on `aws-lambda` types — the wrapper is event-shape agnostic so it works
5
+ * for an APIGW-proxied Hono app (`handle(app)` from `hono/aws-lambda`), a
6
+ * raw SQS/SNS/EventBridge handler, or any other `async (event, context)`
7
+ * function. `Event` / `Result` are inferred from the wrapped handler.
8
+ */
9
+ export type LambdaHandler<Event = unknown, Result = unknown> = (event: Event, context?: unknown) => Promise<Result> | Result;
10
+ /** Config for the cold-start counter tick (C4: `s2s.cold_start_total`). */
11
+ export interface ColdStartMetricConfig {
12
+ /**
13
+ * The vocabulary-registered counter name to increment once per cold
14
+ * boot (e.g. `"s2s.cold_start_total"`). MUST be registered by the
15
+ * consumer via `initTelemetry({ vocabularyRegistry })` — the name is
16
+ * service-specific, so the wrapper cannot hardcode it.
17
+ *
18
+ * If the name is NOT registered (vocabulary miss), the increment is a
19
+ * caught no-op + a one-line warn — a metric mis-config must NOT crash
20
+ * module-load (R1 / pillar 5).
21
+ */
22
+ name: string;
23
+ /** The metric family for the counter. Defaults to `"request_handler"`. */
24
+ family?: MetricFamily;
25
+ /** Static labels stamped on the cold-start tick. */
26
+ labels?: Record<string, string | number>;
27
+ }
28
+ /**
29
+ * `initLambdaTelemetry({...})` argument shape. Extends the base
30
+ * `initTelemetry` config (serviceName + env + otlp + vocabulary, …) with
31
+ * the Lambda-specific cold-start knob.
32
+ */
33
+ export interface InitLambdaTelemetryConfig extends InitTelemetryConfig {
34
+ /**
35
+ * Counter to increment once per cold boot. Omit to skip the cold-start
36
+ * tick entirely (some services track cold starts via a log line only).
37
+ */
38
+ coldStartMetric?: ColdStartMetricConfig;
39
+ /**
40
+ * Name of the per-invocation request span opened by `wrap`. Defaults to
41
+ * `"<serviceName>.lambda.invoke"`.
42
+ */
43
+ requestSpanName?: string;
44
+ }
45
+ /** The handle returned by `initLambdaTelemetry`. */
46
+ export interface LambdaTelemetry {
47
+ /**
48
+ * Wrap a Lambda handler so every invocation:
49
+ * 1. runs inside a request span (`requestSpanName`);
50
+ * 2. force-flushes the trace + log + metric providers BEFORE the
51
+ * handler's result returns (success AND error paths), so nothing
52
+ * is lost when Lambda freezes;
53
+ * 3. is RESILIENT — a flush failure is caught + logged and never
54
+ * propagates; the handler's own result / error is what returns.
55
+ */
56
+ wrap<Event, Result>(handler: LambdaHandler<Event, Result>): (event: Event, context?: unknown) => Promise<Result>;
57
+ /**
58
+ * Force-flush the active OTLP pipelines (trace + log + metric). No-op
59
+ * when no OTLP adapter is installed (e.g. `disableOtlp` / no endpoint).
60
+ * Exposed for callers that flush at custom lifecycle points.
61
+ */
62
+ forceFlush(): Promise<void>;
63
+ }
64
+ /**
65
+ * Boot telemetry for a Lambda at MODULE LOAD (per C4). Call this once at
66
+ * the top of the handler module — not per invocation. Returns a
67
+ * `LambdaTelemetry` handle whose `wrap` adds the per-invocation request
68
+ * span + force-flush-on-return.
69
+ *
70
+ * Idempotency: `initTelemetry` is itself idempotent (a second call
71
+ * warn-no-ops), so a doubly-imported / re-required handler module does
72
+ * NOT double-configure the SDK. The cold-start tick is likewise fired
73
+ * only on the call that actually performs init (the first one) — a second
74
+ * `initLambdaTelemetry` will not re-tick, matching "once per cold boot".
75
+ */
76
+ export declare function initLambdaTelemetry(config: InitLambdaTelemetryConfig): LambdaTelemetry;
77
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lambda/index.ts"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAErE;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,OAAO,IAAI,CAC7D,KAAK,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE,OAAO,KACd,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;AAE9B,2EAA2E;AAC3E,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;;OASG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CAC1C;AAED;;;;GAIG;AACH,MAAM,WAAW,yBAA0B,SAAQ,mBAAmB;IACpE;;;OAGG;IACH,eAAe,CAAC,EAAE,qBAAqB,CAAC;IACxC;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,oDAAoD;AACpD,MAAM,WAAW,eAAe;IAC9B;;;;;;;;OAQG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,EAChB,OAAO,EAAE,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,GACpC,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACxD;;;;OAIG;IACH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAyBD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,yBAAyB,GAChC,eAAe,CAiDjB"}
@@ -0,0 +1,130 @@
1
+ // `@nodii/telemetry/lambda` — the Lambda lifecycle wrapper.
2
+ //
3
+ // Spec: C4 lock — `services/s2s-auth-service/features/telemetry-instrumentation.md`
4
+ // § "The `@nodii/telemetry/lambda` sub-package" + `nodii-libs/telemetry.md`
5
+ // § 10 (subpath exports). First consumer: s2s-auth-service (Lambda-shaped).
6
+ //
7
+ // AWS Lambda freezes the execution environment the instant a handler
8
+ // returns. The OTel batch processors buffer spans / logs / metrics and
9
+ // flush them on a timer — so on a Lambda that timer rarely fires before
10
+ // the freeze, and signals are LOST. Two lifecycle hooks fix this, both
11
+ // locked by C4:
12
+ //
13
+ // 1. Cold-start init at module-load — `initLambdaTelemetry({...})` is
14
+ // called once at the top of the handler module (NOT per-invocation).
15
+ // It boots the SDK (idempotent — a second call warn-no-ops, see
16
+ // `initTelemetry`) and ticks a cold-start counter exactly once per
17
+ // cold boot.
18
+ //
19
+ // 2. `forceFlush()` before the handler returns — `handle.wrap(fn)`
20
+ // runs the handler inside a request span and `await`s a force-flush
21
+ // of the trace + log + metric providers BEFORE returning (and on the
22
+ // error path), so nothing is lost when the environment freezes.
23
+ //
24
+ // RESILIENCE (telemetry-doctrine pillar 5 / R1 — dependency-down path):
25
+ // a force-flush FAILURE (collector down / OTLP timeout) MUST NOT break
26
+ // the Lambda. A flaky telemetry backend cannot be allowed to take down
27
+ // the function. `wrap` therefore catches + logs any flush rejection and
28
+ // STILL returns the handler's result (or re-throws the handler's own
29
+ // error). The only thing that propagates out of the wrapper is the
30
+ // handler's own outcome — never a telemetry-plumbing failure.
31
+ //
32
+ // Lives behind a subpath so non-Lambda services never pull this lifecycle
33
+ // glue into their bundle.
34
+ import { getTelemetryOrNull, initTelemetry } from "../init.js";
35
+ import { metrics } from "../metrics.js";
36
+ import { forceFlush as flushOtlpPipelines } from "../otlp-adapter.js";
37
+ import { tracer } from "../tracer.js";
38
+ /**
39
+ * Increment the cold-start counter exactly once, defensively. A
40
+ * vocabulary miss (name not registered) or any other metric error is
41
+ * caught + warn-logged — a cold-start metric mis-config must NOT crash
42
+ * the Lambda at module load (R1 / pillar 5).
43
+ */
44
+ function tickColdStart(cfg) {
45
+ try {
46
+ const counter = metrics.counter(cfg.name, {
47
+ family: cfg.family ?? "request_handler",
48
+ description: "Lambda cold-start counter (incremented once per cold boot)",
49
+ labelKeys: Object.keys(cfg.labels ?? {}),
50
+ });
51
+ counter.inc(cfg.labels ?? {});
52
+ }
53
+ catch (err) {
54
+ const cause = err instanceof Error ? err.message : String(err);
55
+ // eslint-disable-next-line no-console
56
+ console.warn(`[@nodii/telemetry/lambda] cold-start counter "${cfg.name}" could not be incremented (is it in the vocabularyRegistry?). Continuing — a metric mis-config must not crash module-load. Cause: ${cause}`);
57
+ }
58
+ }
59
+ /**
60
+ * Boot telemetry for a Lambda at MODULE LOAD (per C4). Call this once at
61
+ * the top of the handler module — not per invocation. Returns a
62
+ * `LambdaTelemetry` handle whose `wrap` adds the per-invocation request
63
+ * span + force-flush-on-return.
64
+ *
65
+ * Idempotency: `initTelemetry` is itself idempotent (a second call
66
+ * warn-no-ops), so a doubly-imported / re-required handler module does
67
+ * NOT double-configure the SDK. The cold-start tick is likewise fired
68
+ * only on the call that actually performs init (the first one) — a second
69
+ * `initLambdaTelemetry` will not re-tick, matching "once per cold boot".
70
+ */
71
+ export function initLambdaTelemetry(config) {
72
+ // Was the SDK already initialized before this call? If so, this is a
73
+ // redundant init (re-imported module / double-call) and we must NOT
74
+ // re-tick the cold-start counter — "once per cold boot".
75
+ const alreadyInitialized = getTelemetryOrNull() !== null;
76
+ // `initTelemetry` consumes only the base config keys; the extra
77
+ // Lambda-specific keys are ignored by it (excess-property tolerant at
78
+ // runtime). It is idempotent — a second call warn-no-ops.
79
+ initTelemetry(config);
80
+ if (!alreadyInitialized && config.coldStartMetric) {
81
+ tickColdStart(config.coldStartMetric);
82
+ }
83
+ const spanName = config.requestSpanName ?? `${config.serviceName}.lambda.invoke`;
84
+ // The handle is built first so `wrap` can route its flush through
85
+ // `handle.forceFlush` — that is the single flush seam (and the one a
86
+ // test spies on to fault-inject a flush failure).
87
+ const handle = {
88
+ async forceFlush() {
89
+ await flushOtlpPipelines();
90
+ },
91
+ wrap(handler) {
92
+ return async (event, context) => {
93
+ try {
94
+ // Run the handler inside a request span. `tracer.span` opens +
95
+ // closes the span and applies D27 status mapping.
96
+ const result = await tracer.span(spanName, () => Promise.resolve(handler(event, context)));
97
+ // Flush BEFORE returning — but a flush failure must NOT mask a
98
+ // successful handler result.
99
+ await safeFlush(handle);
100
+ return result;
101
+ }
102
+ catch (handlerErr) {
103
+ // The handler itself threw. Still flush (so the error span +
104
+ // partial signals aren't lost on freeze) — non-fatally — then
105
+ // re-throw the handler's OWN error (NOT a flush error).
106
+ await safeFlush(handle);
107
+ throw handlerErr;
108
+ }
109
+ };
110
+ },
111
+ };
112
+ return handle;
113
+ }
114
+ /**
115
+ * Force-flush via `handle.forceFlush` but NEVER throw. A flush failure
116
+ * (collector down / OTLP timeout) is caught + warn-logged; the Lambda
117
+ * result must not be lost to a flaky telemetry backend (pillar 5 / R1
118
+ * dependency-down path).
119
+ */
120
+ async function safeFlush(handle) {
121
+ try {
122
+ await handle.forceFlush();
123
+ }
124
+ catch (err) {
125
+ const cause = err instanceof Error ? err.message : String(err);
126
+ // eslint-disable-next-line no-console
127
+ console.warn(`[@nodii/telemetry/lambda] forceFlush() failed before return (telemetry backend down?). Swallowed — the handler result is returned regardless. Cause: ${cause}`);
128
+ }
129
+ }
130
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/lambda/index.ts"],"names":[],"mappings":"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"}
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
- /** D13/D14 logger. Envelope fields are SDK-injected; do not supply them. */
13
- export declare const logger: {
14
- readonly debug: (msg: string, fields?: Record<string, unknown>) => void;
15
- readonly info: (msg: string, fields?: Record<string, unknown>) => void;
16
- readonly warn: (msg: string, fields?: Record<string, unknown>) => void;
17
- readonly error: (msg: string, fields?: Record<string, unknown>) => void;
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
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAqBA,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;AA+DD,4EAA4E;AAC5E,eAAO,MAAM,MAAM;0BACN,MAAM,WAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;yBAGhD,MAAM,WAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;yBAG/C,MAAM,WAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;0BAG9C,MAAM,WAAW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;CAGlD,CAAC"}
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 emit(level, msg, fields) {
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
- // D15 redaction (fail-closed). Run BOTH passes before forming the
49
- // envelope; if either throws, drop the line + bump the counter.
50
- const msgResult = attemptRedactString(msg);
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 fieldsResult = fields
58
- ? attemptRedactFields(fields)
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(envelope, fieldsResult.redacted);
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
- /** D13/D14 logger. Envelope fields are SDK-injected; do not supply them. */
85
- export const logger = {
86
- debug(msg, fields) {
87
- emit("debug", msg, fields);
88
- },
89
- info(msg, fields) {
90
- emit("info", msg, fields);
91
- },
92
- warn(msg, fields) {
93
- emit("warn", msg, fields);
94
- },
95
- error(msg, fields) {
96
- emit("error", msg, fields);
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
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
@@ -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>): 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>): RedactionResult<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
@@ -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,GAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUzB;AAYD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM9C;AAED;;;;;;;;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,GAC7B,eAAe,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAS1C;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC,CAStE"}
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 redactString(v);
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 redactFields(v);
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 {
@@ -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;IAE9B,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3C,IAAI,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;YACtB,GAAG,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC;YAClB,SAAS;QACX,CAAC;QACD,GAAG,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,WAAW,CAAC,CAAU;IAC7B,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,CAAC,CAAC;IAC5C,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC;IAClD,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAChD,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,YAAY,CAAC,CAA4B,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,CAAS;IACpC,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,EAAE,EAAE,EAAE,IAAI,cAAc,EAAE,CAAC;QACpC,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAeD,MAAM,UAAU,mBAAmB,CACjC,KAA8B;IAE9B,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;IACrD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,iBAAiB;SAC5D,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,CAAS;IAC3C,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IACjD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,iBAAiB;SAC5D,CAAC;IACJ,CAAC;AACH,CAAC"}
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.11.0",
3
+ "version": "0.13.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",
@@ -22,6 +22,10 @@
22
22
  "./outbox": {
23
23
  "types": "./dist/outbox/index.d.ts",
24
24
  "default": "./dist/outbox/index.js"
25
+ },
26
+ "./lambda": {
27
+ "types": "./dist/lambda/index.d.ts",
28
+ "default": "./dist/lambda/index.js"
25
29
  }
26
30
  },
27
31
  "files": [