@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.
- package/NOTICE +15 -0
- package/README.md +26 -0
- package/dist/compat/index.d.ts +37 -0
- package/dist/compat/index.d.ts.map +1 -0
- package/dist/compat/index.js +97 -0
- package/dist/compat/index.js.map +1 -0
- package/dist/compression/index.d.ts +24 -0
- package/dist/compression/index.d.ts.map +1 -0
- package/dist/compression/index.js +61 -0
- package/dist/compression/index.js.map +1 -0
- package/dist/console/buffer.d.ts +99 -0
- package/dist/console/buffer.d.ts.map +1 -0
- package/dist/console/buffer.js +169 -0
- package/dist/console/buffer.js.map +1 -0
- package/dist/console/index.d.ts +3 -0
- package/dist/console/index.d.ts.map +1 -0
- package/dist/console/index.js +16 -0
- package/dist/console/index.js.map +1 -0
- package/dist/console/types.d.ts +61 -0
- package/dist/console/types.d.ts.map +1 -0
- package/dist/console/types.js +11 -0
- package/dist/console/types.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/masking/body.d.ts +30 -0
- package/dist/masking/body.d.ts.map +1 -0
- package/dist/masking/body.js +33 -0
- package/dist/masking/body.js.map +1 -0
- package/dist/masking/headers.d.ts +16 -0
- package/dist/masking/headers.d.ts.map +1 -0
- package/dist/masking/headers.js +46 -0
- package/dist/masking/headers.js.map +1 -0
- package/dist/masking/index.d.ts +8 -0
- package/dist/masking/index.d.ts.map +1 -0
- package/dist/masking/index.js +11 -0
- package/dist/masking/index.js.map +1 -0
- package/dist/masking/inputs.d.ts +15 -0
- package/dist/masking/inputs.d.ts.map +1 -0
- package/dist/masking/inputs.js +36 -0
- package/dist/masking/inputs.js.map +1 -0
- package/dist/masking/regex.d.ts +96 -0
- package/dist/masking/regex.d.ts.map +1 -0
- package/dist/masking/regex.js +182 -0
- package/dist/masking/regex.js.map +1 -0
- package/dist/masking/selectors.d.ts +67 -0
- package/dist/masking/selectors.d.ts.map +1 -0
- package/dist/masking/selectors.js +137 -0
- package/dist/masking/selectors.js.map +1 -0
- package/dist/masking/text.d.ts +9 -0
- package/dist/masking/text.d.ts.map +1 -0
- package/dist/masking/text.js +15 -0
- package/dist/masking/text.js.map +1 -0
- package/dist/network/cdp.d.ts +54 -0
- package/dist/network/cdp.d.ts.map +1 -0
- package/dist/network/cdp.js +282 -0
- package/dist/network/cdp.js.map +1 -0
- package/dist/network/index.d.ts +4 -0
- package/dist/network/index.d.ts.map +1 -0
- package/dist/network/index.js +14 -0
- package/dist/network/index.js.map +1 -0
- package/dist/network/types.d.ts +133 -0
- package/dist/network/types.d.ts.map +1 -0
- package/dist/network/types.js +35 -0
- package/dist/network/types.js.map +1 -0
- package/dist/network/web-request.d.ts +76 -0
- package/dist/network/web-request.d.ts.map +1 -0
- package/dist/network/web-request.js +294 -0
- package/dist/network/web-request.js.map +1 -0
- package/dist/persistence/index.d.ts +3 -0
- package/dist/persistence/index.d.ts.map +1 -0
- package/dist/persistence/index.js +11 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/persistence/store.d.ts +18 -0
- package/dist/persistence/store.d.ts.map +1 -0
- package/dist/persistence/store.js +327 -0
- package/dist/persistence/store.js.map +1 -0
- package/dist/persistence/types.d.ts +76 -0
- package/dist/persistence/types.d.ts.map +1 -0
- package/dist/persistence/types.js +21 -0
- package/dist/persistence/types.js.map +1 -0
- package/dist/rrweb.d.ts +5 -0
- package/dist/rrweb.d.ts.map +1 -0
- package/dist/rrweb.js +13 -0
- package/dist/rrweb.js.map +1 -0
- package/dist/screenshot/base64.d.ts +8 -0
- package/dist/screenshot/base64.d.ts.map +1 -0
- package/dist/screenshot/base64.js +21 -0
- package/dist/screenshot/base64.js.map +1 -0
- package/dist/screenshot/cdp.d.ts +50 -0
- package/dist/screenshot/cdp.d.ts.map +1 -0
- package/dist/screenshot/cdp.js +65 -0
- package/dist/screenshot/cdp.js.map +1 -0
- package/dist/screenshot/index.d.ts +4 -0
- package/dist/screenshot/index.d.ts.map +1 -0
- package/dist/screenshot/index.js +10 -0
- package/dist/screenshot/index.js.map +1 -0
- package/dist/screenshot/tabs.d.ts +44 -0
- package/dist/screenshot/tabs.d.ts.map +1 -0
- package/dist/screenshot/tabs.js +63 -0
- package/dist/screenshot/tabs.js.map +1 -0
- package/dist/screenshot/types.d.ts +27 -0
- package/dist/screenshot/types.d.ts.map +1 -0
- package/dist/screenshot/types.js +18 -0
- package/dist/screenshot/types.js.map +1 -0
- package/dist/shadow-dom/index.d.ts +3 -0
- package/dist/shadow-dom/index.d.ts.map +1 -0
- package/dist/shadow-dom/index.js +8 -0
- package/dist/shadow-dom/index.js.map +1 -0
- package/dist/shadow-dom/traverse.d.ts +54 -0
- package/dist/shadow-dom/traverse.d.ts.map +1 -0
- package/dist/shadow-dom/traverse.js +209 -0
- package/dist/shadow-dom/traverse.js.map +1 -0
- package/dist/shadow-dom/types.d.ts +43 -0
- package/dist/shadow-dom/types.d.ts.map +1 -0
- package/dist/shadow-dom/types.js +25 -0
- package/dist/shadow-dom/types.js.map +1 -0
- package/dist/throttling/apply.d.ts +59 -0
- package/dist/throttling/apply.d.ts.map +1 -0
- package/dist/throttling/apply.js +101 -0
- package/dist/throttling/apply.js.map +1 -0
- package/dist/throttling/defaults.d.ts +60 -0
- package/dist/throttling/defaults.d.ts.map +1 -0
- package/dist/throttling/defaults.js +81 -0
- package/dist/throttling/defaults.js.map +1 -0
- package/dist/throttling/guards.d.ts +69 -0
- package/dist/throttling/guards.d.ts.map +1 -0
- package/dist/throttling/guards.js +212 -0
- package/dist/throttling/guards.js.map +1 -0
- package/dist/throttling/index.d.ts +5 -0
- package/dist/throttling/index.d.ts.map +1 -0
- package/dist/throttling/index.js +11 -0
- package/dist/throttling/index.js.map +1 -0
- 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"}
|