@corbado/observe 1.10.0 → 1.10.1
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/analysis/client.mjs +0 -10
- package/dist/analysis/config.mjs +1 -4
- package/dist/analysis/device.mjs +0 -79
- package/dist/analysis/low-events/grouped-input-tracker.mjs +2 -3
- package/dist/analysis/low-events/input-change-recorder.mjs +35 -12
- package/dist/analysis/low-events/input-tracker.mjs +0 -58
- package/dist/analysis/readers/network.mjs +5 -0
- package/dist/analysis/transports/fetch.mjs +16 -1
- package/dist/analysis/utils/operation-full.mjs +0 -1
- package/dist/analysis/version.mjs +1 -1
- package/dist/cdn/script.global.js +4 -4
- package/dist/index.d.mts +6 -28
- package/dist/index.d.ts +6 -28
- package/dist/index.js +4 -4
- package/dist/index.mjs +2 -2
- package/package.json +1 -1
- package/dist/analysis/readers/password-manager-dom.mjs +0 -112
package/dist/analysis/client.mjs
CHANGED
|
@@ -1628,16 +1628,6 @@ var CorbadoTracker = class _CorbadoTracker {
|
|
|
1628
1628
|
this.logger.error("Failed to flush queue keepalive", error);
|
|
1629
1629
|
}
|
|
1630
1630
|
}
|
|
1631
|
-
/**
|
|
1632
|
-
* Whether input trackers run the DOM password-manager scan (`pa-1`..`pa-6` lows): only an explicitly
|
|
1633
|
-
* set `fixedDataConfig.pmd` decides; without `fixedDataConfig` or with `pmd` omitted it always runs
|
|
1634
|
-
* (historical behaviour).
|
|
1635
|
-
*
|
|
1636
|
-
* @internal
|
|
1637
|
-
*/
|
|
1638
|
-
isPasswordManagerDomScanEnabled() {
|
|
1639
|
-
return this.fixedData?.pmdExplicit ? this.fixedData.pmd : true;
|
|
1640
|
-
}
|
|
1641
1631
|
/**
|
|
1642
1632
|
* Keepalive flush requested by a low-event tracker's `pagehide` teardown. Gated by the
|
|
1643
1633
|
* server-controlled trigger switch `tlf` (boot-snapshot, default true = historical behavior):
|
package/dist/analysis/config.mjs
CHANGED
|
@@ -183,13 +183,10 @@ function resolveFixedDataConfig(raw) {
|
|
|
183
183
|
return void 0;
|
|
184
184
|
}
|
|
185
185
|
const value = raw;
|
|
186
|
-
const pmd = value.pmd;
|
|
187
|
-
const pmdExplicit = typeof pmd === "boolean";
|
|
188
186
|
const crossOrigin = value.crossOriginSession;
|
|
189
187
|
const cookieDomain = crossOrigin && typeof crossOrigin === "object" && typeof crossOrigin.cookieDomain === "string" ? crossOrigin.cookieDomain : void 0;
|
|
190
188
|
return {
|
|
191
|
-
pmd:
|
|
192
|
-
pmdExplicit,
|
|
189
|
+
pmd: asBoolean(value.pmd, false),
|
|
193
190
|
privateMode: asBoolean(value.privateMode, true),
|
|
194
191
|
...cookieDomain !== void 0 && { crossOriginSession: { cookieDomain } }
|
|
195
192
|
};
|
package/dist/analysis/device.mjs
CHANGED
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
readConditionalMediationAvailable,
|
|
8
8
|
readJavaScriptHighEntropy,
|
|
9
9
|
readMaxTouchPoints,
|
|
10
|
-
readUserAgent,
|
|
11
10
|
readUserVerifyingPlatformAuthenticatorAvailable,
|
|
12
11
|
readWebdriver
|
|
13
12
|
} from "./readers/device.mjs";
|
|
@@ -515,84 +514,6 @@ var DeviceCollector = class {
|
|
|
515
514
|
this.logger.error("Failed to report device info timing", error);
|
|
516
515
|
}
|
|
517
516
|
}
|
|
518
|
-
/**
|
|
519
|
-
* Error situations:
|
|
520
|
-
* - navigator is not available: user agent is treated as empty, osName and browserName are "other"
|
|
521
|
-
* - navigator is available but userAgent is null or undefined: same as above
|
|
522
|
-
*/
|
|
523
|
-
static getOsAndBrowserInfo() {
|
|
524
|
-
return {
|
|
525
|
-
osName: this.getOsName(),
|
|
526
|
-
browserName: this.getBrowserName()
|
|
527
|
-
};
|
|
528
|
-
}
|
|
529
|
-
static getUserAgent() {
|
|
530
|
-
return readUserAgent({
|
|
531
|
-
key: "browser-api:device.user-agent",
|
|
532
|
-
title: "Browser and operating system",
|
|
533
|
-
accessNote: "navigator.userAgent",
|
|
534
|
-
group: "Device information",
|
|
535
|
-
origin: "observe-external",
|
|
536
|
-
fields: [
|
|
537
|
-
{
|
|
538
|
-
path: "result",
|
|
539
|
-
label: "Browser and operating system",
|
|
540
|
-
exposure: "class",
|
|
541
|
-
transform: {
|
|
542
|
-
classes: [
|
|
543
|
-
"iOS",
|
|
544
|
-
"Android",
|
|
545
|
-
"Windows",
|
|
546
|
-
"macOS",
|
|
547
|
-
"Linux",
|
|
548
|
-
"ChromeOS",
|
|
549
|
-
"Chrome",
|
|
550
|
-
"Firefox",
|
|
551
|
-
"Safari",
|
|
552
|
-
"Edge",
|
|
553
|
-
"Opera",
|
|
554
|
-
"IE",
|
|
555
|
-
"other"
|
|
556
|
-
]
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
]
|
|
560
|
-
});
|
|
561
|
-
}
|
|
562
|
-
static getOsName() {
|
|
563
|
-
const ua = this.getUserAgent();
|
|
564
|
-
if (ua.includes("iOS")) {
|
|
565
|
-
return "iOS";
|
|
566
|
-
} else if (ua.includes("Android")) {
|
|
567
|
-
return "Android";
|
|
568
|
-
} else if (ua.includes("Windows")) {
|
|
569
|
-
return "Windows";
|
|
570
|
-
} else if (ua.includes("Macintosh")) {
|
|
571
|
-
return "macOS";
|
|
572
|
-
} else if (ua.includes("Linux")) {
|
|
573
|
-
return "Linux";
|
|
574
|
-
} else if (ua.includes("ChromeOS")) {
|
|
575
|
-
return "ChromeOS";
|
|
576
|
-
}
|
|
577
|
-
return "other";
|
|
578
|
-
}
|
|
579
|
-
static getBrowserName() {
|
|
580
|
-
const ua = this.getUserAgent();
|
|
581
|
-
if (ua.includes("Chrome")) {
|
|
582
|
-
return "Chrome";
|
|
583
|
-
} else if (ua.includes("Firefox")) {
|
|
584
|
-
return "Firefox";
|
|
585
|
-
} else if (ua.includes("Safari")) {
|
|
586
|
-
return "Safari";
|
|
587
|
-
} else if (ua.includes("Edge")) {
|
|
588
|
-
return "Edge";
|
|
589
|
-
} else if (ua.includes("Opera")) {
|
|
590
|
-
return "Opera";
|
|
591
|
-
} else if (ua.includes("IE")) {
|
|
592
|
-
return "IE";
|
|
593
|
-
}
|
|
594
|
-
return "other";
|
|
595
|
-
}
|
|
596
517
|
getClientEnvHandle() {
|
|
597
518
|
const existingClientEnvHandle = this.storage.getItem("cbo_client_env_handle");
|
|
598
519
|
if (existingClientEnvHandle) {
|
|
@@ -99,7 +99,7 @@ var LowEventGroupedInputTracker = class {
|
|
|
99
99
|
this.composing ||= composing;
|
|
100
100
|
if (this.changeTimer !== null) return;
|
|
101
101
|
this.changeTime = Date.now();
|
|
102
|
-
this.
|
|
102
|
+
this.changes.observe();
|
|
103
103
|
this.changeTimer = setTimeout(() => this.safe(() => this.flushChanges()), 0);
|
|
104
104
|
},
|
|
105
105
|
focus: (relatedTarget) => {
|
|
@@ -174,7 +174,6 @@ var LowEventGroupedInputTracker = class {
|
|
|
174
174
|
listeners = [];
|
|
175
175
|
changeTimer = null;
|
|
176
176
|
changeTime = 0;
|
|
177
|
-
changeSeq;
|
|
178
177
|
composing = false;
|
|
179
178
|
destroyed = false;
|
|
180
179
|
contains(target) {
|
|
@@ -214,7 +213,7 @@ var LowEventGroupedInputTracker = class {
|
|
|
214
213
|
flushChanges() {
|
|
215
214
|
if (this.changeTimer === null) return;
|
|
216
215
|
this.cancelChange();
|
|
217
|
-
if (!this.paste.pending) this.changes.record(this.length(), this.changeTime, this.composing
|
|
216
|
+
if (!this.paste.pending) this.changes.record(this.length(), this.changeTime, this.composing);
|
|
218
217
|
this.composing = false;
|
|
219
218
|
}
|
|
220
219
|
emit(lowType) {
|
|
@@ -18,9 +18,28 @@ var InputChangeRecorder = class {
|
|
|
18
18
|
autofillTimestamps = [];
|
|
19
19
|
autofillStreak = null;
|
|
20
20
|
idleTimer = null;
|
|
21
|
+
/** Order of the pending run of changes: reserved when it starts, taken by the first event it sends. */
|
|
22
|
+
runSeq;
|
|
21
23
|
markInputObserved() {
|
|
22
24
|
this.prefillSettled = true;
|
|
23
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Observation of a change begins: reserves the capture order of a new run of changes. One number per
|
|
28
|
+
* run, not per change: every reserved number is sent, so the gaps between sent events never count
|
|
29
|
+
* keystrokes (which would reveal the length of the typed value).
|
|
30
|
+
*/
|
|
31
|
+
observe() {
|
|
32
|
+
if (this.runSeq !== void 0 || this.inputBatch || this.autofillTimestamps.length > 0 || this.autofillStreak) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
this.runSeq = this.reserveCaptureSeq?.();
|
|
36
|
+
}
|
|
37
|
+
/** The run's reserved order for its first event; later events of the run reserve when they are created. */
|
|
38
|
+
takeSeq() {
|
|
39
|
+
const seq = this.runSeq;
|
|
40
|
+
this.runSeq = void 0;
|
|
41
|
+
return seq ?? this.reserveCaptureSeq?.();
|
|
42
|
+
}
|
|
24
43
|
capturePrefill(length, newCapture = false) {
|
|
25
44
|
if (newCapture) this.prefillSettled = false;
|
|
26
45
|
if (this.prefillSettled) return;
|
|
@@ -50,17 +69,17 @@ var InputChangeRecorder = class {
|
|
|
50
69
|
}
|
|
51
70
|
}, INPUT_IDLE_MS);
|
|
52
71
|
}
|
|
53
|
-
extendInputBatch(timestamp, effect = this.currentEffect
|
|
72
|
+
extendInputBatch(timestamp, effect = this.currentEffect) {
|
|
54
73
|
const batch = this.inputBatch;
|
|
55
74
|
if (!batch) {
|
|
56
|
-
this.inputBatch = { firstTimestamp: timestamp, lastTimestamp: timestamp, effect, captureSeq };
|
|
75
|
+
this.inputBatch = { firstTimestamp: timestamp, lastTimestamp: timestamp, effect, captureSeq: this.takeSeq() };
|
|
57
76
|
return;
|
|
58
77
|
}
|
|
59
78
|
batch.lastTimestamp = timestamp;
|
|
60
79
|
}
|
|
61
80
|
drainAutofillRingToBatch() {
|
|
62
81
|
for (const ts of this.autofillTimestamps) {
|
|
63
|
-
this.extendInputBatch(ts
|
|
82
|
+
this.extendInputBatch(ts, this.ringEffect);
|
|
64
83
|
}
|
|
65
84
|
this.autofillTimestamps.length = 0;
|
|
66
85
|
}
|
|
@@ -101,7 +120,7 @@ var InputChangeRecorder = class {
|
|
|
101
120
|
let minInterval = Infinity;
|
|
102
121
|
let maxInterval = -Infinity;
|
|
103
122
|
for (let i = 1; i < ring.length; i++) {
|
|
104
|
-
const interval = ring[i]
|
|
123
|
+
const interval = ring[i] - ring[i - 1];
|
|
105
124
|
if (interval > AUTOFILL_FAST_INTERVAL_MS) {
|
|
106
125
|
return false;
|
|
107
126
|
}
|
|
@@ -114,7 +133,8 @@ var InputChangeRecorder = class {
|
|
|
114
133
|
}
|
|
115
134
|
return maxInterval - minInterval <= AUTOFILL_UNIFORM_SPREAD_MS;
|
|
116
135
|
}
|
|
117
|
-
record(newLength, timestamp = Date.now(), composing = false
|
|
136
|
+
record(newLength, timestamp = Date.now(), composing = false) {
|
|
137
|
+
this.observe();
|
|
118
138
|
this.markInputObserved();
|
|
119
139
|
this.scheduleIdle();
|
|
120
140
|
const oldLength = this.previousLength;
|
|
@@ -123,6 +143,7 @@ var InputChangeRecorder = class {
|
|
|
123
143
|
this.previousLength = newLength;
|
|
124
144
|
if (newLength === 0 && oldLength > 0) {
|
|
125
145
|
this.flush();
|
|
146
|
+
const captureSeq = this.takeSeq();
|
|
126
147
|
this.pushLow({
|
|
127
148
|
...captureSeq === void 0 ? {} : { captureSeq },
|
|
128
149
|
lowType: "input-clear",
|
|
@@ -134,12 +155,13 @@ var InputChangeRecorder = class {
|
|
|
134
155
|
if (composing) {
|
|
135
156
|
this.flushAutofillStreak();
|
|
136
157
|
this.drainAutofillRingToBatch();
|
|
137
|
-
this.extendInputBatch(timestamp, this.currentEffect
|
|
158
|
+
this.extendInputBatch(timestamp, this.currentEffect);
|
|
138
159
|
return;
|
|
139
160
|
}
|
|
140
161
|
if (delta >= BIG_INPUT_DELTA_THRESHOLD) {
|
|
141
162
|
this.flushInputBatch();
|
|
142
163
|
this.flushAutofillStreak();
|
|
164
|
+
const captureSeq = this.takeSeq();
|
|
143
165
|
this.pushLow({
|
|
144
166
|
...captureSeq === void 0 ? {} : { captureSeq },
|
|
145
167
|
lowType: "big-input-add",
|
|
@@ -151,6 +173,7 @@ var InputChangeRecorder = class {
|
|
|
151
173
|
if (delta <= -BIG_INPUT_DELTA_THRESHOLD) {
|
|
152
174
|
this.flushInputBatch();
|
|
153
175
|
this.flushAutofillStreak();
|
|
176
|
+
const captureSeq = this.takeSeq();
|
|
154
177
|
this.pushLow({
|
|
155
178
|
...captureSeq === void 0 ? {} : { captureSeq },
|
|
156
179
|
lowType: "big-input-rem",
|
|
@@ -169,15 +192,15 @@ var InputChangeRecorder = class {
|
|
|
169
192
|
}
|
|
170
193
|
if (delta !== 1) {
|
|
171
194
|
this.drainAutofillRingToBatch();
|
|
172
|
-
this.extendInputBatch(timestamp, this.currentEffect
|
|
195
|
+
this.extendInputBatch(timestamp, this.currentEffect);
|
|
173
196
|
return;
|
|
174
197
|
}
|
|
175
198
|
const ring = this.autofillTimestamps;
|
|
176
199
|
if (ring.length === 0) this.ringEffect = this.currentEffect;
|
|
177
|
-
ring.push(
|
|
200
|
+
ring.push(timestamp);
|
|
178
201
|
if (ring.length > AUTOFILL_STREAK_LENGTH) {
|
|
179
202
|
const graduated = ring.shift();
|
|
180
|
-
this.extendInputBatch(graduated
|
|
203
|
+
this.extendInputBatch(graduated, this.ringEffect);
|
|
181
204
|
this.ringEffect = "modify";
|
|
182
205
|
}
|
|
183
206
|
if (!this.detectAutofillStreak()) {
|
|
@@ -188,9 +211,9 @@ var InputChangeRecorder = class {
|
|
|
188
211
|
ring.length = 0;
|
|
189
212
|
this.flushInputBatch();
|
|
190
213
|
this.autofillStreak = {
|
|
191
|
-
firstTimestamp: streakStart
|
|
192
|
-
captureSeq:
|
|
193
|
-
lastTimestamp: streakLast
|
|
214
|
+
firstTimestamp: streakStart,
|
|
215
|
+
captureSeq: this.takeSeq(),
|
|
216
|
+
lastTimestamp: streakLast,
|
|
194
217
|
effect: this.ringEffect
|
|
195
218
|
};
|
|
196
219
|
}
|
|
@@ -3,9 +3,6 @@ import { InputChangeRecorder } from "./input-change-recorder.mjs";
|
|
|
3
3
|
import { InputPasteObserver } from "../readers/input-paste.mjs";
|
|
4
4
|
import { observeInputField, readFocusedField, readInputContentLength } from "../readers/input.mjs";
|
|
5
5
|
import { listenWindow } from "../readers/page.mjs";
|
|
6
|
-
import { readPasswordManagerDomSignals } from "../readers/password-manager-dom.mjs";
|
|
7
|
-
var MOUNT_PROBE_DELAY_MS = 500;
|
|
8
|
-
var FOCUS_PROBE_DELAY_MS = 250;
|
|
9
6
|
function fieldContentLength(field) {
|
|
10
7
|
return readInputContentLength(
|
|
11
8
|
{
|
|
@@ -85,10 +82,6 @@ var LowEventInputTracker = class {
|
|
|
85
82
|
removePageHide;
|
|
86
83
|
changes;
|
|
87
84
|
pasteObserver;
|
|
88
|
-
emittedSignals = /* @__PURE__ */ new Set();
|
|
89
|
-
firstFocusHandled = false;
|
|
90
|
-
mountProbeTimer = null;
|
|
91
|
-
focusProbeTimer = null;
|
|
92
85
|
destroyed = false;
|
|
93
86
|
destroy() {
|
|
94
87
|
if (this.destroyed) {
|
|
@@ -96,14 +89,6 @@ var LowEventInputTracker = class {
|
|
|
96
89
|
}
|
|
97
90
|
this.destroyed = true;
|
|
98
91
|
try {
|
|
99
|
-
if (this.mountProbeTimer !== null) {
|
|
100
|
-
clearTimeout(this.mountProbeTimer);
|
|
101
|
-
this.mountProbeTimer = null;
|
|
102
|
-
}
|
|
103
|
-
if (this.focusProbeTimer !== null) {
|
|
104
|
-
clearTimeout(this.focusProbeTimer);
|
|
105
|
-
this.focusProbeTimer = null;
|
|
106
|
-
}
|
|
107
92
|
this.changes.flush();
|
|
108
93
|
this.unregisterInputs?.();
|
|
109
94
|
this.pasteObserver.destroy();
|
|
@@ -204,9 +189,6 @@ var LowEventInputTracker = class {
|
|
|
204
189
|
this.handleFocus();
|
|
205
190
|
}
|
|
206
191
|
}
|
|
207
|
-
if (typeof window !== "undefined") {
|
|
208
|
-
this.mountProbeTimer = setTimeout(() => this.runEnvProbe(), MOUNT_PROBE_DELAY_MS);
|
|
209
|
-
}
|
|
210
192
|
}
|
|
211
193
|
detach() {
|
|
212
194
|
this.removeFieldListeners?.();
|
|
@@ -217,45 +199,6 @@ var LowEventInputTracker = class {
|
|
|
217
199
|
pushLow = (low) => {
|
|
218
200
|
this.sink.enqueueLowEvent(low);
|
|
219
201
|
};
|
|
220
|
-
runEnvProbe() {
|
|
221
|
-
try {
|
|
222
|
-
if (typeof __CBO_DATA_PMD__ === "boolean" ? __CBO_DATA_PMD__ : this.sink.passwordManagerDomScan?.() !== false) {
|
|
223
|
-
const matches = readPasswordManagerDomSignals({
|
|
224
|
-
key: "dom:password-managers.dom-signals",
|
|
225
|
-
title: "Password manager traces in the page",
|
|
226
|
-
accessNote: "DOM markers that password manager extensions insert (attributes, elements, styles)",
|
|
227
|
-
group: "Password manager detection",
|
|
228
|
-
origin: "observe-external",
|
|
229
|
-
fields: [
|
|
230
|
-
{
|
|
231
|
-
path: "signals[]",
|
|
232
|
-
label: "Password manager traces found",
|
|
233
|
-
exposure: "enum",
|
|
234
|
-
transform: { values: ["pa-1", "pa-2", "pa-3", "pa-4", "pa-5", "pa-6"] }
|
|
235
|
-
}
|
|
236
|
-
],
|
|
237
|
-
dataConfig: "pmd"
|
|
238
|
-
});
|
|
239
|
-
const now = Date.now();
|
|
240
|
-
for (const eventType of matches) {
|
|
241
|
-
if (this.emittedSignals.has(eventType)) {
|
|
242
|
-
continue;
|
|
243
|
-
}
|
|
244
|
-
this.emittedSignals.add(eventType);
|
|
245
|
-
this.pushLow({ lowType: eventType, ts: now });
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
} catch (error) {
|
|
249
|
-
this.logger.error("Failed to run input env probe", error);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
scheduleFocusProbe() {
|
|
253
|
-
if (this.firstFocusHandled) {
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
this.firstFocusHandled = true;
|
|
257
|
-
this.focusProbeTimer = setTimeout(() => this.runEnvProbe(), FOCUS_PROBE_DELAY_MS);
|
|
258
|
-
}
|
|
259
202
|
capturePrefill(newCapture = false) {
|
|
260
203
|
if (this.destroyed) return;
|
|
261
204
|
this.flushPending();
|
|
@@ -270,7 +213,6 @@ var LowEventInputTracker = class {
|
|
|
270
213
|
this.pushLow({ lowType: eventType, ts: Date.now() });
|
|
271
214
|
}
|
|
272
215
|
handleFocus() {
|
|
273
|
-
this.scheduleFocusProbe();
|
|
274
216
|
this.enqueueNonInputEvent("focus");
|
|
275
217
|
}
|
|
276
218
|
handleBlur() {
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
// src/readers/network.ts
|
|
2
|
+
var declaredByBrowser = /* @__PURE__ */ new Set();
|
|
3
|
+
function declareBrowserRequestData(meta) {
|
|
4
|
+
declaredByBrowser.add(meta);
|
|
5
|
+
}
|
|
2
6
|
function sendFetch(_meta, url, init) {
|
|
3
7
|
return fetch(url, init);
|
|
4
8
|
}
|
|
@@ -10,5 +14,6 @@ function beaconSender(_meta) {
|
|
|
10
14
|
}
|
|
11
15
|
export {
|
|
12
16
|
beaconSender,
|
|
17
|
+
declareBrowserRequestData,
|
|
13
18
|
sendFetch
|
|
14
19
|
};
|
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
// src/transports/fetch.ts
|
|
2
2
|
import { parseReliabilityConfig } from "../config.mjs";
|
|
3
|
-
import { beaconSender, sendFetch } from "../readers/network.mjs";
|
|
3
|
+
import { beaconSender, declareBrowserRequestData, sendFetch } from "../readers/network.mjs";
|
|
4
4
|
var MAX_KEEPALIVE_BODY_BYTES = 6e4;
|
|
5
5
|
var FETCH_TIMEOUT_MS = 6e4;
|
|
6
6
|
var FetchTransport = class {
|
|
7
7
|
constructor(options) {
|
|
8
8
|
this.options = options;
|
|
9
|
+
declareBrowserRequestData({
|
|
10
|
+
key: "browser-api:device.user-agent",
|
|
11
|
+
title: "Browser and operating system",
|
|
12
|
+
accessNote: "User-Agent header the browser sends with every request to the Observe ingestion API (the SDK does not read it); Corbado stores it and derives browser and operating system name and version",
|
|
13
|
+
group: "Device information",
|
|
14
|
+
origin: "observe-external",
|
|
15
|
+
fields: [
|
|
16
|
+
{
|
|
17
|
+
path: "request.header.user-agent",
|
|
18
|
+
label: "Browser and operating system identifier",
|
|
19
|
+
exposure: "raw",
|
|
20
|
+
transform: { note: "full User-Agent string, sent by the browser" }
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
});
|
|
9
24
|
}
|
|
10
25
|
/**
|
|
11
26
|
* Error situations:
|
|
@@ -30,7 +30,6 @@ var OperationFull = class {
|
|
|
30
30
|
this.captureSessionId
|
|
31
31
|
),
|
|
32
32
|
flushKeepalive: () => this.tracker.lowEventFlushKeepalive(),
|
|
33
|
-
passwordManagerDomScan: () => this.tracker.isPasswordManagerDomScanEnabled(),
|
|
34
33
|
registerInputs: (fields, flush) => this.tracker.getWindowObserver().registerInputs(
|
|
35
34
|
fields,
|
|
36
35
|
() => ({
|