@corbado/observe 0.14.0 → 0.15.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/index.d.mts CHANGED
@@ -148,6 +148,12 @@ type AuthDecisionFinished = {
148
148
  explicitDecisionValue?: string;
149
149
  };
150
150
  type StepOptions = {
151
+ /** Optional initiator override. Passkey ceremonies infer it from the operation/step spec when omitted. */
152
+ initiator?: LowEventInitiator;
153
+ /** @internal Session captured with the operation start; never sent as event metadata. */
154
+ captureSessionId?: string;
155
+ /** @internal Capture anchor supplied by operation helpers. */
156
+ subflowStartEventId?: string;
151
157
  /** @deprecated Use tracker.setUser() within the active flow instead. */
152
158
  userReference?: UserReference;
153
159
  explicitTimestamp?: number;
@@ -178,7 +184,22 @@ interface CustomEvent extends BaseEvent {
178
184
  data?: Record<string, unknown>;
179
185
  }
180
186
  type Event = PredefinedEvent | CustomEvent;
187
+ type LowEventSourceKind = "input" | "input-group" | "ceremony" | "window";
188
+ type LowEventFieldRole = "password" | "identifier" | "otp" | "data";
189
+ type LowEventInitiator = `input-${LowEventFieldRole}` | "passkey-button" | "automatic" | "unknown";
190
+ type LowEventInputEffect = "fill" | "modify" | "clear";
181
191
  interface LowEvent {
192
+ /** Per-page uint32 observation order; reserved before batching and retained on retry. */
193
+ captureSeq?: number;
194
+ captureVersion?: number;
195
+ pageId?: string;
196
+ initiator?: LowEventInitiator;
197
+ inputEffect?: LowEventInputEffect;
198
+ /** Immutable delivery identity; absent on legacy records. */
199
+ id?: string;
200
+ subflowStartEventId?: string;
201
+ sourceKind?: LowEventSourceKind;
202
+ fieldRole?: LowEventFieldRole;
182
203
  lowType: string;
183
204
  ts: number;
184
205
  durationMs?: number;
@@ -233,6 +254,10 @@ interface EventBatchMeta {
233
254
  configVersion?: string;
234
255
  }
235
256
  interface EventMeta {
257
+ initiator?: LowEventInitiator;
258
+ captureVersion?: number;
259
+ pageId?: string;
260
+ subflowStartEventId?: string;
236
261
  trackingSourcePath: string;
237
262
  /**
238
263
  * Per-tab id (uuidv7, `sessionStorage`-scoped) of the tab that CREATED this event, stamped at
@@ -242,6 +267,8 @@ interface EventMeta {
242
267
  tabId?: string;
243
268
  }
244
269
  interface EventBatch {
270
+ /** Request durable acceptance for replayable lows. */
271
+ deliveryAck?: boolean;
245
272
  sessionId: string;
246
273
  events: Event[];
247
274
  sdk: SdkInfo;
@@ -316,30 +343,24 @@ type ObserveSdkConfigSnapshot = {
316
343
  readonly aap: string;
317
344
  };
318
345
  /**
319
- * SDK reliability configuration returned by the events endpoint (opt-in via the
320
- * `X-Corbado-Observe-Config` header). Mirrors the server `observeEventCreateRes` schema.
321
- * All delivery-reliability features default OFF until the server returns config.
322
- *
323
- * @remarks
324
- * Boot-snapshot model: the config resolved at construction (from the localStorage cache) is the
325
- * config for the entire page load. A config received from the server during the load is only
326
- * cached for the NEXT load, never applied live — this keeps session identity, seq source and
327
- * outbox mode coherent within one load.
346
+ * Resolved browser SDK reliability policy. Init overrides take precedence over server policy and defaults.
347
+ * Session continuity and durable outbox can activate on any refresh and stay enabled for the rest of the document.
328
348
  */
329
349
  interface SdkReliabilityConfig {
330
350
  /**
331
- * Content-derived version (hash) assigned by the server. Echoed in the config request header so
332
- * the server can answer 204 when nothing changed, and stamped into every batch's
333
- * `meta.configVersion`. Empty string for the built-in defaults (nothing cached yet).
351
+ * Content-derived version assigned by the server, or a non-empty identifier for injected config.
352
+ * Stamped into every batch's meta.configVersion. Empty when neither the server nor init overrides supply a version.
334
353
  */
335
354
  version: string;
336
355
  /** How often the SDK flushes its event queue, in milliseconds. */
337
356
  flushIntervalMs: number;
338
- /** Persist queued events to a durable outbox so they survive reloads, redirects and context switches. */
357
+ /** Persist queued events across reloads, redirects and context switches. Can activate on any refresh; deactivation takes effect on the next initialization. */
339
358
  durableOutbox: boolean;
359
+ /** Persist lows in a separate bounded outbox; defaults to disabled for older configs. */
360
+ durableLowOutbox?: boolean;
340
361
  /** Use keepalive/sendBeacon transport for flushes triggered during page unload. */
341
362
  beaconKeepalive: boolean;
342
- /** Maintain session continuity across reloads/tabs by persisting the session id in localStorage. */
363
+ /** Maintain session continuity across reloads/tabs. Can activate on any refresh; deactivation takes effect on the next initialization. */
343
364
  sessionContinuity: boolean;
344
365
  /**
345
366
  * Inactivity threshold for continuity sessions, in milliseconds. When more time than this has
@@ -373,8 +394,8 @@ interface SdkReliabilityConfig {
373
394
  tlf: boolean;
374
395
  /**
375
396
  * Master switch for the diagnostic telemetry stream. When true the SDK sends buffered telemetry
376
- * entries piggybacked on normal event requests; when false it collects and sends nothing. Defaults
377
- * to true (telemetry is on out of the box) and can be turned off server-side without a redeploy.
397
+ * entries piggybacked on normal event requests. When false it stops collection, but already buffered
398
+ * entries can still be sent. Defaults to true and can be turned off server-side without a redeploy.
378
399
  */
379
400
  telemetry: boolean;
380
401
  /**
@@ -417,6 +438,10 @@ interface SdkReliabilityConfig {
417
438
  /** Retry configuration for failed event flushes. */
418
439
  retry: SdkRetryConfig;
419
440
  }
441
+ /** Optional init overrides; omitted fields (including nested retry fields) inherit server policy or defaults. */
442
+ type SdkReliabilityConfigOverrides = Partial<Omit<SdkReliabilityConfig, "retry">> & {
443
+ retry?: Partial<SdkRetryConfig>;
444
+ };
420
445
 
421
446
  /** Sink that escalates a diagnostic message to the telemetry stream. */
422
447
  type TelemetrySink = (level: TelemetryLevel, message: string) => void;
@@ -440,6 +465,41 @@ interface CreateLoggerOptions {
440
465
  }
441
466
  declare function createLogger(options: CreateLoggerOptions): Logger;
442
467
 
468
+ type WindowCaptureContext = Pick<LowEvent, "subflowStartEventId" | "fieldRole" | "initiator"> & {
469
+ sessionId?: string;
470
+ };
471
+ /** One passive observer per tracker. Field/ceremony collectors register context, not DOM listeners. */
472
+ declare class SharedWindowObserver {
473
+ private logger;
474
+ private enqueue;
475
+ private flushKeepalive;
476
+ private inputs;
477
+ private ceremonies;
478
+ private removers;
479
+ private lastBlur?;
480
+ private bracket?;
481
+ private unrelatedPointerAt;
482
+ private destroyed;
483
+ private viewportContext;
484
+ private resize;
485
+ private scroll;
486
+ constructor(logger: Logger, enqueue: (low: LowEvent, sessionId?: string) => void, flushKeepalive: () => void);
487
+ registerInputs(fields: readonly HTMLInputElement[], context: () => WindowCaptureContext, flush: () => void): () => void;
488
+ beginCeremony(context: WindowCaptureContext): {
489
+ settle: (tailMs: number) => void;
490
+ destroy: () => void;
491
+ };
492
+ private context;
493
+ private findInput;
494
+ /** Flush all registered input batches before a high-level lifecycle boundary. */
495
+ flushInputs(): void;
496
+ private emit;
497
+ private listen;
498
+ private extendViewport;
499
+ private observeNavigation;
500
+ destroy(): void;
501
+ }
502
+
443
503
  /**
444
504
  * Where low events go. `flushKeepalive` is requested on `pagehide` teardown so lows batched after
445
505
  * the queue's own lifecycle flush still get out; operations wire it to the client's
@@ -447,49 +507,27 @@ declare function createLogger(options: CreateLoggerOptions): Logger;
447
507
  * (default true = historical behavior, can be disabled remotely).
448
508
  */
449
509
  interface LowEventSink {
510
+ reserveCaptureSeq?(): number;
450
511
  enqueueLowEvent(low: LowEvent): void;
451
512
  flushKeepalive(): void;
513
+ registerInputs?(fields: readonly HTMLInputElement[], flush: () => void): () => void;
514
+ beginCeremony?(initiator?: LowEventInitiator): {
515
+ settle(tailMs: number): void;
516
+ destroy(): void;
517
+ };
452
518
  }
453
519
 
454
- /**
455
- * Collects window-scoped "low" events around a WebAuthn ceremony: window focus/blur, document
456
- * visibility changes and visualviewport resize/scroll (batched). The listener set mirrors
457
- * connect-react's `installLowEventWindowListeners`; the event names match
458
- * {@link LowEventInputTracker}'s vocabulary.
459
- *
460
- * Unlike {@link LowEventInputTracker} (anchored to an input field, active for the owning
461
- * operation's lifetime), this tracker is armed only for the ceremony window: the owning operation
462
- * arms it on `ceremony.start()` and schedules disarming shortly after the ceremony settles, so
463
- * signals from the picker closing (focus return, dismiss animations) are still captured.
464
- *
465
- * Never triggers a flush — low events ride along on the queue's existing flush triggers.
466
- */
520
+ /** Ceremony context lease on the shared observer. Never installs its own window listeners. */
467
521
  declare class LowEventWindowTracker {
468
522
  private logger;
469
523
  private sink;
470
- private armed;
524
+ private lease?;
471
525
  private destroyed;
472
- private disarmTimer;
473
- private resizeBatcher;
474
- private scrollBatcher;
475
- private boundHandlers;
476
526
  constructor(logger: Logger, sink: LowEventSink);
477
- /** Start listening. Idempotent; cancels a pending scheduled disarm (ceremony retry). */
478
- arm(): void;
479
- /**
480
- * Disarm after `delayMs`. The tail keeps the listeners alive briefly after the ceremony settles:
481
- * focus return and picker dismiss animations land after the WebAuthn promise resolves/rejects.
482
- */
527
+ arm(initiator?: LowEventInitiator, conditional?: boolean): void;
483
528
  scheduleDisarm(delayMs: number): void;
484
- /** Stop listening and flush the viewport batchers into the queue. Idempotent. */
485
529
  disarm(): void;
486
- /** Disarm and refuse any further arming; for the owning operation's destroy(). */
487
530
  destroy(): void;
488
- private cancelScheduledDisarm;
489
- private pushLow;
490
- private handleVisibilityChange;
491
- private flushBatchers;
492
- private wrapHandler;
493
531
  }
494
532
 
495
533
  /**
@@ -507,6 +545,17 @@ type StepHelper<TStart = {}, TFinished = {}, TTypedError = never> = {
507
545
  declare abstract class OperationFull {
508
546
  private tracker;
509
547
  private operationName;
548
+ private startReference?;
549
+ private captureSpecType?;
550
+ private captureSessionId?;
551
+ private readonly lowFlushers;
552
+ private readonly lowPrefillCapturers;
553
+ protected lowEventSink(sourceKind: LowEventSourceKind, fieldRole?: LowEventFieldRole): LowEventSink;
554
+ protected createLowCollector<T extends {
555
+ capturePrefill(newCapture?: boolean): void;
556
+ }>(create: () => T): T | undefined;
557
+ protected registerLowFlusher(flush: () => void): void;
558
+ private captureOptions;
510
559
  constructor(tracker: CorbadoTracker, operationName: SubflowType);
511
560
  /**
512
561
  * Emits an additional subflow_started; construction already emits the initial start.
@@ -514,6 +563,13 @@ declare abstract class OperationFull {
514
563
  * plus free-form extras; see SubflowTrigger for programmatic interaction suppression.
515
564
  */
516
565
  subflowStart(data: any, options?: StepOptions): void;
566
+ /**
567
+ * Capture values initialized by the application after constructing this operation, without
568
+ * dispatching DOM input events. Call immediately after initialization, before user editing.
569
+ * Each field/group emits at most one prefill per subflow start; values are never recorded.
570
+ */
571
+ capturePrefill(): void;
572
+ private captureInputPrefills;
517
573
  /**
518
574
  * @deprecated `subflow_trigger` will be removed in the next major version.
519
575
  */
@@ -596,13 +652,22 @@ type EmailOTPOperationPostResponseStart = {
596
652
  explicitSpecType?: EmailOTPOperationSpecType;
597
653
  };
598
654
  type EmailOTPOperationConfig = {
655
+ /** Email domain only, no full address. */
656
+ emailDomain?: string;
657
+ /** One real input, or an ordered group representing one OTP. */
658
+ inputHtmlField?: HTMLInputElement;
659
+ inputHtmlFields?: HTMLInputElement[];
599
660
  explicitSpecType?: EmailOTPOperationSpecType;
600
661
  };
601
662
  declare class EmailOtpOperationFull extends OperationFull {
663
+ private lowEventTracker?;
602
664
  readonly send: StepHelper<EmailOTPOperationSendOTPStart>;
603
665
  readonly postResponse: StepHelper<EmailOTPOperationPostResponseStart>;
604
666
  readonly resend: StepHelper;
605
667
  constructor(tracker: CorbadoTracker, config?: EmailOTPOperationConfig);
668
+ /** Rebind the ordered OTP group without starting a new subflow. An empty list detaches it. */
669
+ setInputFields(fields: readonly HTMLInputElement[]): void;
670
+ destroy(): void;
606
671
  }
607
672
 
608
673
  type SmsOTPOperationSpecType = "sms-otp-login" | "sms-otp-enrollment";
@@ -610,12 +675,19 @@ type SmsOTPOperationPostResponseStart = {
610
675
  explicitSpecType?: SmsOTPOperationSpecType;
611
676
  };
612
677
  type SmsOTPOperationConfig = {
678
+ /** One real input, or an ordered group representing one OTP. */
679
+ inputHtmlField?: HTMLInputElement;
680
+ inputHtmlFields?: HTMLInputElement[];
613
681
  explicitSpecType?: SmsOTPOperationSpecType;
614
682
  };
615
683
  declare class SmsOtpOperationFull extends OperationFull {
684
+ private lowEventTracker?;
616
685
  readonly postResponse: StepHelper<SmsOTPOperationPostResponseStart>;
617
686
  readonly resend: StepHelper;
618
687
  constructor(tracker: CorbadoTracker, config?: SmsOTPOperationConfig);
688
+ /** Rebind the ordered OTP group without starting a new subflow. An empty list detaches it. */
689
+ setInputFields(fields: readonly HTMLInputElement[]): void;
690
+ destroy(): void;
619
691
  }
620
692
 
621
693
  type EmailLinkOperationSpecType = "email-link-login" | "email-link-enrollment";
@@ -725,8 +797,7 @@ type PasswordLoginConfig = {
725
797
  /** The password input field. When set, low-event input tracking is attached to it. */
726
798
  inputHtmlField?: HTMLInputElement;
727
799
  /**
728
- * The identifier (e.g. email) input field. Accepted but not tracked yet — low-event
729
- * tracking for a second field lands together with per-field attribution.
800
+ * The identifier (e.g. email) input field. Tracked separately from the password field.
730
801
  */
731
802
  identifierInputHtmlField?: HTMLInputElement;
732
803
  };
@@ -744,6 +815,7 @@ declare class PasswordLoginOperationFull extends OperationFull {
744
815
  postResponse: StepHelper;
745
816
  };
746
817
  private lowEventTracker?;
818
+ private identifierLowEventTracker?;
747
819
  constructor(tracker: CorbadoTracker, config?: PasswordLoginConfig);
748
820
  /**
749
821
  * @deprecated `subflow_trigger` is not supported for password-login and will be removed in the
@@ -903,6 +975,10 @@ interface TrackerOptions {
903
975
  projectId: string;
904
976
  apiBaseUrl: string;
905
977
  apiEventPath?: string;
978
+ /** Per-field overrides over server config and defaults. A complete policy disables remote fetching. */
979
+ sdkConfig?: SdkReliabilityConfigOverrides;
980
+ /** Config endpoint override for integrations that proxy Observe under a different path. */
981
+ apiConfigPath?: string;
906
982
  storage?: "cookie" | "local";
907
983
  cookieDomain?: string;
908
984
  debug?: boolean;
@@ -942,12 +1018,10 @@ declare class CorbadoTracker {
942
1018
  private persistentStorage;
943
1019
  /** Seq/continuity Web Lock name; project-scoped together with the storage keys it guards. */
944
1020
  private readonly seqLockName;
945
- /**
946
- * Reliability config for this load. A boot with a cached server config is a snapshot (immutable
947
- * mid-load); a boot on the built-in defaults upgrades once to the first server-returned config
948
- * (see {@link handleConfig}).
949
- */
1021
+ /** Current resolved policy. Continuity and persistence stay enabled once activated within a document. */
950
1022
  private config;
1023
+ private readonly configManager?;
1024
+ private readonly configOverrides;
951
1025
  private deviceInfoManager;
952
1026
  private deviceCollector;
953
1027
  /**
@@ -969,14 +1043,11 @@ declare class CorbadoTracker {
969
1043
  private telemetryReady;
970
1044
  private readonly reportedTelemetryKeys;
971
1045
  private pendingSelfTelemetry;
1046
+ private windowObserver?;
1047
+ /** @internal Shared passive page observation and per-operation context registration. */
1048
+ getWindowObserver(): SharedWindowObserver;
972
1049
  constructor(options: TrackerOptions);
973
- /**
974
- * Cache fresh server config as last-known so the next page load boots with it. When this load
975
- * booted on the built-in defaults (no cached config), the config is additionally applied live:
976
- * every field is read at use time, and a mid-load `sessionContinuity` flip is safe because
977
- * `nextSeq` adopts the in-memory session id into the empty continuity store instead of minting
978
- * (no session split). A load that booted on a cached config keeps its snapshot untouched.
979
- */
1050
+ /** Apply init overrides on every refresh; continuity and persistence only activate within a document. */
980
1051
  private handleConfig;
981
1052
  /**
982
1053
  * Returns the logger used by this tracker.
@@ -1009,7 +1080,7 @@ declare class CorbadoTracker {
1009
1080
  /** Returns a copy of the currently active experiment assignments. */
1010
1081
  getExperiments(): Record<string, string>;
1011
1082
  /**
1012
- * Returns the public SDK configuration for this page load.
1083
+ * Returns the currently active public SDK configuration, including live updates.
1013
1084
  *
1014
1085
  * @returns A frozen snapshot, created fresh on every call.
1015
1086
  */
@@ -1028,7 +1099,7 @@ declare class CorbadoTracker {
1028
1099
  /**
1029
1100
  * Resolve the session id from localStorage so it survives reloads and is shared across tabs of the
1030
1101
  * same browser. Rotates after `config.sessionInactivityMs` of inactivity (server-controlled,
1031
- * boot-snapshot like the rest of the config), resetting the seq counter.
1102
+ * evaluated at boot), resetting the seq counter.
1032
1103
  *
1033
1104
  * Inactivity rotation happens at boot only, here and on the per-tab path {@link resolveSessionId}
1034
1105
  * takes without continuity. Boot is chosen on an assumption, not a guarantee: that a load
@@ -1057,12 +1128,11 @@ declare class CorbadoTracker {
1057
1128
  * Persist the per-tab record and remember when, sharing the throttle bookkeeping with the
1058
1129
  * continuity record — a load resolves its session on one path or the other, never both.
1059
1130
  *
1060
- * Only a load that received a server config stamps the window; any other carries forward what the
1061
- * tab already knows. So a defaults boot never downgrades a tab that has already learned the
1062
- * project's threshold to the built-in one, and the window survives a rotation within the tab.
1131
+ * An explicit timeout override or server config stamps the window. Otherwise carry forward what
1132
+ * the tab already knows, so a defaults boot does not replace a previously configured threshold.
1063
1133
  */
1064
1134
  private persistPerTabSession;
1065
- /** The window this tab measures against: what a configured load recorded, else this load's own. */
1135
+ /** Explicit init timeout wins; otherwise retain the window a prior configured load recorded. */
1066
1136
  private perTabInactivityMs;
1067
1137
  /**
1068
1138
  * Return the next sequence number. With session continuity the counter is persisted so ordering
@@ -1088,7 +1158,7 @@ declare class CorbadoTracker {
1088
1158
  * sessionStorage-backed and stable for the whole page lifetime.
1089
1159
  */
1090
1160
  private resolveEventTabId;
1091
- trackSubflowStarted(subflowType: SubflowType, data: Record<string, any>, options?: StepOptions): void;
1161
+ trackSubflowStarted(subflowType: SubflowType, data: Record<string, any>, options?: StepOptions, eventId?: string): void;
1092
1162
  trackSubflowTrigger(subflowType: SubflowType, data: Record<string, any>, options?: StepOptions): void;
1093
1163
  trackSubflowStepStarted(subflowType: SubflowType, stepName: string, data: Record<string, any>, options?: StepOptions, ignoreAsInteraction?: boolean): void;
1094
1164
  trackSubflowStepFinished(subflowType: SubflowType, stepName: string, data: Record<string, any>, options?: StepOptions): void;
@@ -1106,7 +1176,12 @@ declare class CorbadoTracker {
1106
1176
  *
1107
1177
  * @internal
1108
1178
  */
1109
- track(name: AuthEventName, data: Record<string, any>, userReference?: UserReference, tags?: Record<string, string>, contexts?: Record<string, any>, explicitTimestamp?: number, experiments?: Record<string, string>): Promise<void>;
1179
+ track(name: AuthEventName, data: Record<string, any>, userReference?: UserReference, tags?: Record<string, string>, contexts?: Record<string, any>, explicitTimestamp?: number, experiments?: Record<string, string>, capture?: {
1180
+ id?: string;
1181
+ subflowStartEventId?: string;
1182
+ sessionId?: string;
1183
+ initiator?: StepOptions["initiator"];
1184
+ }): Promise<void>;
1110
1185
  /**
1111
1186
  * Track when an authentication flow (or flow selection screen) becomes visible.
1112
1187
  *
@@ -1296,7 +1371,7 @@ declare class CorbadoTracker {
1296
1371
  *
1297
1372
  * @internal
1298
1373
  */
1299
- enqueueLowEvent(low: LowEvent): void;
1374
+ enqueueLowEvent(low: LowEvent, capturedSessionId?: string): void;
1300
1375
  /**
1301
1376
  * Record a diagnostic telemetry entry (a `level` + free-form `message`) for the current session.
1302
1377
  *
@@ -1407,6 +1482,7 @@ declare const SDK_NAME = "@corbado/observe";
1407
1482
  declare const SDK_VERSION: string;
1408
1483
 
1409
1484
  interface TransportMakeRequestResponse {
1485
+ deliveryAccepted?: boolean;
1410
1486
  statusCode?: number;
1411
1487
  headers?: Record<string, string | null>;
1412
1488
  /** Parsed SDK reliability config, present only when the server returns it (HTTP 200). */
@@ -1538,16 +1614,11 @@ interface QueueOptions {
1538
1614
  */
1539
1615
  flushInterval?: number;
1540
1616
  debug?: boolean;
1541
- /**
1542
- * Reliability config for this page load; defaults to all-features-OFF. Boot-snapshot model: with
1543
- * a cached config the queue never changes its behavior mid-load — a fresh config returned by the
1544
- * server is only handed to {@link QueueOptions.onConfigReceived} for caching and applies on the
1545
- * next load. Only a defaults boot (no cached config) applies the first server config live.
1546
- */
1617
+ /** Initial delivery policy. The tracker applies later updates with updateConfig(). */
1547
1618
  config?: SdkReliabilityConfig;
1548
1619
  /** Called when the server returns a fresh config, so the client can cache it for the next load. */
1549
1620
  onConfigReceived?: (config: SdkReliabilityConfig) => void;
1550
- /** Whether to send the opt-in config header on the first flush of this load. Defaults to true. */
1621
+ /** Legacy standalone queue handshake. Trackers set false and use the independent config manager. */
1551
1622
  requestConfig?: boolean;
1552
1623
  /**
1553
1624
  * Web Lock name for the durable outbox, scoped alongside the storage engine's keys (see
@@ -1567,7 +1638,7 @@ interface QueueOptions {
1567
1638
  * Pending events are held as {@link OutboxEntry} records. When `config.durableOutbox` is enabled they are
1568
1639
  * additionally persisted to a localStorage-backed {@link EventStore} and recovered on the next load.
1569
1640
  * Delivery removes an entry only on a 2xx response; retryable failures back off (honoring `Retry-After`)
1570
- * up to `config.retry.maxAttempts`. Low events are best-effort and never persisted.
1641
+ * up to `config.retry.maxAttempts`. Low events have a separately bounded outbox when durableLowOutbox is enabled.
1571
1642
  *
1572
1643
  * Flushing is timer-driven only (the flush interval); `batchSize` caps the events per request, and a
1573
1644
  * flush drains all due work in sequential capped batches, stopping at the first failed send.
@@ -1583,14 +1654,16 @@ declare class RequestQueue {
1583
1654
  private readonly storage?;
1584
1655
  private pending;
1585
1656
  private lowsQueue;
1657
+ private lowPending;
1658
+ private lowStore?;
1586
1659
  /**
1587
- * Diagnostic telemetry buffered for the current session. Best-effort and never persisted (like
1588
- * lows). Attached to the next outgoing batch for this session; a telemetry entry alone never arms
1660
+ * Diagnostic telemetry buffered for the current session. Best-effort and never persisted. Attached to the next outgoing batch for this session; a telemetry entry alone never arms
1589
1661
  * the flush timer (it piggybacks), unless `config.flushOnTelemetry` escalates to an immediate flush.
1590
1662
  */
1591
1663
  private telemetryQueue;
1592
1664
  private timer;
1593
1665
  private isFlushing;
1666
+ private flushingDone?;
1594
1667
  private destroyed;
1595
1668
  /**
1596
1669
  * True when something was enqueued (or recovered) since the last sync flush. visibilitychange,
@@ -1605,11 +1678,7 @@ declare class RequestQueue {
1605
1678
  private readonly debug;
1606
1679
  private readonly requestConfig;
1607
1680
  private readonly onConfigReceived?;
1608
- /**
1609
- * Reliability config for this load. A boot with a cached server config is a snapshot that never
1610
- * changes mid-load; a boot on the built-in defaults upgrades once to the first server-returned
1611
- * config (see {@link handleConfigResponse}).
1612
- */
1681
+ /** Current delivery policy, including live updates. */
1613
1682
  private config;
1614
1683
  /**
1615
1684
  * Flow types whose completion triggers an immediate flush at enqueue time
@@ -1632,17 +1701,17 @@ declare class RequestQueue {
1632
1701
  * Error situations:
1633
1702
  * - Any error while enqueueing or scheduling the flush timer: log "Failed to enqueue event"
1634
1703
  */
1635
- enqueue(event: Event): void;
1704
+ enqueue(event: Event, capturedSessionId?: string): void;
1636
1705
  /**
1637
1706
  * Error situations:
1638
1707
  * - Any error while enqueueing or scheduling the flush timer: log "Failed to enqueue low event"
1639
1708
  */
1640
- enqueueLow(low: LowEvent): void;
1709
+ enqueueLow(low: LowEvent, capturedSessionId?: string): void;
1641
1710
  /**
1642
1711
  * Buffer a diagnostic telemetry entry for delivery with the next event batch.
1643
1712
  *
1644
1713
  * @remarks
1645
- * The master switch `config.telemetry` gates collection: when off, nothing is buffered or sent.
1714
+ * The switch `config.telemetry` gates collection. Entries buffered while on remain eligible for delivery.
1646
1715
  * By default a telemetry entry does NOT arm the flush timer — it piggybacks the next flush caused
1647
1716
  * by events or a lifecycle signal (it is marked dirty so the unload flush picks it up). When
1648
1717
  * `config.flushOnTelemetry` is on it escalates to an immediate flush.
@@ -1685,6 +1754,10 @@ declare class RequestQueue {
1685
1754
  private attachBatchMeta;
1686
1755
  private getDuePending;
1687
1756
  private takeLows;
1757
+ private validPendingLow;
1758
+ private removeLowEntries;
1759
+ private handleLowSendResult;
1760
+ private deferLowEntries;
1688
1761
  private takeTelemetry;
1689
1762
  private shouldRequestConfig;
1690
1763
  /**
@@ -1696,13 +1769,8 @@ declare class RequestQueue {
1696
1769
  * reliability features.
1697
1770
  */
1698
1771
  private handleConfigResponse;
1699
- /**
1700
- * Switch this load from the built-in defaults to the first server config (defaults boot only).
1701
- * Most fields are read at use time, so replacing the reference is enough; only the derived state
1702
- * (priority flow type set, durable outbox store) needs rebuilding.
1703
- */
1704
- private applyConfigLive;
1705
- /** Returns true when the batch was acknowledged with a 2xx (safe to keep draining). */
1772
+ /** Applies live delivery policy, retaining pending events, retry deadlines, and activated persistence. */
1773
+ updateConfig(config: SdkReliabilityConfig): void;
1706
1774
  private handleSendResult;
1707
1775
  private isRetryable;
1708
1776
  /**
@@ -1742,7 +1810,7 @@ declare class RequestQueue {
1742
1810
  destroy(): void;
1743
1811
  }
1744
1812
 
1745
- /** localStorage key under which the last-known server config is cached. */
1813
+ /** Last-known server config shared by batch-based and independently fetching SDK versions. */
1746
1814
  declare const CONFIG_STORAGE_KEY = "cbo_sdk_config";
1747
1815
  /**
1748
1816
  * Opt-in request header that asks the events endpoint to return the SDK reliability config. Its value
@@ -1797,11 +1865,9 @@ declare const CONFIG_BOUNDS: {
1797
1865
  /** Built-in continuity-session inactivity threshold (30 minutes); matches the historical default. */
1798
1866
  declare const DEFAULT_SESSION_INACTIVITY_MS: number;
1799
1867
  /**
1800
- * Default config: every delivery-reliability feature is OFF. The SDK behaves like a plain async
1801
- * fetch-keepalive flusher until the server returns config, which is cached as last-known for the
1802
- * next load AND applied live to the current load (a defaults boot has no prior config to stay
1803
- * coherent with; loads booting on a cached config keep their snapshot — boot-snapshot model). The
1804
- * empty version means "nothing cached"; the config request header sends "1" in that case.
1868
+ * Defaults used until a valid injected, cached, or fetched config is available.
1869
+ * Delivery-reliability features start OFF. Last-known remote config never expires.
1870
+ * Init overrides win per field; a complete override bypasses remote fetching and caching.
1805
1871
  */
1806
1872
  declare const DEFAULT_RELIABILITY_CONFIG: SdkReliabilityConfig;
1807
1873
  /**
@@ -1814,13 +1880,15 @@ declare const DEFAULT_RELIABILITY_CONFIG: SdkReliabilityConfig;
1814
1880
  * server value cannot harm the client.
1815
1881
  */
1816
1882
  declare function parseReliabilityConfig(raw: unknown): SdkReliabilityConfig | null;
1883
+ /** Resolve init overrides over validated server policy, then defaults, including individual retry fields. */
1884
+ declare function resolveReliabilityConfig(serverConfig: SdkReliabilityConfig | undefined, overrides?: SdkReliabilityConfigOverrides): SdkReliabilityConfig;
1817
1885
  /** Read the cached config from storage, or `null` if absent/invalid. */
1818
1886
  declare function loadCachedConfig(storage: StorageEngine): SdkReliabilityConfig | null;
1819
1887
  /** Persist the config as last-known so the next page load starts with these features enabled. */
1820
1888
  declare function cacheConfig(storage: StorageEngine, config: SdkReliabilityConfig): void;
1821
1889
 
1822
1890
  /** A persisted, not-yet-acknowledged event awaiting delivery. */
1823
- interface OutboxEntry {
1891
+ interface OutboxEntry<T = Event> {
1824
1892
  /** Event idempotency id; primary key of the entry. */
1825
1893
  id: string;
1826
1894
  /** Session id snapshot taken at enqueue time (so session rotation never relabels old entries). */
@@ -1830,7 +1898,7 @@ interface OutboxEntry {
1830
1898
  /** Number of completed send attempts so far. */
1831
1899
  attempts: number;
1832
1900
  /** The event payload. */
1833
- event: Event;
1901
+ event: T;
1834
1902
  }
1835
1903
  /** localStorage key under which the durable outbox is persisted. */
1836
1904
  declare const OUTBOX_STORAGE_KEY = "cbo_outbox";
@@ -1856,7 +1924,7 @@ declare const DEFAULT_MAX_SERIALIZED_LENGTH: number;
1856
1924
  * behavior. Mutations never reject; failures are logged.
1857
1925
  * The store is size-capped; overflow evicts the oldest entries and logs the count.
1858
1926
  */
1859
- declare class EventStore {
1927
+ declare class EventStore<T = Event> {
1860
1928
  private readonly storage;
1861
1929
  private readonly logger;
1862
1930
  private readonly maxEntries;
@@ -1867,6 +1935,7 @@ declare class EventStore {
1867
1935
  * and a shared key guarded by scoped locks would lose the cross-tab atomicity guarantee.
1868
1936
  */
1869
1937
  private readonly lockName;
1938
+ private readonly storageKey;
1870
1939
  private entries;
1871
1940
  /** Malformed entries are dropped on every read; report only once per instance to avoid log spam. */
1872
1941
  private reportedMalformed;
@@ -1876,21 +1945,21 @@ declare class EventStore {
1876
1945
  * to: a project-scoped outbox key guarded by the shared lock would serialize unrelated trackers,
1877
1946
  * and a shared key guarded by scoped locks would lose the cross-tab atomicity guarantee.
1878
1947
  */
1879
- lockName?: string);
1948
+ lockName?: string, storageKey?: string);
1880
1949
  private read;
1881
1950
  private mutate;
1882
1951
  /** Evict oldest entries until the serialized outbox fits {@link maxSerializedLength}. */
1883
1952
  private enforceSizeBudget;
1884
1953
  /** Append an entry. No-op if an entry with the same id already exists. */
1885
- add(entry: OutboxEntry): Promise<void>;
1954
+ add(entry: OutboxEntry<T>): Promise<void>;
1886
1955
  /** Re-read from storage and return all entries (memory mirror refreshed). */
1887
- all(): OutboxEntry[];
1956
+ all(): OutboxEntry<T>[];
1888
1957
  /** Entries whose `flushAfter` has elapsed, in insertion order. */
1889
- getDue(now: number): OutboxEntry[];
1958
+ getDue(now: number): OutboxEntry<T>[];
1890
1959
  /** Remove entries by id (acknowledged or permanently dropped). */
1891
1960
  remove(ids: string[]): Promise<void>;
1892
1961
  /** Replace existing entries (matched by id) with updated copies, e.g. after bumping backoff. */
1893
- update(updated: OutboxEntry[]): Promise<void>;
1962
+ update(updated: OutboxEntry<T>[]): Promise<void>;
1894
1963
  size(): number;
1895
1964
  }
1896
1965
 
@@ -1924,4 +1993,4 @@ declare function logInfo(message: string): void;
1924
1993
  declare function logError(message: string): void;
1925
1994
  declare function destroy(): Promise<void>;
1926
1995
 
1927
- export { type AppConfirmationOperationCeremonyTypedError, type AppConfirmationOperationConfig, AppConfirmationOperationFull, type AppConfirmationOperationRetryReason, type AppConfirmationOperationSpecType, type AppConfirmationOperationStart, type AuthDecisionFinished, type AuthDecisionStarted, AuthEventName, type AuthMethodDecisionFinished, type AuthMethodDecisionStarted, type AuthMethodType, type BaseEvent, CEREMONY_LOW_EVENT_TAIL_MS, CONFIG_BOUNDS, CONFIG_REQUEST_HEADER, CONFIG_STORAGE_KEY, type CaptchaOperationConfig, CaptchaOperationFull, type CaptchaOperationSpecType, type ClientCapabilities, type ClientEnvHandleMeta, type ClientEnvHandleMetaSource, type Conversion, CookieStorage, CorbadoTracker, type CreateLoggerOptions, type CustomEvent, DEFAULT_DEVICE_INFO_COLLECTOR_TIMEOUT_MS, DEFAULT_FLUSH_INTERVAL_MS, DEFAULT_MAX_ENTRIES, DEFAULT_MAX_SERIALIZED_LENGTH, DEFAULT_RELIABILITY_CONFIG, DEFAULT_SEQ_LOCK_TIMEOUT_MS, DEFAULT_SESSION_INACTIVITY_MS, type DeviceInfo, type DeviceInfoCollectionError, type DeviceInfoDataWeb, type DeviceType, type EmailLinkOperationConfig, EmailLinkOperationFull, type EmailLinkOperationPostResponseStart, type EmailLinkOperationSendStart, type EmailLinkOperationSpecType, type EmailOTPOperationConfig, type EmailOTPOperationPostResponseStart, type EmailOTPOperationSendOTPStart, type EmailOTPOperationSpecType, EmailOtpOperationFull, type Event, type EventBatch, type EventBatchMeta, type EventMeta, EventStore, type EventType, type FlowAutoFinished, type FlowDecided, type FlowFinished, type FlowReset, type FlowStarted, type FlowType, type FlushReason, type JavaScriptHighEntropy, LocalStorage, type Logger, type LowEvent, type MultiFlowReset, type MultiFlowStarted, NamespacedStorage, type NormalizedError, OUTBOX_LOCK_NAME, OUTBOX_STORAGE_KEY, type ObserveSdkConfigSnapshot, OperationFull, OperationFullProvideIdentifierWithCUI, type OperationFullProvideIdentifierWithCUIConfig, type OutboxEntry, type PasskeyEnrollmentCeremonyFinished, type PasskeyEnrollmentCeremonyStart, type PasskeyEnrollmentGetOptionsFinished, type PasskeyEnrollmentGetOptionsStart, type PasskeyEnrollmentOperationConfig, PasskeyEnrollmentOperationFull, type PasskeyEnrollmentPostResponseStart, type PasskeyLoginCUIGetOptionsFinished, type PasskeyLoginCUIGetOptionsStart, type PasskeyLoginCUISpecType, type PasskeyLoginCeremonyFinished, type PasskeyLoginCeremonyStart, type PasskeyLoginClientError, type PasskeyLoginFinish, type PasskeyLoginGetOptionsFinished, type PasskeyLoginGetOptionsStart, type PasskeyLoginOperationConfig, PasskeyLoginOperationFull, type PasskeyLoginPostResponseStart, type PasskeyLoginStartable, type PasskeyLoginSubmitted, type PasskeyOperationEnrollmentExplicitSpecType, type PasskeyOperationLoginExplicitSpecType, type PasswordEnrollmentConfig, PasswordEnrollmentOperationFull, type PasswordEnrollmentTypedError, type PasswordLoginCUICeremonyStart, type PasswordLoginCUIGetOptionsFinished, type PasswordLoginCUIGetOptionsStart, type PasswordLoginCUISpecType, type PasswordLoginCUITypedError, type PasswordLoginConfig, type PasswordLoginExplicitSpecType, PasswordLoginOperationFull, type PasswordLoginTypedError, type PredefinedEvent, type ProvideDataOperationConfig, ProvideDataOperationFull, type ProvideDataOperationPostResponseStart, type ProvideDataOperationSpecType, type ProvideDataOperationStart, type ProvideIdentifierError, type ProvideIdentifierFinish, type ProvideIdentifierPostResponseStart, type ProvideIdentifierSpecType, type ProvideIdentifierStart, type QueueOptions, RequestQueue, SDK_NAME, SDK_VERSION, type SdkInfo, type SdkReliabilityConfig, type SdkRetryConfig, SessionStorage, type SmsOTPOperationConfig, type SmsOTPOperationPostResponseStart, type SmsOTPOperationSpecType, SmsOtpOperationFull, type SocialLoginExchangeCodeFinished, type SocialLoginExchangeCodeStart, type SocialLoginGetRedirectUrlFinished, type SocialLoginGetRedirectUrlStart, type SocialLoginOperationConfig, SocialLoginOperationFull, type SocialLoginProviderType, type SocialLoginSpecType, type StepHelper, type StepOptions, type StorageEngine, type SubflowTrigger, type SubflowType, type TelemetryEntry, type TelemetryLevel, type TelemetrySink, type TrackerOptions, type Transport, type TransportMakeRequestResponse, type TransportOptions, type UserReference, cacheConfig, clearExperiment, clearExperiments, createLogger, destroy, getExperiments, getSessionId, getTracker, init, loadCachedConfig, logError, logInfo, namespacedKey, parseReliabilityConfig, resetSession, setExperiment, setExperiments, setUser, telemetry };
1996
+ export { type AppConfirmationOperationCeremonyTypedError, type AppConfirmationOperationConfig, AppConfirmationOperationFull, type AppConfirmationOperationRetryReason, type AppConfirmationOperationSpecType, type AppConfirmationOperationStart, type AuthDecisionFinished, type AuthDecisionStarted, AuthEventName, type AuthMethodDecisionFinished, type AuthMethodDecisionStarted, type AuthMethodType, type BaseEvent, CEREMONY_LOW_EVENT_TAIL_MS, CONFIG_BOUNDS, CONFIG_REQUEST_HEADER, CONFIG_STORAGE_KEY, type CaptchaOperationConfig, CaptchaOperationFull, type CaptchaOperationSpecType, type ClientCapabilities, type ClientEnvHandleMeta, type ClientEnvHandleMetaSource, type Conversion, CookieStorage, CorbadoTracker, type CreateLoggerOptions, type CustomEvent, DEFAULT_DEVICE_INFO_COLLECTOR_TIMEOUT_MS, DEFAULT_FLUSH_INTERVAL_MS, DEFAULT_MAX_ENTRIES, DEFAULT_MAX_SERIALIZED_LENGTH, DEFAULT_RELIABILITY_CONFIG, DEFAULT_SEQ_LOCK_TIMEOUT_MS, DEFAULT_SESSION_INACTIVITY_MS, type DeviceInfo, type DeviceInfoCollectionError, type DeviceInfoDataWeb, type DeviceType, type EmailLinkOperationConfig, EmailLinkOperationFull, type EmailLinkOperationPostResponseStart, type EmailLinkOperationSendStart, type EmailLinkOperationSpecType, type EmailOTPOperationConfig, type EmailOTPOperationPostResponseStart, type EmailOTPOperationSendOTPStart, type EmailOTPOperationSpecType, EmailOtpOperationFull, type Event, type EventBatch, type EventBatchMeta, type EventMeta, EventStore, type EventType, type FlowAutoFinished, type FlowDecided, type FlowFinished, type FlowReset, type FlowStarted, type FlowType, type FlushReason, type JavaScriptHighEntropy, LocalStorage, type Logger, type LowEvent, type LowEventFieldRole, type LowEventInitiator, type LowEventInputEffect, type LowEventSourceKind, type MultiFlowReset, type MultiFlowStarted, NamespacedStorage, type NormalizedError, OUTBOX_LOCK_NAME, OUTBOX_STORAGE_KEY, type ObserveSdkConfigSnapshot, OperationFull, OperationFullProvideIdentifierWithCUI, type OperationFullProvideIdentifierWithCUIConfig, type OutboxEntry, type PasskeyEnrollmentCeremonyFinished, type PasskeyEnrollmentCeremonyStart, type PasskeyEnrollmentGetOptionsFinished, type PasskeyEnrollmentGetOptionsStart, type PasskeyEnrollmentOperationConfig, PasskeyEnrollmentOperationFull, type PasskeyEnrollmentPostResponseStart, type PasskeyLoginCUIGetOptionsFinished, type PasskeyLoginCUIGetOptionsStart, type PasskeyLoginCUISpecType, type PasskeyLoginCeremonyFinished, type PasskeyLoginCeremonyStart, type PasskeyLoginClientError, type PasskeyLoginFinish, type PasskeyLoginGetOptionsFinished, type PasskeyLoginGetOptionsStart, type PasskeyLoginOperationConfig, PasskeyLoginOperationFull, type PasskeyLoginPostResponseStart, type PasskeyLoginStartable, type PasskeyLoginSubmitted, type PasskeyOperationEnrollmentExplicitSpecType, type PasskeyOperationLoginExplicitSpecType, type PasswordEnrollmentConfig, PasswordEnrollmentOperationFull, type PasswordEnrollmentTypedError, type PasswordLoginCUICeremonyStart, type PasswordLoginCUIGetOptionsFinished, type PasswordLoginCUIGetOptionsStart, type PasswordLoginCUISpecType, type PasswordLoginCUITypedError, type PasswordLoginConfig, type PasswordLoginExplicitSpecType, PasswordLoginOperationFull, type PasswordLoginTypedError, type PredefinedEvent, type ProvideDataOperationConfig, ProvideDataOperationFull, type ProvideDataOperationPostResponseStart, type ProvideDataOperationSpecType, type ProvideDataOperationStart, type ProvideIdentifierError, type ProvideIdentifierFinish, type ProvideIdentifierPostResponseStart, type ProvideIdentifierSpecType, type ProvideIdentifierStart, type QueueOptions, RequestQueue, SDK_NAME, SDK_VERSION, type SdkInfo, type SdkReliabilityConfig, type SdkReliabilityConfigOverrides, type SdkRetryConfig, SessionStorage, type SmsOTPOperationConfig, type SmsOTPOperationPostResponseStart, type SmsOTPOperationSpecType, SmsOtpOperationFull, type SocialLoginExchangeCodeFinished, type SocialLoginExchangeCodeStart, type SocialLoginGetRedirectUrlFinished, type SocialLoginGetRedirectUrlStart, type SocialLoginOperationConfig, SocialLoginOperationFull, type SocialLoginProviderType, type SocialLoginSpecType, type StepHelper, type StepOptions, type StorageEngine, type SubflowTrigger, type SubflowType, type TelemetryEntry, type TelemetryLevel, type TelemetrySink, type TrackerOptions, type Transport, type TransportMakeRequestResponse, type TransportOptions, type UserReference, cacheConfig, clearExperiment, clearExperiments, createLogger, destroy, getExperiments, getSessionId, getTracker, init, loadCachedConfig, logError, logInfo, namespacedKey, parseReliabilityConfig, resetSession, resolveReliabilityConfig, setExperiment, setExperiments, setUser, telemetry };