@ttt-productions/monitoring-core 0.13.3 → 0.13.5
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/capture-context.d.ts +19 -6
- package/dist/capture-context.d.ts.map +1 -1
- package/dist/capture-context.js +28 -6
- package/dist/capture-context.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/scrubber.d.ts +2 -1
- package/dist/scrubber.d.ts.map +1 -1
- package/dist/scrubber.js +31 -1
- package/dist/scrubber.js.map +1 -1
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,21 +2,34 @@
|
|
|
2
2
|
* Capture-context application — the one place that decides how a capture's
|
|
3
3
|
* context argument lands on a Sentry scope.
|
|
4
4
|
*
|
|
5
|
-
* Context keys become EXTRAS, with
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* Context keys become EXTRAS, with two exceptions — the keys call sites pass
|
|
6
|
+
* meaning a FIRST-CLASS Sentry field rather than a free-form attachment:
|
|
7
|
+
*
|
|
8
|
+
* - `tags`, a flat string map, is applied as REAL Sentry tags
|
|
9
|
+
* (`scope.setTag`), so those values are searchable, filterable, and
|
|
10
|
+
* alert-routable;
|
|
11
|
+
* - `level`, one of the severity names, is applied as the capture's REAL
|
|
12
|
+
* severity (`scope.setLevel`), so a call site asking for `warning` is not
|
|
13
|
+
* reported as an error.
|
|
14
|
+
*
|
|
15
|
+
* Both are all-or-nothing: a value that does not fit the shape (a `tags` map
|
|
16
|
+
* with a non-string value, an unrecognized `level`) stays an ordinary extra, so
|
|
17
|
+
* nothing is ever dropped. A scope that cannot honour the field (no `setLevel`)
|
|
18
|
+
* also falls back to the extra.
|
|
10
19
|
*/
|
|
20
|
+
import type { MonitoringLevel } from "./types.js";
|
|
11
21
|
/**
|
|
12
22
|
* Narrow an arbitrary value to a flat `Record<string, string>`, or `null` when
|
|
13
23
|
* it is not one. An empty object qualifies (it carries no tags and no
|
|
14
24
|
* information, so it yields neither a tag nor an extra).
|
|
15
25
|
*/
|
|
16
26
|
export declare function asFlatStringTagMap(value: unknown): Record<string, string> | null;
|
|
27
|
+
/** Narrow a value to a monitoring severity name, or `null` when it is not one. */
|
|
28
|
+
export declare function asMonitoringLevel(value: unknown): MonitoringLevel | null;
|
|
17
29
|
/**
|
|
18
30
|
* Apply a capture context to a scope: real tags for a flat-string-map `tags`
|
|
19
|
-
* entry,
|
|
31
|
+
* entry, the real severity for a recognized `level`, extras for everything else.
|
|
32
|
+
* Tolerates a scope missing any of the methods.
|
|
20
33
|
*/
|
|
21
34
|
export declare function applyCaptureContext(scope: unknown, context: Record<string, unknown>): void;
|
|
22
35
|
//# sourceMappingURL=capture-context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capture-context.d.ts","sourceRoot":"","sources":["../src/capture-context.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"capture-context.d.ts","sourceRoot":"","sources":["../src/capture-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAa,MAAM,YAAY,CAAC;AAE7D;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAShF;AAID,kFAAkF;AAClF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CAExE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CA0B1F"}
|
package/dist/capture-context.js
CHANGED
|
@@ -2,11 +2,20 @@
|
|
|
2
2
|
* Capture-context application — the one place that decides how a capture's
|
|
3
3
|
* context argument lands on a Sentry scope.
|
|
4
4
|
*
|
|
5
|
-
* Context keys become EXTRAS, with
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* Context keys become EXTRAS, with two exceptions — the keys call sites pass
|
|
6
|
+
* meaning a FIRST-CLASS Sentry field rather than a free-form attachment:
|
|
7
|
+
*
|
|
8
|
+
* - `tags`, a flat string map, is applied as REAL Sentry tags
|
|
9
|
+
* (`scope.setTag`), so those values are searchable, filterable, and
|
|
10
|
+
* alert-routable;
|
|
11
|
+
* - `level`, one of the severity names, is applied as the capture's REAL
|
|
12
|
+
* severity (`scope.setLevel`), so a call site asking for `warning` is not
|
|
13
|
+
* reported as an error.
|
|
14
|
+
*
|
|
15
|
+
* Both are all-or-nothing: a value that does not fit the shape (a `tags` map
|
|
16
|
+
* with a non-string value, an unrecognized `level`) stays an ordinary extra, so
|
|
17
|
+
* nothing is ever dropped. A scope that cannot honour the field (no `setLevel`)
|
|
18
|
+
* also falls back to the extra.
|
|
10
19
|
*/
|
|
11
20
|
/**
|
|
12
21
|
* Narrow an arbitrary value to a flat `Record<string, string>`, or `null` when
|
|
@@ -24,9 +33,15 @@ export function asFlatStringTagMap(value) {
|
|
|
24
33
|
}
|
|
25
34
|
return out;
|
|
26
35
|
}
|
|
36
|
+
const MONITORING_LEVELS = ["fatal", "error", "warning", "info", "debug"];
|
|
37
|
+
/** Narrow a value to a monitoring severity name, or `null` when it is not one. */
|
|
38
|
+
export function asMonitoringLevel(value) {
|
|
39
|
+
return typeof value === "string" && MONITORING_LEVELS.includes(value) ? value : null;
|
|
40
|
+
}
|
|
27
41
|
/**
|
|
28
42
|
* Apply a capture context to a scope: real tags for a flat-string-map `tags`
|
|
29
|
-
* entry,
|
|
43
|
+
* entry, the real severity for a recognized `level`, extras for everything else.
|
|
44
|
+
* Tolerates a scope missing any of the methods.
|
|
30
45
|
*/
|
|
31
46
|
export function applyCaptureContext(scope, context) {
|
|
32
47
|
const target = scope;
|
|
@@ -42,6 +57,13 @@ export function applyCaptureContext(scope, context) {
|
|
|
42
57
|
continue;
|
|
43
58
|
}
|
|
44
59
|
}
|
|
60
|
+
if (key === "level") {
|
|
61
|
+
const level = asMonitoringLevel(value);
|
|
62
|
+
if (level && typeof target?.setLevel === "function") {
|
|
63
|
+
target.setLevel(level);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
45
67
|
if (typeof target?.setExtra === "function")
|
|
46
68
|
target.setExtra(key, value);
|
|
47
69
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capture-context.js","sourceRoot":"","sources":["../src/capture-context.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"capture-context.js","sourceRoot":"","sources":["../src/capture-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAErF,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;QAC5E,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC3C,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACnB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,iBAAiB,GAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAE5F,kFAAkF;AAClF,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,iBAAiB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,KAAyB,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5G,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAc,EAAE,OAAgC;IAClF,MAAM,MAAM,GAAG,KAA8C,CAAC;IAE9D,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;YACnB,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;YACzC,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,OAAO,MAAM,EAAE,MAAM,KAAK,UAAU,EAAE,CAAC;oBACzC,KAAK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;wBACxD,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;oBAClC,CAAC;gBACH,CAAC;gBACD,SAAS;YACX,CAAC;QACH,CAAC;QAED,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YACpB,MAAM,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;YACvC,IAAI,KAAK,IAAI,OAAO,MAAM,EAAE,QAAQ,KAAK,UAAU,EAAE,CAAC;gBACpD,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBACvB,SAAS;YACX,CAAC;QACH,CAAC;QAED,IAAI,OAAO,MAAM,EAAE,QAAQ,KAAK,UAAU;YAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC","sourcesContent":["/**\n * Capture-context application — the one place that decides how a capture's\n * context argument lands on a Sentry scope.\n *\n * Context keys become EXTRAS, with two exceptions — the keys call sites pass\n * meaning a FIRST-CLASS Sentry field rather than a free-form attachment:\n *\n * - `tags`, a flat string map, is applied as REAL Sentry tags\n * (`scope.setTag`), so those values are searchable, filterable, and\n * alert-routable;\n * - `level`, one of the severity names, is applied as the capture's REAL\n * severity (`scope.setLevel`), so a call site asking for `warning` is not\n * reported as an error.\n *\n * Both are all-or-nothing: a value that does not fit the shape (a `tags` map\n * with a non-string value, an unrecognized `level`) stays an ordinary extra, so\n * nothing is ever dropped. A scope that cannot honour the field (no `setLevel`)\n * also falls back to the extra.\n */\n\nimport type { MonitoringLevel, ScopeLike } from \"./types.js\";\n\n/**\n * Narrow an arbitrary value to a flat `Record<string, string>`, or `null` when\n * it is not one. An empty object qualifies (it carries no tags and no\n * information, so it yields neither a tag nor an extra).\n */\nexport function asFlatStringTagMap(value: unknown): Record<string, string> | null {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) return null;\n\n const out: Record<string, string> = {};\n for (const [key, entry] of Object.entries(value as Record<string, unknown>)) {\n if (typeof entry !== \"string\") return null;\n out[key] = entry;\n }\n return out;\n}\n\nconst MONITORING_LEVELS: readonly string[] = [\"fatal\", \"error\", \"warning\", \"info\", \"debug\"];\n\n/** Narrow a value to a monitoring severity name, or `null` when it is not one. */\nexport function asMonitoringLevel(value: unknown): MonitoringLevel | null {\n return typeof value === \"string\" && MONITORING_LEVELS.includes(value) ? (value as MonitoringLevel) : null;\n}\n\n/**\n * Apply a capture context to a scope: real tags for a flat-string-map `tags`\n * entry, the real severity for a recognized `level`, extras for everything else.\n * Tolerates a scope missing any of the methods.\n */\nexport function applyCaptureContext(scope: unknown, context: Record<string, unknown>): void {\n const target = scope as Partial<ScopeLike> | null | undefined;\n\n for (const [key, value] of Object.entries(context)) {\n if (key === \"tags\") {\n const tagMap = asFlatStringTagMap(value);\n if (tagMap) {\n if (typeof target?.setTag === \"function\") {\n for (const [tagKey, tagValue] of Object.entries(tagMap)) {\n target.setTag(tagKey, tagValue);\n }\n }\n continue;\n }\n }\n\n if (key === \"level\") {\n const level = asMonitoringLevel(value);\n if (level && typeof target?.setLevel === \"function\") {\n target.setLevel(level);\n continue;\n }\n }\n\n if (typeof target?.setExtra === \"function\") target.setExtra(key, value);\n }\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { MonitoringInitOptions, MonitoringUser, MonitoringProvider, ScopeLike } from "./types.js";
|
|
1
|
+
export type { MonitoringInitOptions, MonitoringUser, MonitoringProvider, MonitoringLevel, ScopeLike } from "./types.js";
|
|
2
2
|
export type { MonitoringAdapter } from "./adapter.js";
|
|
3
3
|
export { initMonitoring, getMonitoringAdapter, setMonitoringAdapter, resetMonitoringAdapter } from "./init.js";
|
|
4
4
|
export { captureException, captureMessage, setUser, setTag, withScope, addBreadcrumb } from "./api.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,qBAAqB,EAAE,cAAc,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,qBAAqB,EAAE,cAAc,EAAE,kBAAkB,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACxH,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAC/G,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEvG,YAAY,EACV,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,wBAAwB,EACxB,cAAc,GACf,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,YAAY,EACZ,WAAW,EACX,uBAAuB,GACxB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,mBAAmB,EACnB,SAAS,EACT,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAC/G,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AASvG,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,YAAY,EACZ,WAAW,EACX,uBAAuB,GACxB,MAAM,eAAe,CAAC;AAOvB,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC","sourcesContent":["export type { MonitoringInitOptions, MonitoringUser, MonitoringProvider, ScopeLike } from \"./types.js\";\nexport type { MonitoringAdapter } from \"./adapter.js\";\n\nexport { initMonitoring, getMonitoringAdapter, setMonitoringAdapter, resetMonitoringAdapter } from \"./init.js\";\nexport { captureException, captureMessage, setUser, setTag, withScope, addBreadcrumb } from \"./api.js\";\n\nexport type {\n ForbiddenPattern,\n RedactStringOptions,\n ScrubbableEvent,\n TelemetryScrubberOptions,\n BeforeSendHook,\n} from \"./scrubber.js\";\nexport {\n REDACTION_PLACEHOLDER,\n DEFAULT_FORBIDDEN_PATTERNS,\n redactString,\n redactEvent,\n createTelemetryScrubber,\n} from \"./scrubber.js\";\n\nexport type {\n DefaultSafeEventKey,\n SafeEvent,\n BuildSafeEventOptions,\n} from \"./safe-event.js\";\nexport { DEFAULT_SAFE_EVENT_KEYS, buildSafeEvent } from \"./safe-event.js\";"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAC/G,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AASvG,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,YAAY,EACZ,WAAW,EACX,uBAAuB,GACxB,MAAM,eAAe,CAAC;AAOvB,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC","sourcesContent":["export type { MonitoringInitOptions, MonitoringUser, MonitoringProvider, MonitoringLevel, ScopeLike } from \"./types.js\";\nexport type { MonitoringAdapter } from \"./adapter.js\";\n\nexport { initMonitoring, getMonitoringAdapter, setMonitoringAdapter, resetMonitoringAdapter } from \"./init.js\";\nexport { captureException, captureMessage, setUser, setTag, withScope, addBreadcrumb } from \"./api.js\";\n\nexport type {\n ForbiddenPattern,\n RedactStringOptions,\n ScrubbableEvent,\n TelemetryScrubberOptions,\n BeforeSendHook,\n} from \"./scrubber.js\";\nexport {\n REDACTION_PLACEHOLDER,\n DEFAULT_FORBIDDEN_PATTERNS,\n redactString,\n redactEvent,\n createTelemetryScrubber,\n} from \"./scrubber.js\";\n\nexport type {\n DefaultSafeEventKey,\n SafeEvent,\n BuildSafeEventOptions,\n} from \"./safe-event.js\";\nexport { DEFAULT_SAFE_EVENT_KEYS, buildSafeEvent } from \"./safe-event.js\";"]}
|
package/dist/scrubber.d.ts
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
*
|
|
9
9
|
* This package is GENERIC — it ships only obvious, domain-neutral defaults
|
|
10
10
|
* (full IPv4/IPv6 addresses, bearer/authorization tokens, generic credential
|
|
11
|
-
* assignments
|
|
11
|
+
* assignments, URL-borne credential parameters such as `oobCode` / `id_token`).
|
|
12
|
+
* Product-specific patterns (evidence-bucket URL prefixes,
|
|
12
13
|
* detector-hash shapes, NCMEC credential markers) are INJECTED by the consuming
|
|
13
14
|
* app via {@link createTelemetryScrubber}'s `patterns` option. No app-data-package
|
|
14
15
|
* import, no app-specific literals.
|
package/dist/scrubber.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scrubber.d.ts","sourceRoot":"","sources":["../src/scrubber.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"scrubber.d.ts","sourceRoot":"","sources":["../src/scrubber.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,0EAA0E;AAC1E,eAAO,MAAM,qBAAqB,eAAe,CAAC;AAElD;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,CAAC;AAE/C,MAAM,MAAM,mBAAmB,GAAG;IAChC,yEAAyE;IACzE,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC9B,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,EAAE,MAAM,EAyC9C,CAAC;AAwBF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,MAAM,CASrF;AAwCD;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC;IAClE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC9B,oEAAoE;IACpE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,eAAe,EACnD,KAAK,EAAE,CAAC,EACR,OAAO,GAAE,wBAA6B,GACrC,CAAC,CAmCH;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,eAAe,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,eAAe,GAAG,IAAI,CAAC;AAEhG;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,GAAE,wBAA6B,GAAG,cAAc,CAK9F"}
|
package/dist/scrubber.js
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
*
|
|
9
9
|
* This package is GENERIC — it ships only obvious, domain-neutral defaults
|
|
10
10
|
* (full IPv4/IPv6 addresses, bearer/authorization tokens, generic credential
|
|
11
|
-
* assignments
|
|
11
|
+
* assignments, URL-borne credential parameters such as `oobCode` / `id_token`).
|
|
12
|
+
* Product-specific patterns (evidence-bucket URL prefixes,
|
|
12
13
|
* detector-hash shapes, NCMEC credential markers) are INJECTED by the consuming
|
|
13
14
|
* app via {@link createTelemetryScrubber}'s `patterns` option. No app-data-package
|
|
14
15
|
* import, no app-specific literals.
|
|
@@ -29,6 +30,35 @@ export const DEFAULT_FORBIDDEN_PATTERNS = [
|
|
|
29
30
|
/\b(?:[0-9a-fA-F]{1,4}:){1,7}:(?:[0-9a-fA-F]{1,4}:?){0,6}(?:[0-9a-fA-F]{1,4})?\b|::(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}\b/g,
|
|
30
31
|
// Authorization / bearer token: "Bearer xyz", "Authorization: Basic xyz".
|
|
31
32
|
/\b(?:Bearer|Basic)\s+[A-Za-z0-9._~+/-]{8,}={0,2}/gi,
|
|
33
|
+
// URL-borne credential PARAMETERS — bearer credentials that ride in a query
|
|
34
|
+
// string, where the browser SDK records the landing URL into `request.url`,
|
|
35
|
+
// navigation breadcrumbs, and session replay:
|
|
36
|
+
// - `oobCode` — the Firebase email-action one-time code
|
|
37
|
+
// (?mode=resetPassword&oobCode=…). Whoever reads it can complete the
|
|
38
|
+
// password reset, i.e. take the account over.
|
|
39
|
+
// - ANY `<prefix>token` spelling — `id_token`, `idToken`, `authToken`,
|
|
40
|
+
// `session_token`, `csrf_token`, … The generic assignment below cannot
|
|
41
|
+
// reach these: its `\btoken\b` needs a word boundary that both camelCase
|
|
42
|
+
// (`d` before `Token`) and snake_case (`_` before `token`) deny, which is
|
|
43
|
+
// why it had to enumerate `access[_-]?token` and `refresh[_-]?token` by
|
|
44
|
+
// hand. `[a-z]*[_-]?token\b` covers the whole class instead — the trailing
|
|
45
|
+
// `\b` is what keeps `valid_tokens`, `tokenizer`, and `tokenize` out.
|
|
46
|
+
// (Measured: no backtracking cost — the literal `token` anchor makes a
|
|
47
|
+
// non-matching alpha run fail fast, sub-ms on 40k chars.)
|
|
48
|
+
//
|
|
49
|
+
// This entry runs BEFORE the generic assignment ON PURPOSE, and its value
|
|
50
|
+
// class is the generic one MINUS `&`: these live in a query string, so
|
|
51
|
+
// stopping at the next parameter keeps `mode=`, `state=`, `lang=`, and
|
|
52
|
+
// `continueUrl=` readable instead of swallowing the rest of the URL. Order is
|
|
53
|
+
// load-bearing for any spelling the greedy pattern CAN reach — `id-token`,
|
|
54
|
+
// `X-Auth-Token` (`-` IS a word boundary) — which it would otherwise consume
|
|
55
|
+
// to end-of-string. The class stays negated rather than shaped to
|
|
56
|
+
// base64url/JWT so an unexpected value over-redacts instead of leaking a tail.
|
|
57
|
+
//
|
|
58
|
+
// This does NOT subsume the generic pattern's own token branches, so those
|
|
59
|
+
// stay: a value carrying an early `&` (`token=ab&cdef`) has fewer than 4
|
|
60
|
+
// non-`&` chars here and falls through to the greedy entry by design.
|
|
61
|
+
/\b(?:oob[_-]?code|[a-z]*[_-]?token)\b\s*[:=]\s*["']?[^\s"',}{&]{4,}/gi,
|
|
32
62
|
// Generic credential assignment: password=..., api_key: "...", secret=...,
|
|
33
63
|
// token=..., apiKey=..., access_token=... (value up to whitespace/quote).
|
|
34
64
|
/\b(?:password|passwd|pwd|secret|api[_-]?key|apikey|access[_-]?token|refresh[_-]?token|token|client[_-]?secret|authorization)\b\s*[:=]\s*["']?[^\s"',}{]{4,}/gi,
|
package/dist/scrubber.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scrubber.js","sourceRoot":"","sources":["../src/scrubber.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Telemetry scrubber — generic Sentry-event redaction.\n *\n * A defense-in-depth `beforeSend`-style hook that walks an ENTIRE Sentry event\n * (message, exception values + stacktrace frame vars, breadcrumbs, extra,\n * contexts, tags, request data, user) and replaces any substring matching a\n * forbidden pattern with a fixed placeholder.\n *\n * This package is GENERIC — it ships only obvious, domain-neutral defaults\n * (full IPv4/IPv6 addresses, bearer/authorization tokens, generic credential\n * assignments). Product-specific patterns (evidence-bucket URL prefixes,\n * detector-hash shapes, NCMEC credential markers) are INJECTED by the consuming\n * app via {@link createTelemetryScrubber}'s `patterns` option. No app-data-package\n * import, no app-specific literals.\n */\n\n/** The fixed replacement written over any matched forbidden substring. */\nexport const REDACTION_PLACEHOLDER = \"[REDACTED]\";\n\n/**\n * A forbidden pattern. Either a `RegExp` (matched globally against every string\n * in the event) or a literal `string` (every occurrence replaced). Strings are\n * treated as literals, not regex source, so callers do not have to escape them.\n */\nexport type ForbiddenPattern = RegExp | string;\n\nexport type RedactStringOptions = {\n /** Patterns to strip. Defaults to {@link DEFAULT_FORBIDDEN_PATTERNS}. */\n patterns?: ForbiddenPattern[];\n /** Replacement text. Defaults to {@link REDACTION_PLACEHOLDER}. */\n placeholder?: string;\n};\n\n/**\n * Generic, domain-neutral built-in patterns. These are intentionally\n * conservative (specific → low collateral on ordinary errors) but catch the\n * obvious secrets that must never reach telemetry regardless of app.\n */\nexport const DEFAULT_FORBIDDEN_PATTERNS: RegExp[] = [\n // Full IPv4 address (four dotted octets, each 0–255).\n /\\b(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\b/g,\n // Full (uncompressed) IPv6 address — eight hextet groups.\n /\\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\\b/g,\n // Compressed IPv6 with a \"::\" run (e.g. 2001:db8::1, ::1, fe80::abcd).\n /\\b(?:[0-9a-fA-F]{1,4}:){1,7}:(?:[0-9a-fA-F]{1,4}:?){0,6}(?:[0-9a-fA-F]{1,4})?\\b|::(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}\\b/g,\n // Authorization / bearer token: \"Bearer xyz\", \"Authorization: Basic xyz\".\n /\\b(?:Bearer|Basic)\\s+[A-Za-z0-9._~+/-]{8,}={0,2}/gi,\n // Generic credential assignment: password=..., api_key: \"...\", secret=...,\n // token=..., apiKey=..., access_token=... (value up to whitespace/quote).\n /\\b(?:password|passwd|pwd|secret|api[_-]?key|apikey|access[_-]?token|refresh[_-]?token|token|client[_-]?secret|authorization)\\b\\s*[:=]\\s*[\"']?[^\\s\"',}{]{4,}/gi,\n];\n\ntype CompiledPattern = { regex: RegExp; isLiteral: boolean; literal?: string };\n\nfunction escapeRegExp(input: string): string {\n return input.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction compilePatterns(patterns: ForbiddenPattern[]): CompiledPattern[] {\n return patterns.map((p) => {\n if (typeof p === \"string\") {\n return {\n regex: new RegExp(escapeRegExp(p), \"g\"),\n isLiteral: true,\n literal: p,\n };\n }\n // Ensure the flag set is global so `String.replace` strips every hit; clone\n // so we never mutate a caller-owned RegExp's lastIndex across calls.\n const flags = p.flags.includes(\"g\") ? p.flags : p.flags + \"g\";\n return { regex: new RegExp(p.source, flags), isLiteral: false };\n });\n}\n\n/**\n * Redact every forbidden-pattern hit inside a single string. Pure and safe on\n * any input. Empty when nothing matches → returns the original reference.\n */\nexport function redactString(value: string, options: RedactStringOptions = {}): string {\n const placeholder = options.placeholder ?? REDACTION_PLACEHOLDER;\n const compiled = compilePatterns(options.patterns ?? DEFAULT_FORBIDDEN_PATTERNS);\n let out = value;\n for (const { regex } of compiled) {\n regex.lastIndex = 0;\n out = out.replace(regex, placeholder);\n }\n return out;\n}\n\ntype DeepRedactOptions = {\n patterns: ForbiddenPattern[];\n placeholder: string;\n};\n\n/**\n * Recursively redact every string reachable inside an arbitrary value (objects,\n * arrays, nested combinations). Non-string primitives pass through untouched.\n * Object keys are NOT rewritten (a forbidden value hiding in a key is\n * pathological and rewriting keys would corrupt the event shape); only values\n * are scrubbed. Guards against cycles.\n */\nfunction deepRedact(value: unknown, options: DeepRedactOptions, seen: WeakSet<object>): unknown {\n if (typeof value === \"string\") {\n return redactString(value, options);\n }\n if (value === null || typeof value !== \"object\") {\n return value;\n }\n if (seen.has(value as object)) {\n return value;\n }\n seen.add(value as object);\n\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n value[i] = deepRedact(value[i], options, seen);\n }\n return value;\n }\n\n const record = value as Record<string, unknown>;\n for (const key of Object.keys(record)) {\n record[key] = deepRedact(record[key], options, seen);\n }\n return record;\n}\n\n/**\n * Minimal structural shape of a Sentry event we walk. Deliberately loose — we\n * do not depend on `@sentry/*` types (this package's Sentry deps are optional\n * peers, and the scrubber is provider-agnostic). Unknown fields are left alone\n * except that we deep-redact the free-form containers below.\n */\nexport type ScrubbableEvent = {\n message?: unknown;\n exception?: { values?: Array<Record<string, unknown>> } | unknown;\n breadcrumbs?: unknown;\n extra?: unknown;\n contexts?: unknown;\n tags?: unknown;\n request?: unknown;\n user?: unknown;\n [key: string]: unknown;\n};\n\nexport type TelemetryScrubberOptions = {\n /**\n * App-injected forbidden patterns (evidence-bucket URL prefixes, detector-hash\n * shapes, NCMEC credential markers, …). Merged AFTER the generic defaults\n * unless {@link includeDefaults} is false.\n */\n patterns?: ForbiddenPattern[];\n /** Include {@link DEFAULT_FORBIDDEN_PATTERNS}. Defaults to true. */\n includeDefaults?: boolean;\n /** Replacement text. Defaults to {@link REDACTION_PLACEHOLDER}. */\n placeholder?: string;\n};\n\n/**\n * Redact a whole Sentry event in place and return it. Exported so the backend\n * `withScope` / manual-capture path can benefit even where a `beforeSend`\n * pipeline is not wired.\n */\nexport function redactEvent<T extends ScrubbableEvent>(\n event: T,\n options: TelemetryScrubberOptions = {}\n): T {\n if (event === null || typeof event !== \"object\") return event;\n\n const includeDefaults = options.includeDefaults ?? true;\n const patterns: ForbiddenPattern[] = [\n ...(includeDefaults ? DEFAULT_FORBIDDEN_PATTERNS : []),\n ...(options.patterns ?? []),\n ];\n const deepOptions: DeepRedactOptions = {\n patterns,\n placeholder: options.placeholder ?? REDACTION_PLACEHOLDER,\n };\n const seen = new WeakSet<object>();\n\n // Top-level message (string or {message,params} structured form).\n if (event.message !== undefined) {\n event.message = deepRedact(event.message, deepOptions, seen);\n }\n\n // Exception values: type/value strings plus stacktrace frame vars/filenames.\n const exception = event.exception as { values?: Array<Record<string, unknown>> } | undefined;\n if (exception && Array.isArray(exception.values)) {\n for (const val of exception.values) {\n deepRedact(val, deepOptions, seen);\n }\n }\n\n // Free-form containers — walked wholesale.\n for (const container of [\"breadcrumbs\", \"extra\", \"contexts\", \"tags\", \"request\", \"user\"] as const) {\n if (event[container] !== undefined) {\n event[container] = deepRedact(event[container], deepOptions, seen);\n }\n }\n\n return event;\n}\n\n/**\n * A Sentry `beforeSend`-style hook: `(event, hint?) => event | null`. Drop-in\n * for `Sentry.init({ beforeSend })` in both the browser and Node SDKs.\n */\nexport type BeforeSendHook = (event: ScrubbableEvent, hint?: unknown) => ScrubbableEvent | null;\n\n/**\n * Build a `beforeSend` hook that scrubs every outgoing event. The app supplies\n * its product-specific `patterns`; generic defaults are included unless disabled.\n *\n * @example\n * Sentry.init({\n * dsn,\n * beforeSend: createTelemetryScrubber({\n * patterns: [\n * 'https://storage.googleapis.com/example-ncii-evidence/',\n * /\\bncmec-[a-z0-9]{16,}\\b/gi,\n * /\\b[a-f0-9]{64}\\b/g, // detector hash shape\n * ],\n * }),\n * });\n */\nexport function createTelemetryScrubber(options: TelemetryScrubberOptions = {}): BeforeSendHook {\n return (event, _hint) => {\n if (event === null || typeof event !== \"object\") return event;\n return redactEvent(event, options);\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"scrubber.js","sourceRoot":"","sources":["../src/scrubber.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Telemetry scrubber — generic Sentry-event redaction.\n *\n * A defense-in-depth `beforeSend`-style hook that walks an ENTIRE Sentry event\n * (message, exception values + stacktrace frame vars, breadcrumbs, extra,\n * contexts, tags, request data, user) and replaces any substring matching a\n * forbidden pattern with a fixed placeholder.\n *\n * This package is GENERIC — it ships only obvious, domain-neutral defaults\n * (full IPv4/IPv6 addresses, bearer/authorization tokens, generic credential\n * assignments, URL-borne credential parameters such as `oobCode` / `id_token`).\n * Product-specific patterns (evidence-bucket URL prefixes,\n * detector-hash shapes, NCMEC credential markers) are INJECTED by the consuming\n * app via {@link createTelemetryScrubber}'s `patterns` option. No app-data-package\n * import, no app-specific literals.\n */\n\n/** The fixed replacement written over any matched forbidden substring. */\nexport const REDACTION_PLACEHOLDER = \"[REDACTED]\";\n\n/**\n * A forbidden pattern. Either a `RegExp` (matched globally against every string\n * in the event) or a literal `string` (every occurrence replaced). Strings are\n * treated as literals, not regex source, so callers do not have to escape them.\n */\nexport type ForbiddenPattern = RegExp | string;\n\nexport type RedactStringOptions = {\n /** Patterns to strip. Defaults to {@link DEFAULT_FORBIDDEN_PATTERNS}. */\n patterns?: ForbiddenPattern[];\n /** Replacement text. Defaults to {@link REDACTION_PLACEHOLDER}. */\n placeholder?: string;\n};\n\n/**\n * Generic, domain-neutral built-in patterns. These are intentionally\n * conservative (specific → low collateral on ordinary errors) but catch the\n * obvious secrets that must never reach telemetry regardless of app.\n */\nexport const DEFAULT_FORBIDDEN_PATTERNS: RegExp[] = [\n // Full IPv4 address (four dotted octets, each 0–255).\n /\\b(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\b/g,\n // Full (uncompressed) IPv6 address — eight hextet groups.\n /\\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\\b/g,\n // Compressed IPv6 with a \"::\" run (e.g. 2001:db8::1, ::1, fe80::abcd).\n /\\b(?:[0-9a-fA-F]{1,4}:){1,7}:(?:[0-9a-fA-F]{1,4}:?){0,6}(?:[0-9a-fA-F]{1,4})?\\b|::(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}\\b/g,\n // Authorization / bearer token: \"Bearer xyz\", \"Authorization: Basic xyz\".\n /\\b(?:Bearer|Basic)\\s+[A-Za-z0-9._~+/-]{8,}={0,2}/gi,\n // URL-borne credential PARAMETERS — bearer credentials that ride in a query\n // string, where the browser SDK records the landing URL into `request.url`,\n // navigation breadcrumbs, and session replay:\n // - `oobCode` — the Firebase email-action one-time code\n // (?mode=resetPassword&oobCode=…). Whoever reads it can complete the\n // password reset, i.e. take the account over.\n // - ANY `<prefix>token` spelling — `id_token`, `idToken`, `authToken`,\n // `session_token`, `csrf_token`, … The generic assignment below cannot\n // reach these: its `\\btoken\\b` needs a word boundary that both camelCase\n // (`d` before `Token`) and snake_case (`_` before `token`) deny, which is\n // why it had to enumerate `access[_-]?token` and `refresh[_-]?token` by\n // hand. `[a-z]*[_-]?token\\b` covers the whole class instead — the trailing\n // `\\b` is what keeps `valid_tokens`, `tokenizer`, and `tokenize` out.\n // (Measured: no backtracking cost — the literal `token` anchor makes a\n // non-matching alpha run fail fast, sub-ms on 40k chars.)\n //\n // This entry runs BEFORE the generic assignment ON PURPOSE, and its value\n // class is the generic one MINUS `&`: these live in a query string, so\n // stopping at the next parameter keeps `mode=`, `state=`, `lang=`, and\n // `continueUrl=` readable instead of swallowing the rest of the URL. Order is\n // load-bearing for any spelling the greedy pattern CAN reach — `id-token`,\n // `X-Auth-Token` (`-` IS a word boundary) — which it would otherwise consume\n // to end-of-string. The class stays negated rather than shaped to\n // base64url/JWT so an unexpected value over-redacts instead of leaking a tail.\n //\n // This does NOT subsume the generic pattern's own token branches, so those\n // stay: a value carrying an early `&` (`token=ab&cdef`) has fewer than 4\n // non-`&` chars here and falls through to the greedy entry by design.\n /\\b(?:oob[_-]?code|[a-z]*[_-]?token)\\b\\s*[:=]\\s*[\"']?[^\\s\"',}{&]{4,}/gi,\n // Generic credential assignment: password=..., api_key: \"...\", secret=...,\n // token=..., apiKey=..., access_token=... (value up to whitespace/quote).\n /\\b(?:password|passwd|pwd|secret|api[_-]?key|apikey|access[_-]?token|refresh[_-]?token|token|client[_-]?secret|authorization)\\b\\s*[:=]\\s*[\"']?[^\\s\"',}{]{4,}/gi,\n];\n\ntype CompiledPattern = { regex: RegExp; isLiteral: boolean; literal?: string };\n\nfunction escapeRegExp(input: string): string {\n return input.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction compilePatterns(patterns: ForbiddenPattern[]): CompiledPattern[] {\n return patterns.map((p) => {\n if (typeof p === \"string\") {\n return {\n regex: new RegExp(escapeRegExp(p), \"g\"),\n isLiteral: true,\n literal: p,\n };\n }\n // Ensure the flag set is global so `String.replace` strips every hit; clone\n // so we never mutate a caller-owned RegExp's lastIndex across calls.\n const flags = p.flags.includes(\"g\") ? p.flags : p.flags + \"g\";\n return { regex: new RegExp(p.source, flags), isLiteral: false };\n });\n}\n\n/**\n * Redact every forbidden-pattern hit inside a single string. Pure and safe on\n * any input. Empty when nothing matches → returns the original reference.\n */\nexport function redactString(value: string, options: RedactStringOptions = {}): string {\n const placeholder = options.placeholder ?? REDACTION_PLACEHOLDER;\n const compiled = compilePatterns(options.patterns ?? DEFAULT_FORBIDDEN_PATTERNS);\n let out = value;\n for (const { regex } of compiled) {\n regex.lastIndex = 0;\n out = out.replace(regex, placeholder);\n }\n return out;\n}\n\ntype DeepRedactOptions = {\n patterns: ForbiddenPattern[];\n placeholder: string;\n};\n\n/**\n * Recursively redact every string reachable inside an arbitrary value (objects,\n * arrays, nested combinations). Non-string primitives pass through untouched.\n * Object keys are NOT rewritten (a forbidden value hiding in a key is\n * pathological and rewriting keys would corrupt the event shape); only values\n * are scrubbed. Guards against cycles.\n */\nfunction deepRedact(value: unknown, options: DeepRedactOptions, seen: WeakSet<object>): unknown {\n if (typeof value === \"string\") {\n return redactString(value, options);\n }\n if (value === null || typeof value !== \"object\") {\n return value;\n }\n if (seen.has(value as object)) {\n return value;\n }\n seen.add(value as object);\n\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n value[i] = deepRedact(value[i], options, seen);\n }\n return value;\n }\n\n const record = value as Record<string, unknown>;\n for (const key of Object.keys(record)) {\n record[key] = deepRedact(record[key], options, seen);\n }\n return record;\n}\n\n/**\n * Minimal structural shape of a Sentry event we walk. Deliberately loose — we\n * do not depend on `@sentry/*` types (this package's Sentry deps are optional\n * peers, and the scrubber is provider-agnostic). Unknown fields are left alone\n * except that we deep-redact the free-form containers below.\n */\nexport type ScrubbableEvent = {\n message?: unknown;\n exception?: { values?: Array<Record<string, unknown>> } | unknown;\n breadcrumbs?: unknown;\n extra?: unknown;\n contexts?: unknown;\n tags?: unknown;\n request?: unknown;\n user?: unknown;\n [key: string]: unknown;\n};\n\nexport type TelemetryScrubberOptions = {\n /**\n * App-injected forbidden patterns (evidence-bucket URL prefixes, detector-hash\n * shapes, NCMEC credential markers, …). Merged AFTER the generic defaults\n * unless {@link includeDefaults} is false.\n */\n patterns?: ForbiddenPattern[];\n /** Include {@link DEFAULT_FORBIDDEN_PATTERNS}. Defaults to true. */\n includeDefaults?: boolean;\n /** Replacement text. Defaults to {@link REDACTION_PLACEHOLDER}. */\n placeholder?: string;\n};\n\n/**\n * Redact a whole Sentry event in place and return it. Exported so the backend\n * `withScope` / manual-capture path can benefit even where a `beforeSend`\n * pipeline is not wired.\n */\nexport function redactEvent<T extends ScrubbableEvent>(\n event: T,\n options: TelemetryScrubberOptions = {}\n): T {\n if (event === null || typeof event !== \"object\") return event;\n\n const includeDefaults = options.includeDefaults ?? true;\n const patterns: ForbiddenPattern[] = [\n ...(includeDefaults ? DEFAULT_FORBIDDEN_PATTERNS : []),\n ...(options.patterns ?? []),\n ];\n const deepOptions: DeepRedactOptions = {\n patterns,\n placeholder: options.placeholder ?? REDACTION_PLACEHOLDER,\n };\n const seen = new WeakSet<object>();\n\n // Top-level message (string or {message,params} structured form).\n if (event.message !== undefined) {\n event.message = deepRedact(event.message, deepOptions, seen);\n }\n\n // Exception values: type/value strings plus stacktrace frame vars/filenames.\n const exception = event.exception as { values?: Array<Record<string, unknown>> } | undefined;\n if (exception && Array.isArray(exception.values)) {\n for (const val of exception.values) {\n deepRedact(val, deepOptions, seen);\n }\n }\n\n // Free-form containers — walked wholesale.\n for (const container of [\"breadcrumbs\", \"extra\", \"contexts\", \"tags\", \"request\", \"user\"] as const) {\n if (event[container] !== undefined) {\n event[container] = deepRedact(event[container], deepOptions, seen);\n }\n }\n\n return event;\n}\n\n/**\n * A Sentry `beforeSend`-style hook: `(event, hint?) => event | null`. Drop-in\n * for `Sentry.init({ beforeSend })` in both the browser and Node SDKs.\n */\nexport type BeforeSendHook = (event: ScrubbableEvent, hint?: unknown) => ScrubbableEvent | null;\n\n/**\n * Build a `beforeSend` hook that scrubs every outgoing event. The app supplies\n * its product-specific `patterns`; generic defaults are included unless disabled.\n *\n * @example\n * Sentry.init({\n * dsn,\n * beforeSend: createTelemetryScrubber({\n * patterns: [\n * 'https://storage.googleapis.com/example-ncii-evidence/',\n * /\\bncmec-[a-z0-9]{16,}\\b/gi,\n * /\\b[a-f0-9]{64}\\b/g, // detector hash shape\n * ],\n * }),\n * });\n */\nexport function createTelemetryScrubber(options: TelemetryScrubberOptions = {}): BeforeSendHook {\n return (event, _hint) => {\n if (event === null || typeof event !== \"object\") return event;\n return redactEvent(event, options);\n };\n}\n"]}
|
package/dist/types.d.ts
CHANGED
|
@@ -19,10 +19,15 @@ export type MonitoringUser = {
|
|
|
19
19
|
username?: string;
|
|
20
20
|
ip_address?: string;
|
|
21
21
|
};
|
|
22
|
+
/** The severity names every provider in this package understands. */
|
|
23
|
+
export type MonitoringLevel = "fatal" | "error" | "warning" | "info" | "debug";
|
|
22
24
|
export type ScopeLike = {
|
|
23
25
|
setTag: (key: string, value: string) => void;
|
|
24
26
|
setUser: (user: MonitoringUser | null) => void;
|
|
25
27
|
setExtra: (key: string, value: unknown) => void;
|
|
26
28
|
setContext: (key: string, context: Record<string, unknown>) => void;
|
|
29
|
+
/** Optional: real Sentry scopes have it, the noop/minimal scopes may not. A capture
|
|
30
|
+
* context's `level` is applied through this when present (see capture-context.ts). */
|
|
31
|
+
setLevel?: (level: MonitoringLevel) => void;
|
|
27
32
|
};
|
|
28
33
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,aAAa,GAAG,MAAM,CAAC;AAEnE,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;4CACwC;IACxC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;iGAE6F;IAC7F,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,OAAO,EAAE,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,KAAK,IAAI,CAAC;IAC/C,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,aAAa,GAAG,MAAM,CAAC;AAEnE,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;4CACwC;IACxC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;iGAE6F;IAC7F,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,qEAAqE;AACrE,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAE/E,MAAM,MAAM,SAAS,GAAG;IACtB,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,OAAO,EAAE,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,KAAK,IAAI,CAAC;IAC/C,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACpE;2FACuF;IACvF,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;CAC7C,CAAC"}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export type MonitoringProvider = \"sentry\" | \"sentry-node\" | \"noop\";\n\nexport type MonitoringInitOptions = {\n provider: MonitoringProvider;\n dsn?: string;\n environment?: string;\n enabled?: boolean; // default true\n release?: string;\n /** Performance-trace sample rate (0–1), passed through to the provider's init.\n * Omit to use the provider default. */\n tracesSampleRate?: number;\n /** Provider integrations passed through to the SDK init — e.g. `[]` to disable the\n * default auto-integrations and keep init lightweight (the consuming app's Cloud\n * Functions bootstrap does this). Typed loosely: it is a provider-specific pass-through. */\n integrations?: unknown[];\n};\n\nexport type MonitoringUser = {\n id?: string;\n email?: string;\n username?: string;\n ip_address?: string;\n};\n\nexport type ScopeLike = {\n setTag: (key: string, value: string) => void;\n setUser: (user: MonitoringUser | null) => void;\n setExtra: (key: string, value: unknown) => void;\n setContext: (key: string, context: Record<string, unknown>) => void;\n};"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export type MonitoringProvider = \"sentry\" | \"sentry-node\" | \"noop\";\n\nexport type MonitoringInitOptions = {\n provider: MonitoringProvider;\n dsn?: string;\n environment?: string;\n enabled?: boolean; // default true\n release?: string;\n /** Performance-trace sample rate (0–1), passed through to the provider's init.\n * Omit to use the provider default. */\n tracesSampleRate?: number;\n /** Provider integrations passed through to the SDK init — e.g. `[]` to disable the\n * default auto-integrations and keep init lightweight (the consuming app's Cloud\n * Functions bootstrap does this). Typed loosely: it is a provider-specific pass-through. */\n integrations?: unknown[];\n};\n\nexport type MonitoringUser = {\n id?: string;\n email?: string;\n username?: string;\n ip_address?: string;\n};\n\n/** The severity names every provider in this package understands. */\nexport type MonitoringLevel = \"fatal\" | \"error\" | \"warning\" | \"info\" | \"debug\";\n\nexport type ScopeLike = {\n setTag: (key: string, value: string) => void;\n setUser: (user: MonitoringUser | null) => void;\n setExtra: (key: string, value: unknown) => void;\n setContext: (key: string, context: Record<string, unknown>) => void;\n /** Optional: real Sentry scopes have it, the noop/minimal scopes may not. A capture\n * context's `level` is applied through this when present (see capture-context.ts). */\n setLevel?: (level: MonitoringLevel) => void;\n};"]}
|