@cubenest/rrweb-core 0.1.0-alpha.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.
Files changed (135) hide show
  1. package/NOTICE +15 -0
  2. package/README.md +26 -0
  3. package/dist/compat/index.d.ts +37 -0
  4. package/dist/compat/index.d.ts.map +1 -0
  5. package/dist/compat/index.js +97 -0
  6. package/dist/compat/index.js.map +1 -0
  7. package/dist/compression/index.d.ts +24 -0
  8. package/dist/compression/index.d.ts.map +1 -0
  9. package/dist/compression/index.js +61 -0
  10. package/dist/compression/index.js.map +1 -0
  11. package/dist/console/buffer.d.ts +99 -0
  12. package/dist/console/buffer.d.ts.map +1 -0
  13. package/dist/console/buffer.js +169 -0
  14. package/dist/console/buffer.js.map +1 -0
  15. package/dist/console/index.d.ts +3 -0
  16. package/dist/console/index.d.ts.map +1 -0
  17. package/dist/console/index.js +16 -0
  18. package/dist/console/index.js.map +1 -0
  19. package/dist/console/types.d.ts +61 -0
  20. package/dist/console/types.d.ts.map +1 -0
  21. package/dist/console/types.js +11 -0
  22. package/dist/console/types.js.map +1 -0
  23. package/dist/index.d.ts +17 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +18 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/masking/body.d.ts +30 -0
  28. package/dist/masking/body.d.ts.map +1 -0
  29. package/dist/masking/body.js +33 -0
  30. package/dist/masking/body.js.map +1 -0
  31. package/dist/masking/headers.d.ts +16 -0
  32. package/dist/masking/headers.d.ts.map +1 -0
  33. package/dist/masking/headers.js +46 -0
  34. package/dist/masking/headers.js.map +1 -0
  35. package/dist/masking/index.d.ts +8 -0
  36. package/dist/masking/index.d.ts.map +1 -0
  37. package/dist/masking/index.js +11 -0
  38. package/dist/masking/index.js.map +1 -0
  39. package/dist/masking/inputs.d.ts +15 -0
  40. package/dist/masking/inputs.d.ts.map +1 -0
  41. package/dist/masking/inputs.js +36 -0
  42. package/dist/masking/inputs.js.map +1 -0
  43. package/dist/masking/regex.d.ts +96 -0
  44. package/dist/masking/regex.d.ts.map +1 -0
  45. package/dist/masking/regex.js +182 -0
  46. package/dist/masking/regex.js.map +1 -0
  47. package/dist/masking/selectors.d.ts +67 -0
  48. package/dist/masking/selectors.d.ts.map +1 -0
  49. package/dist/masking/selectors.js +137 -0
  50. package/dist/masking/selectors.js.map +1 -0
  51. package/dist/masking/text.d.ts +9 -0
  52. package/dist/masking/text.d.ts.map +1 -0
  53. package/dist/masking/text.js +15 -0
  54. package/dist/masking/text.js.map +1 -0
  55. package/dist/network/cdp.d.ts +54 -0
  56. package/dist/network/cdp.d.ts.map +1 -0
  57. package/dist/network/cdp.js +282 -0
  58. package/dist/network/cdp.js.map +1 -0
  59. package/dist/network/index.d.ts +4 -0
  60. package/dist/network/index.d.ts.map +1 -0
  61. package/dist/network/index.js +14 -0
  62. package/dist/network/index.js.map +1 -0
  63. package/dist/network/types.d.ts +133 -0
  64. package/dist/network/types.d.ts.map +1 -0
  65. package/dist/network/types.js +35 -0
  66. package/dist/network/types.js.map +1 -0
  67. package/dist/network/web-request.d.ts +76 -0
  68. package/dist/network/web-request.d.ts.map +1 -0
  69. package/dist/network/web-request.js +294 -0
  70. package/dist/network/web-request.js.map +1 -0
  71. package/dist/persistence/index.d.ts +3 -0
  72. package/dist/persistence/index.d.ts.map +1 -0
  73. package/dist/persistence/index.js +11 -0
  74. package/dist/persistence/index.js.map +1 -0
  75. package/dist/persistence/store.d.ts +18 -0
  76. package/dist/persistence/store.d.ts.map +1 -0
  77. package/dist/persistence/store.js +327 -0
  78. package/dist/persistence/store.js.map +1 -0
  79. package/dist/persistence/types.d.ts +76 -0
  80. package/dist/persistence/types.d.ts.map +1 -0
  81. package/dist/persistence/types.js +21 -0
  82. package/dist/persistence/types.js.map +1 -0
  83. package/dist/rrweb.d.ts +5 -0
  84. package/dist/rrweb.d.ts.map +1 -0
  85. package/dist/rrweb.js +13 -0
  86. package/dist/rrweb.js.map +1 -0
  87. package/dist/screenshot/base64.d.ts +8 -0
  88. package/dist/screenshot/base64.d.ts.map +1 -0
  89. package/dist/screenshot/base64.js +21 -0
  90. package/dist/screenshot/base64.js.map +1 -0
  91. package/dist/screenshot/cdp.d.ts +50 -0
  92. package/dist/screenshot/cdp.d.ts.map +1 -0
  93. package/dist/screenshot/cdp.js +65 -0
  94. package/dist/screenshot/cdp.js.map +1 -0
  95. package/dist/screenshot/index.d.ts +4 -0
  96. package/dist/screenshot/index.d.ts.map +1 -0
  97. package/dist/screenshot/index.js +10 -0
  98. package/dist/screenshot/index.js.map +1 -0
  99. package/dist/screenshot/tabs.d.ts +44 -0
  100. package/dist/screenshot/tabs.d.ts.map +1 -0
  101. package/dist/screenshot/tabs.js +63 -0
  102. package/dist/screenshot/tabs.js.map +1 -0
  103. package/dist/screenshot/types.d.ts +27 -0
  104. package/dist/screenshot/types.d.ts.map +1 -0
  105. package/dist/screenshot/types.js +18 -0
  106. package/dist/screenshot/types.js.map +1 -0
  107. package/dist/shadow-dom/index.d.ts +3 -0
  108. package/dist/shadow-dom/index.d.ts.map +1 -0
  109. package/dist/shadow-dom/index.js +8 -0
  110. package/dist/shadow-dom/index.js.map +1 -0
  111. package/dist/shadow-dom/traverse.d.ts +54 -0
  112. package/dist/shadow-dom/traverse.d.ts.map +1 -0
  113. package/dist/shadow-dom/traverse.js +209 -0
  114. package/dist/shadow-dom/traverse.js.map +1 -0
  115. package/dist/shadow-dom/types.d.ts +43 -0
  116. package/dist/shadow-dom/types.d.ts.map +1 -0
  117. package/dist/shadow-dom/types.js +25 -0
  118. package/dist/shadow-dom/types.js.map +1 -0
  119. package/dist/throttling/apply.d.ts +59 -0
  120. package/dist/throttling/apply.d.ts.map +1 -0
  121. package/dist/throttling/apply.js +101 -0
  122. package/dist/throttling/apply.js.map +1 -0
  123. package/dist/throttling/defaults.d.ts +60 -0
  124. package/dist/throttling/defaults.d.ts.map +1 -0
  125. package/dist/throttling/defaults.js +81 -0
  126. package/dist/throttling/defaults.js.map +1 -0
  127. package/dist/throttling/guards.d.ts +69 -0
  128. package/dist/throttling/guards.d.ts.map +1 -0
  129. package/dist/throttling/guards.js +212 -0
  130. package/dist/throttling/guards.js.map +1 -0
  131. package/dist/throttling/index.d.ts +5 -0
  132. package/dist/throttling/index.d.ts.map +1 -0
  133. package/dist/throttling/index.js +11 -0
  134. package/dist/throttling/index.js.map +1 -0
  135. package/package.json +35 -0
@@ -0,0 +1,182 @@
1
+ // PII regex bank. Internal — not part of the public API surface.
2
+ //
3
+ // Each pattern is intentionally conservative to limit false positives;
4
+ // callers route matches through type-tagged tokens (`<<REDACTED:CC>>` etc).
5
+ // Known caveats are documented inline alongside each pattern.
6
+ //
7
+ // All `g` (global) patterns are stateful via lastIndex; helpers reset before
8
+ // use. Treat these as read-only constants.
9
+ /**
10
+ * Email — RFC 5322 "lite". Matches the overwhelming majority of real-world
11
+ * addresses without trying to model the full grammar (which permits quoted
12
+ * locals and comments most senders never use).
13
+ *
14
+ * Quantifier caps (`{1,64}`/`{1,255}`/`{2,24}`) are intentional: the spec
15
+ * lets local-parts run to 64 chars and the full address to 254, so the
16
+ * caps are not under-matching real addresses. They DO bound backtracking
17
+ * cost — unbounded `+` here is catastrophic on large no-`@` inputs (a
18
+ * megabyte of `a`s would quadratically backtrack at every start position).
19
+ *
20
+ * False-positive surface: strings like `a@b.co` where the TLD is short
21
+ * will match. Acceptable — we'd rather over-redact emails.
22
+ */
23
+ export const EMAIL_REGEX = /[A-Za-z0-9._%+-]{1,64}@[A-Za-z0-9.-]{1,255}\.[A-Za-z]{2,24}/g;
24
+ /**
25
+ * US Social Security Number — `NNN-NN-NNNN`. We intentionally require the
26
+ * dashes; the dash-less 9-digit form collides with too many legitimate
27
+ * identifiers (order numbers, zip+4, etc).
28
+ */
29
+ export const SSN_REGEX = /\b\d{3}-\d{2}-\d{4}\b/g;
30
+ /**
31
+ * Credit-card candidate — 13-19 contiguous digits with optional separators
32
+ * (spaces or dashes). Match alone is NOT enough; callers MUST pass each
33
+ * match through {@link luhn} before treating it as a real card number.
34
+ *
35
+ * Prefixes we expect to catch (validated by Luhn after the fact):
36
+ * Visa 4xxx
37
+ * Mastercard 5xxx, 2221-2720
38
+ * Amex 34xx, 37xx (15 digits)
39
+ * Discover 6011, 65, 644-649 (16 digits)
40
+ *
41
+ * The `(?:[ -]?\d){12,18}` shape is anchored on a leading digit and only
42
+ * matches 13-19 total digits — bounded width means linear-time matching.
43
+ *
44
+ * False-positive surface without Luhn: phone numbers, account numbers,
45
+ * arbitrary 16-digit strings. Luhn cuts that to near-zero.
46
+ */
47
+ export const CREDIT_CARD_REGEX = /\b\d(?:[ -]?\d){12,18}\b/g;
48
+ /**
49
+ * Phone — international-ish (E.164-friendly). Permissive on separators.
50
+ *
51
+ * False-positive surface: large numeric runs with separators (e.g. some
52
+ * timestamps, account numbers with dashes). We accept this; callers route
53
+ * to `<<REDACTED:PHONE>>` so the AI consumer knows the redaction type and
54
+ * can choose to ignore it if context suggests not-a-phone.
55
+ */
56
+ export const PHONE_REGEX = /\+?\d{1,3}[-.\s]?\(?\d{1,4}\)?[-.\s]?\d{1,4}[-.\s]?\d{1,9}/g;
57
+ /**
58
+ * JWT — three base64url segments separated by `.`. The 10-char minimum on
59
+ * each segment screens out very short look-alikes (e.g. `eyJ.a.b`).
60
+ * Upper bound of 4096 per segment is generous (RFC 7519 doesn't set one;
61
+ * real-world JWTs rarely exceed ~2 KB total) and keeps the regex linear.
62
+ */
63
+ export const JWT_REGEX = /eyJ[A-Za-z0-9_-]{10,4096}\.[A-Za-z0-9_-]{10,4096}\.[A-Za-z0-9_-]{10,4096}/g;
64
+ /**
65
+ * Stripe secret/publishable keys — `sk_live_*`, `sk_test_*`, `pk_live_*`,
66
+ * `pk_test_*` with 24-128 chars of payload (real keys are ~99 chars but
67
+ * the cap protects against pathological inputs).
68
+ */
69
+ export const STRIPE_KEY_REGEX = /\b(?:sk|pk)_(?:live|test)_[A-Za-z0-9]{24,128}\b/g;
70
+ /**
71
+ * GitHub personal-access tokens — `ghp_` prefix + 36 chars.
72
+ */
73
+ export const GITHUB_TOKEN_REGEX = /\bghp_[A-Za-z0-9]{36}\b/g;
74
+ /**
75
+ * AWS access key IDs — `AKIA` prefix + 16 uppercase-alnum chars.
76
+ */
77
+ export const AWS_ACCESS_KEY_REGEX = /\bAKIA[0-9A-Z]{16}\b/g;
78
+ /**
79
+ * PEM blocks — anything between `-----BEGIN ...-----` and `-----END ...-----`.
80
+ * Non-greedy so multiple blocks in one string don't merge. The `{1,64}`
81
+ * label cap matches what OpenSSL emits; the `{1,131072}` body cap is the
82
+ * widest realistic PEM (~96 KB for an 8192-bit RSA key with armor).
83
+ */
84
+ export const PEM_BLOCK_REGEX = /-----BEGIN [A-Z ]{1,64}-----[\s\S]{1,131072}?-----END [A-Z ]{1,64}-----/g;
85
+ /**
86
+ * Luhn check (mod-10). Accepts a digit string with optional spaces/dashes;
87
+ * returns true iff the cleaned digit run is 13-19 chars and passes the
88
+ * checksum. Used to confirm a {@link CREDIT_CARD_REGEX} match before
89
+ * tagging as a credit card.
90
+ */
91
+ export function luhn(candidate) {
92
+ const digits = candidate.replace(/[\s-]/g, '');
93
+ if (digits.length < 13 || digits.length > 19)
94
+ return false;
95
+ if (!/^\d+$/.test(digits))
96
+ return false;
97
+ let sum = 0;
98
+ let alt = false;
99
+ for (let i = digits.length - 1; i >= 0; i--) {
100
+ let n = digits.charCodeAt(i) - 48; // '0' = 48
101
+ if (n < 0 || n > 9)
102
+ return false;
103
+ if (alt) {
104
+ n *= 2;
105
+ if (n > 9)
106
+ n -= 9;
107
+ }
108
+ sum += n;
109
+ alt = !alt;
110
+ }
111
+ return sum % 10 === 0;
112
+ }
113
+ const TOKEN = (tag) => `<<REDACTED:${tag}>>`;
114
+ /**
115
+ * Order matters: high-specificity patterns first so they win when a string
116
+ * could match multiple banks (e.g. a Stripe key looks like a generic alnum
117
+ * blob; PEM bodies might contain base64 chunks that resemble JWT halves).
118
+ *
119
+ * Credit cards are handled separately because they need Luhn validation.
120
+ */
121
+ const ORDERED_PATTERNS = [
122
+ { tag: 'PEM', re: PEM_BLOCK_REGEX },
123
+ { tag: 'JWT', re: JWT_REGEX },
124
+ { tag: 'STRIPE_KEY', re: STRIPE_KEY_REGEX },
125
+ { tag: 'GITHUB_TOKEN', re: GITHUB_TOKEN_REGEX },
126
+ { tag: 'AWS_KEY', re: AWS_ACCESS_KEY_REGEX },
127
+ { tag: 'EMAIL', re: EMAIL_REGEX },
128
+ { tag: 'SSN', re: SSN_REGEX },
129
+ // Phone is intentionally last among the non-CC banks: it's the most
130
+ // false-positive-prone, so any prior bank that matched the same span
131
+ // should claim it first.
132
+ { tag: 'PHONE', re: PHONE_REGEX },
133
+ ];
134
+ /**
135
+ * Apply the regex bank to `input`, returning the redacted string.
136
+ * Credit cards are handled in a separate Luhn-validated pass.
137
+ *
138
+ * Internal — exposed via `redactBody` and `maskTextContent` only.
139
+ */
140
+ export function applyRegexBank(input) {
141
+ if (input.length === 0)
142
+ return input;
143
+ let out = input;
144
+ // Pass 1: Luhn-validated credit cards. We replace match-by-match so we
145
+ // don't redact strings that look like CCs but fail the checksum.
146
+ out = replaceWithValidator(out, CREDIT_CARD_REGEX, (m) => (luhn(m) ? TOKEN('CC') : null));
147
+ // Pass 2: the remaining ordered patterns. Each pattern runs against
148
+ // whatever's left after the prior passes, so tokens like
149
+ // `<<REDACTED:CC>>` won't be re-matched.
150
+ for (const { tag, re } of ORDERED_PATTERNS) {
151
+ // Fresh regex per pass to keep `lastIndex` clean.
152
+ const fresh = new RegExp(re.source, re.flags);
153
+ out = out.replace(fresh, TOKEN(tag));
154
+ }
155
+ return out;
156
+ }
157
+ /**
158
+ * Like `String.prototype.replace(re, fn)` but lets the callback return
159
+ * `null` to skip the replacement (leave the original substring in place).
160
+ * Used for Luhn-gated credit-card redaction.
161
+ */
162
+ function replaceWithValidator(input, re, fn) {
163
+ const fresh = new RegExp(re.source, re.flags);
164
+ let result = '';
165
+ let lastIndex = 0;
166
+ let match = fresh.exec(input);
167
+ while (match !== null) {
168
+ const replacement = fn(match[0]);
169
+ if (replacement !== null) {
170
+ result += input.slice(lastIndex, match.index) + replacement;
171
+ lastIndex = match.index + match[0].length;
172
+ }
173
+ // If validator rejected, leave the substring; advance past it so the
174
+ // regex doesn't re-match in place.
175
+ if (fresh.lastIndex === match.index)
176
+ fresh.lastIndex++;
177
+ match = fresh.exec(input);
178
+ }
179
+ result += input.slice(lastIndex);
180
+ return result;
181
+ }
182
+ //# sourceMappingURL=regex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regex.js","sourceRoot":"","sources":["../../src/masking/regex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Selector families recognized by the substrate. Frozen at module load to
3
+ * prevent runtime tampering — masking config is a privacy boundary and we
4
+ * don't want anywhere in the stack to be able to mutate it.
5
+ */
6
+ export declare const COMPAT_SELECTORS: Readonly<{
7
+ /**
8
+ * Native `<org>`-prefixed family (cubenest).
9
+ * Apps embedding the substrate directly should prefer these.
10
+ */
11
+ cubenest: Readonly<{
12
+ block: "cubenest-block";
13
+ mask: "cubenest-mask";
14
+ ignore: "cubenest-ignore";
15
+ dataAttrs: readonly string[];
16
+ }>;
17
+ /**
18
+ * PostHog session-replay conventions.
19
+ * Sources: posthog-js README and `session-recording.ts`.
20
+ */
21
+ posthog: Readonly<{
22
+ block: "ph-no-capture";
23
+ mask: "ph-mask";
24
+ ignore: "ph-ignore-input";
25
+ dataAttrs: readonly string[];
26
+ }>;
27
+ /**
28
+ * Sentry session-replay conventions.
29
+ * Sources: @sentry/replay docs.
30
+ */
31
+ sentry: Readonly<{
32
+ block: "sentry-block";
33
+ mask: "sentry-mask";
34
+ ignore: "sentry-ignore";
35
+ dataAttrs: readonly string[];
36
+ }>;
37
+ /**
38
+ * Upstream rrweb conventions (the `rr-*` prefix).
39
+ * Sources: rrweb-snapshot README.
40
+ */
41
+ rrweb: Readonly<{
42
+ block: "rr-block";
43
+ mask: "rr-mask";
44
+ ignore: "rr-ignore";
45
+ dataAttrs: readonly string[];
46
+ }>;
47
+ /**
48
+ * Datadog RUM session-replay conventions. Datadog uses data-attribute
49
+ * values rather than classes; we expose the attribute names plus the
50
+ * privacy values they accept.
51
+ * Sources: Datadog RUM docs.
52
+ */
53
+ datadog: Readonly<{
54
+ block: "data-dd-privacy=\"hidden\"";
55
+ mask: "data-dd-privacy=\"mask\"";
56
+ ignore: "data-private";
57
+ dataAttrs: readonly string[];
58
+ }>;
59
+ }>;
60
+ export type CompatSelectorFamily = keyof typeof COMPAT_SELECTORS;
61
+ /**
62
+ * Walks `el` and its ancestors, returning true if any node carries a class
63
+ * from a known mask/block family OR a Datadog `data-dd-privacy` /
64
+ * `data-private` attribute. Internal — used by `maskInputValue`.
65
+ */
66
+ export declare function elementMatchesAnyMaskClass(el: Element | null): boolean;
67
+ //# sourceMappingURL=selectors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selectors.d.ts","sourceRoot":"","sources":["../../src/masking/selectors.ts"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;IAC3B;;;OAGG;;;;;mBASK,SAAS,MAAM,EAAE;;IAGzB;;;OAGG;;;;;mBAK0D,SAAS,MAAM,EAAE;;IAG9E;;;OAGG;;;;;mBASK,SAAS,MAAM,EAAE;;IAGzB;;;OAGG;;;;;mBASK,SAAS,MAAM,EAAE;;IAGzB;;;;;OAKG;;;;;mBAQgE,SAAS,MAAM,EAAE;;EAEpF,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,MAAM,OAAO,gBAAgB,CAAC;AAwBjE;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,GAAG,OAAO,CAwBtE"}
@@ -0,0 +1,137 @@
1
+ // Compatibility selectors inherited from the rrweb ecosystem.
2
+ // Recording libraries (PostHog, Sentry, upstream rrweb, Datadog) have each
3
+ // established their own DOM hint conventions for "don't capture this".
4
+ // `@cubenest/rrweb-core` honors all of them so apps that already annotated
5
+ // their DOM for one vendor don't have to re-annotate.
6
+ //
7
+ // See ADR-0002 for the rationale and source links.
8
+ /**
9
+ * Selector families recognized by the substrate. Frozen at module load to
10
+ * prevent runtime tampering — masking config is a privacy boundary and we
11
+ * don't want anywhere in the stack to be able to mutate it.
12
+ */
13
+ export const COMPAT_SELECTORS = Object.freeze({
14
+ /**
15
+ * Native `<org>`-prefixed family (cubenest).
16
+ * Apps embedding the substrate directly should prefer these.
17
+ */
18
+ cubenest: Object.freeze({
19
+ block: 'cubenest-block',
20
+ mask: 'cubenest-mask',
21
+ ignore: 'cubenest-ignore',
22
+ dataAttrs: Object.freeze([
23
+ 'data-cubenest-mask',
24
+ 'data-cubenest-block',
25
+ 'data-cubenest-ignore',
26
+ ]),
27
+ }),
28
+ /**
29
+ * PostHog session-replay conventions.
30
+ * Sources: posthog-js README and `session-recording.ts`.
31
+ */
32
+ posthog: Object.freeze({
33
+ block: 'ph-no-capture',
34
+ mask: 'ph-mask',
35
+ ignore: 'ph-ignore-input',
36
+ dataAttrs: Object.freeze(['data-ph-capture-attribute']),
37
+ }),
38
+ /**
39
+ * Sentry session-replay conventions.
40
+ * Sources: @sentry/replay docs.
41
+ */
42
+ sentry: Object.freeze({
43
+ block: 'sentry-block',
44
+ mask: 'sentry-mask',
45
+ ignore: 'sentry-ignore',
46
+ dataAttrs: Object.freeze([
47
+ 'data-sentry-block',
48
+ 'data-sentry-mask',
49
+ 'data-sentry-ignore',
50
+ ]),
51
+ }),
52
+ /**
53
+ * Upstream rrweb conventions (the `rr-*` prefix).
54
+ * Sources: rrweb-snapshot README.
55
+ */
56
+ rrweb: Object.freeze({
57
+ block: 'rr-block',
58
+ mask: 'rr-mask',
59
+ ignore: 'rr-ignore',
60
+ dataAttrs: Object.freeze([
61
+ 'data-rr-block',
62
+ 'data-rr-mask',
63
+ 'data-rr-ignore',
64
+ ]),
65
+ }),
66
+ /**
67
+ * Datadog RUM session-replay conventions. Datadog uses data-attribute
68
+ * values rather than classes; we expose the attribute names plus the
69
+ * privacy values they accept.
70
+ * Sources: Datadog RUM docs.
71
+ */
72
+ datadog: Object.freeze({
73
+ // Datadog has no class-based block/mask/ignore; we mirror the shape
74
+ // by surfacing the attribute names. Consumers walking the tree look
75
+ // for `data-dd-privacy=hidden` (block) or `=mask` (mask).
76
+ block: 'data-dd-privacy="hidden"',
77
+ mask: 'data-dd-privacy="mask"',
78
+ ignore: 'data-private',
79
+ dataAttrs: Object.freeze(['data-private', 'data-dd-privacy']),
80
+ }),
81
+ });
82
+ /**
83
+ * Flat list of class names that mean "block this element entirely" across
84
+ * all families. Internal helper used by {@link elementMatchesAnyMaskClass}.
85
+ */
86
+ const ALL_BLOCK_CLASSES = Object.freeze([
87
+ COMPAT_SELECTORS.cubenest.block,
88
+ COMPAT_SELECTORS.posthog.block,
89
+ COMPAT_SELECTORS.sentry.block,
90
+ COMPAT_SELECTORS.rrweb.block,
91
+ ]);
92
+ /**
93
+ * Flat list of class names that mean "mask this element's value". Datadog
94
+ * is omitted because it uses attributes, not classes.
95
+ */
96
+ const ALL_MASK_CLASSES = Object.freeze([
97
+ COMPAT_SELECTORS.cubenest.mask,
98
+ COMPAT_SELECTORS.posthog.mask,
99
+ COMPAT_SELECTORS.sentry.mask,
100
+ COMPAT_SELECTORS.rrweb.mask,
101
+ ]);
102
+ /**
103
+ * Walks `el` and its ancestors, returning true if any node carries a class
104
+ * from a known mask/block family OR a Datadog `data-dd-privacy` /
105
+ * `data-private` attribute. Internal — used by `maskInputValue`.
106
+ */
107
+ export function elementMatchesAnyMaskClass(el) {
108
+ let node = el;
109
+ while (node !== null) {
110
+ // Class-based matches.
111
+ if (node.classList !== undefined) {
112
+ for (const cls of ALL_MASK_CLASSES) {
113
+ if (node.classList.contains(cls))
114
+ return true;
115
+ }
116
+ for (const cls of ALL_BLOCK_CLASSES) {
117
+ if (node.classList.contains(cls))
118
+ return true;
119
+ }
120
+ }
121
+ // Attribute-based matches (cubenest data-attrs + Datadog).
122
+ if (typeof node.hasAttribute === 'function') {
123
+ for (const attr of COMPAT_SELECTORS.cubenest.dataAttrs) {
124
+ if (node.hasAttribute(attr))
125
+ return true;
126
+ }
127
+ if (node.hasAttribute('data-private'))
128
+ return true;
129
+ const ddPrivacy = node.getAttribute('data-dd-privacy');
130
+ if (ddPrivacy === 'hidden' || ddPrivacy === 'mask')
131
+ return true;
132
+ }
133
+ node = node.parentElement;
134
+ }
135
+ return false;
136
+ }
137
+ //# sourceMappingURL=selectors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selectors.js","sourceRoot":"","sources":["../../src/masking/selectors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Apply the PII regex bank to a text-node's content. Used when capturing
3
+ * text mutations during recording.
4
+ *
5
+ * Pure string in, pure string out — no DOM dependency. Callers extract
6
+ * `textNode.data` (or equivalent) before calling.
7
+ */
8
+ export declare function maskTextContent(text: string): string;
9
+ //# sourceMappingURL=text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/masking/text.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGpD"}
@@ -0,0 +1,15 @@
1
+ // Text-node content masking.
2
+ import { applyRegexBank } from './regex';
3
+ /**
4
+ * Apply the PII regex bank to a text-node's content. Used when capturing
5
+ * text mutations during recording.
6
+ *
7
+ * Pure string in, pure string out — no DOM dependency. Callers extract
8
+ * `textNode.data` (or equivalent) before calling.
9
+ */
10
+ export function maskTextContent(text) {
11
+ if (text.length === 0)
12
+ return text;
13
+ return applyRegexBank(text);
14
+ }
15
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/masking/text.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAE7B,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,54 @@
1
+ import type { NetworkCaptureAdapter } from './types';
2
+ /**
3
+ * Structural shape of the CDP event source. The product-side wrapper
4
+ * adapts whichever CDP client it has (chrome-remote-interface,
5
+ * WDIO/Playwright/Puppeteer CDP sessions, …) to this minimal interface.
6
+ *
7
+ * `on(event, handler)` MUST return an unsubscribe function; if the
8
+ * underlying client doesn't natively expose unsubscribe, the wrapper is
9
+ * responsible for synthesizing one.
10
+ *
11
+ * `getResponseBody`, when present, mirrors CDP's
12
+ * `Network.getResponseBody` reply: `{ body, base64Encoded }`. The adapter
13
+ * only calls it when `captureResponseBodies: true` (and silently skips
14
+ * binary `base64Encoded: true` payloads — we don't redact binary, so
15
+ * tagging it would mislead consumers).
16
+ */
17
+ export interface CDPNetworkEventSource {
18
+ on(event: string, handler: (params: unknown) => void): () => void;
19
+ getResponseBody?(requestId: string): Promise<{
20
+ body: string;
21
+ base64Encoded: boolean;
22
+ }>;
23
+ }
24
+ /**
25
+ * Factory-time options for `createCDPNetworkAdapter`.
26
+ */
27
+ export interface CDPNetworkOptions {
28
+ /**
29
+ * Try to fetch response bodies via `getResponseBody` when the event
30
+ * source exposes it. Defaults to `false` because CDP retains bodies in
31
+ * the renderer until fetched (memory tax) and the request/response
32
+ * metadata is usually enough for triage.
33
+ */
34
+ captureResponseBodies?: boolean;
35
+ /**
36
+ * Body cap forwarded to `redactBody`. Defaults to 1 MB (the masking
37
+ * module's own default — listed here for discoverability).
38
+ */
39
+ maxBodyBytes?: number;
40
+ }
41
+ /**
42
+ * Build a `NetworkCaptureAdapter` that consumes CDP `Network.*` events.
43
+ *
44
+ * The adapter installs its own subscriptions on `source` and tracks
45
+ * in-flight requests in an internal `Map` keyed by CDP `requestId`. The
46
+ * map is cleared lazily as terminal events arrive; calling `dispose()`
47
+ * unsubscribes all four CDP listeners and drops any remaining entries.
48
+ *
49
+ * @param source A `CDPNetworkEventSource` (typically a thin wrapper around
50
+ * the CDP client owned by the calling framework).
51
+ * @param options `{ captureResponseBodies?, maxBodyBytes? }`.
52
+ */
53
+ export declare function createCDPNetworkAdapter(source: CDPNetworkEventSource, options?: CDPNetworkOptions): NetworkCaptureAdapter;
54
+ //# sourceMappingURL=cdp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdp.d.ts","sourceRoot":"","sources":["../../src/network/cdp.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAqC,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAExF;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,qBAAqB;IACpC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAClE,eAAe,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACxF;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA2GD;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,qBAAqB,EAC7B,OAAO,GAAE,iBAAsB,GAC9B,qBAAqB,CAqOvB"}