@corbado/observe 0.12.0-next.94-3fd9bb7 → 0.13.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/dist/index.d.mts CHANGED
@@ -24,8 +24,6 @@ declare enum AuthEventName {
24
24
  SubflowError = "subflow_error",
25
25
  SubflowStarted = "subflow_started",
26
26
  SubflowFinished = "subflow_finished",
27
- /** Client-side flow enrichment (the server accepts `session_enriched` as a legacy alias). */
28
- FlowEnriched = "flow_enriched",
29
27
  Conversion = "conversion"
30
28
  }
31
29
  interface BaseEvent {
@@ -53,6 +51,7 @@ interface BaseEvent {
53
51
  type UserReference = {
54
52
  userId?: string;
55
53
  identifier?: string;
54
+ crossEnvironmentTransactionID?: string;
56
55
  };
57
56
  /**
58
57
  * Serializable error shape produced by {@link normalizeError}.
@@ -106,8 +105,7 @@ type AuthMethodDecisionStarted = {
106
105
  };
107
106
  type AuthMethodDecisionFinished = {
108
107
  decisionName: string;
109
- /** Optional — when omitted, the backend completes the open decision of the same name using its declared options (classifier follow-up). */
110
- options?: (AuthMethodType | (string & {}))[];
108
+ options: (AuthMethodType | (string & {}))[];
111
109
  explicitDecisionValue?: string;
112
110
  };
113
111
  type ProvideIdentifierStart = {};
@@ -146,6 +144,15 @@ type StepOptions = {
146
144
  type SubflowTrigger = {
147
145
  actor: "system" | "user";
148
146
  explicitSpecType?: string;
147
+ /**
148
+ * Declares this subflow_started / subflow_trigger as not user-driven, excluding it from
149
+ * interaction-evidence calculations on the backend: a started subflow that produces no step
150
+ * afterwards is classified as a "no-followup" error unless this flag is set. Set it when the
151
+ * integration fires the start programmatically (e.g. an automatic passkey attempt after
152
+ * identifier lookup) and an abandoned attempt is expected rather than an error signal.
153
+ * Optional; absent/false means the event counts (legacy behavior).
154
+ */
155
+ ignoreAsInteraction?: boolean;
149
156
  };
150
157
  interface PredefinedEvent extends BaseEvent {
151
158
  type: "predefined";
@@ -477,17 +484,6 @@ declare class LowEventWindowTracker {
477
484
  * picker dismiss animations land shortly after the WebAuthn promise resolves/rejects.
478
485
  */
479
486
  declare const CEREMONY_LOW_EVENT_TAIL_MS = 1500;
480
- /**
481
- * Common constructor options shared by all operation helpers: every helper emits
482
- * `subflow_started` from its constructor unless opted out.
483
- */
484
- type OperationConfig = {
485
- /**
486
- * Emit `subflow_started` from the constructor (default `true`). Set to `false` to opt out and
487
- * call {@link OperationFull.subflowStart} yourself.
488
- */
489
- autoStart?: boolean;
490
- };
491
487
  type StepHelper<TStart = {}, TFinished = {}, TTypedError = never> = {
492
488
  start: (data: TStart, options?: StepOptions) => void;
493
489
  finished: (data: TFinished, options?: StepOptions) => void;
@@ -499,11 +495,12 @@ declare abstract class OperationFull {
499
495
  private tracker;
500
496
  private operationName;
501
497
  constructor(tracker: CorbadoTracker, operationName: SubflowType);
502
- /** Emit `subflow_started` for this operation. Only needed after opting out via `autoStart: false`. */
503
- subflowStart(data: any, options?: StepOptions): void;
504
498
  /**
505
- * @deprecated `subflow_trigger` will be removed in the next major version.
499
+ * Emits subflow_started. `data` supports the SubflowTrigger fields (`actor`,
500
+ * `explicitSpecType`, `ignoreAsInteraction`) plus free-form extras; see SubflowTrigger for when
501
+ * to set `ignoreAsInteraction` on programmatic starts.
506
502
  */
503
+ subflowStart(data: any, options?: StepOptions): void;
507
504
  trigger(data: SubflowTrigger, options?: StepOptions): void;
508
505
  customStep<TStart = {}, TFinished = {}>(stepName: string): StepHelper<TStart, TFinished>;
509
506
  protected subflowStepStarted(stepName: string, data: any, options?: StepOptions, ignoreAsInteraction?: boolean): void;
@@ -557,16 +554,12 @@ type PasskeyLoginPostResponseStart = {
557
554
  */
558
555
  assertionResponse?: string;
559
556
  };
560
- type PasskeyLoginOperationConfig = OperationConfig & {
561
- /** The classifier drops the attempt if no spec type arrives on any of its events — supply it here or on a step's start data as soon as known. */
562
- explicitSpecType?: PasskeyOperationLoginExplicitSpecType;
563
- };
564
557
  declare class PasskeyLoginOperationFull extends OperationFull {
565
558
  readonly getOptions: StepHelper<PasskeyLoginGetOptionsStart, PasskeyLoginGetOptionsFinished>;
566
559
  readonly ceremony: StepHelper<PasskeyLoginCeremonyStart, PasskeyLoginCeremonyFinished>;
567
560
  readonly postResponse: StepHelper<PasskeyLoginPostResponseStart>;
568
561
  private lowEventTracker;
569
- constructor(tracker: CorbadoTracker, config?: PasskeyLoginOperationConfig);
562
+ constructor(tracker: CorbadoTracker);
570
563
  /**
571
564
  * @deprecated `subflow_trigger` is not supported for passkey-login and will be removed in the
572
565
  * next major version.
@@ -582,7 +575,7 @@ type EmailOTPOperationSendOTPStart = {
582
575
  type EmailOTPOperationPostResponseStart = {
583
576
  explicitSpecType?: EmailOTPOperationSpecType;
584
577
  };
585
- type EmailOTPOperationConfig = OperationConfig & {
578
+ type EmailOTPOperationConfig = {
586
579
  explicitSpecType?: EmailOTPOperationSpecType;
587
580
  };
588
581
  declare class EmailOtpOperationFull extends OperationFull {
@@ -596,7 +589,7 @@ type SmsOTPOperationSpecType = "sms-otp-login" | "sms-otp-enrollment";
596
589
  type SmsOTPOperationPostResponseStart = {
597
590
  explicitSpecType?: SmsOTPOperationSpecType;
598
591
  };
599
- type SmsOTPOperationConfig = OperationConfig & {
592
+ type SmsOTPOperationConfig = {
600
593
  explicitSpecType?: SmsOTPOperationSpecType;
601
594
  };
602
595
  declare class SmsOtpOperationFull extends OperationFull {
@@ -612,18 +605,25 @@ type EmailLinkOperationSendStart = {
612
605
  type EmailLinkOperationPostResponseStart = {
613
606
  explicitSpecType?: EmailLinkOperationSpecType;
614
607
  };
615
- type EmailLinkOperationConfig = OperationConfig & {
616
- /** The classifier drops the attempt if no spec type arrives on any of its events — supply it here or on a step's start data as soon as known. */
617
- explicitSpecType?: EmailLinkOperationSpecType;
618
- };
619
608
  declare class EmailLinkOperationFull extends OperationFull {
620
609
  readonly send: StepHelper<EmailLinkOperationSendStart>;
621
610
  readonly postResponse: StepHelper<EmailLinkOperationPostResponseStart>;
622
611
  readonly resend: StepHelper;
623
- constructor(tracker: CorbadoTracker, config?: EmailLinkOperationConfig);
612
+ constructor(tracker: CorbadoTracker);
624
613
  }
625
614
 
626
- type PasskeyOperationEnrollmentExplicitSpecType = "conditional-auto-manual" | "auto-manual" | "manual";
615
+ /**
616
+ * Passkey-enrollment spec types. Two vocabularies coexist:
617
+ *
618
+ * - ATTEMPT-scoped (preferred): one subflow per attempt KIND — `"conditional"` (silent conditional
619
+ * create), `"auto"` (automatic required-mediation prompt fired by the integration) or `"manual"`
620
+ * (fired by the user's button). Create a NEW operation for every attempt; the backend opens a new
621
+ * subflow whenever the spec changes, so "auto prompt dismissed, then completed via the button" is two
622
+ * subflows and stays distinguishable from "completed by the auto prompt".
623
+ * - OFFER-scoped (legacy): one subflow per offer — `"conditional-auto-manual"` / `"auto-manual"` name
624
+ * the offer mode, and the completing ceremony's `mediation` tells the completion variants apart.
625
+ */
626
+ type PasskeyOperationEnrollmentExplicitSpecType = "conditional" | "auto" | "manual" | "conditional-auto-manual" | "auto-manual";
627
627
  type PasskeyEnrollmentGetOptionsStart = {
628
628
  explicitSpecType?: PasskeyOperationEnrollmentExplicitSpecType;
629
629
  };
@@ -650,14 +650,15 @@ type PasskeyEnrollmentPostResponseStart = {
650
650
  */
651
651
  attestationResponse?: string;
652
652
  };
653
- type PasskeyEnrollmentOperationConfig = OperationConfig & {
654
- /** The classifier drops the attempt if no spec type arrives on any of its events — supply it here or on a step's start data as soon as known. */
653
+ type PasskeyEnrollmentOperationConfig = {
655
654
  explicitSpecType?: PasskeyOperationEnrollmentExplicitSpecType;
656
655
  /**
657
- * Timestamp (epoch ms) for the subflow-started event. Set it when the enrollment began before the
658
- * operation could be constructed.
656
+ * Marks the auto-emitted `subflow_started` as not user-driven (see SubflowTrigger.ignoreAsInteraction).
657
+ * Set it for attempts the integration fires without a user gesture and without a visible surface —
658
+ * e.g. a `"conditional"` attempt — so a start that never produced a step is not read as a user asking
659
+ * to enroll.
659
660
  */
660
- explicitTimestamp?: number;
661
+ ignoreAsInteraction?: boolean;
661
662
  };
662
663
  declare class PasskeyEnrollmentOperationFull extends OperationFull {
663
664
  readonly getOptions: StepHelper<PasskeyEnrollmentGetOptionsStart, PasskeyEnrollmentGetOptionsFinished>;
@@ -693,11 +694,14 @@ type PasswordLoginCUIGetOptionsFinished = {
693
694
  type PasswordLoginCUICeremonyStart = {
694
695
  explicitSpecType?: PasswordLoginCUISpecType;
695
696
  };
696
- type PasswordLoginExplicitSpecType = "password-known-identifier" | "password-with-identifier";
697
- type PasswordLoginAutoTrackConfig = OperationConfig & {
698
- explicitSpecType?: PasswordLoginExplicitSpecType;
699
- /** The password input field. When set, low-event input tracking is attached to it. */
700
- inputHtmlField?: HTMLInputElement;
697
+ type PasswordLoginAutoTrackConfig = {
698
+ explicitSpecType: "password-known-identifier";
699
+ /** The password input field. */
700
+ inputHtmlField: HTMLInputElement;
701
+ } | {
702
+ explicitSpecType: "password-with-identifier";
703
+ /** The password input field. */
704
+ inputHtmlField: HTMLInputElement;
701
705
  /**
702
706
  * The identifier (e.g. email) input field. Accepted but not tracked yet — low-event
703
707
  * tracking for a second field lands together with per-field attribution.
@@ -732,10 +736,8 @@ type PasswordEnrollmentTypedError = {
732
736
  };
733
737
  type PasswordEnrollmentTypedErrorCode = "requirements_not_fulfilled";
734
738
  type PasswordEnrollmentExplicitSpecType = "password-set" | "password-reset";
735
- type PasswordEnrollmentAutoTrackConfig = OperationConfig & {
736
- /** The classifier drops the attempt if no spec type arrives on any of its events — supply it here or on a step's start data as soon as known. */
739
+ type PasswordEnrollmentAutoTrackConfig = {
737
740
  explicitSpecType?: PasswordEnrollmentExplicitSpecType;
738
- /** The password input field. When set, low-event input tracking is attached to it. */
739
741
  inputHtmlField?: HTMLInputElement;
740
742
  };
741
743
  declare class PasswordEnrollmentOperationFull extends OperationFull {
@@ -765,16 +767,17 @@ type PasskeyLoginCUIGetOptionsFinished = {
765
767
  explicitSpecType?: ProvideIdentifierSpecType;
766
768
  assertionOptions: string;
767
769
  };
768
- type OperationFullProvideIdentifierWithCUIConfig = OperationConfig & {
769
- /** When set, low event collection is enabled for the input field. */
770
+ type OperationFullProvideIdentifierWithCUIConfig = {
770
771
  inputHtmlField?: HTMLInputElement;
771
772
  explicitSpecType?: ProvideIdentifierSpecType;
772
773
  };
773
- declare class OperationFullProvideIdentifierWithCUI extends OperationFull {
774
+ declare class OperationFullProvideIdentifierWithCUI {
775
+ private tracker;
774
776
  private lowEventTracker?;
775
777
  readonly cui: {
776
778
  /**
777
- * @deprecated `subflow_trigger` will be removed in the next major version.
779
+ * @deprecated `subflow_trigger` is not supported for the CUI part of provide-identifier and
780
+ * will be removed in the next major version.
778
781
  */
779
782
  trigger: (data: SubflowTrigger, options?: StepOptions) => void;
780
783
  getOptions: StepHelper<PasskeyLoginCUIGetOptionsStart, PasskeyLoginCUIGetOptionsFinished>;
@@ -783,34 +786,32 @@ declare class OperationFullProvideIdentifierWithCUI extends OperationFull {
783
786
  };
784
787
  readonly provideIdentifier: {
785
788
  /**
786
- * @deprecated `subflow_trigger` will be removed in the next major version.
789
+ * @deprecated `subflow_trigger` is not supported for provide-identifier and will be removed
790
+ * in the next major version.
787
791
  */
788
792
  trigger: (data: SubflowTrigger, options?: StepOptions) => void;
789
793
  clientValidation: StepHelper;
790
794
  postResponse: StepHelper<ProvideIdentifierPostResponseStart>;
791
795
  };
792
796
  constructor(tracker: CorbadoTracker, config?: OperationFullProvideIdentifierWithCUIConfig);
797
+ private createStep;
793
798
  destroy(): void;
794
799
  }
795
800
 
796
801
  type SocialLoginSpecType = "pre-identifier" | "post-identifier";
797
802
  type SocialLoginGetRedirectUrlStart = {
798
803
  provider?: SocialLoginProviderType;
799
- explicitSpecType?: SocialLoginSpecType;
804
+ explicitSpecType: SocialLoginSpecType;
800
805
  };
801
806
  type SocialLoginGetRedirectUrlFinished = {};
802
807
  type SocialLoginExchangeCodeStart = {
803
808
  provider?: SocialLoginProviderType;
804
809
  };
805
810
  type SocialLoginExchangeCodeFinished = {};
806
- type SocialLoginOperationConfig = OperationConfig & {
807
- /** The classifier drops the attempt if no spec type arrives on any of its events — supply it here or on a step's start data as soon as known. */
808
- explicitSpecType?: SocialLoginSpecType;
809
- };
810
811
  declare class SocialLoginOperationFull extends OperationFull {
811
812
  readonly getRedirectUrl: StepHelper<SocialLoginGetRedirectUrlStart, SocialLoginGetRedirectUrlFinished>;
812
813
  readonly exchangeCode: StepHelper<SocialLoginExchangeCodeStart, SocialLoginExchangeCodeFinished>;
813
- constructor(tracker: CorbadoTracker, config?: SocialLoginOperationConfig);
814
+ constructor(tracker: CorbadoTracker);
814
815
  }
815
816
 
816
817
  type AppConfirmationOperationSpecType = "qr-code";
@@ -822,14 +823,11 @@ type AppConfirmationOperationCeremonyTypedError = {
822
823
  };
823
824
  type AppConfirmationOperationCeremonyTypedErrorCode = "declined" | "expired";
824
825
  type AppConfirmationOperationRetryReason = AppConfirmationOperationCeremonyTypedErrorCode | "technical-error" | "manual";
825
- type AppConfirmationOperationConfig = OperationConfig & {
826
- explicitSpecType?: AppConfirmationOperationSpecType;
827
- };
828
826
  declare class AppConfirmationOperationFull extends OperationFull {
829
827
  readonly ceremony: StepHelper<{}, {}, AppConfirmationOperationCeremonyTypedError>;
830
828
  readonly retry: StepHelper;
831
829
  readonly postResponse: StepHelper;
832
- constructor(tracker: CorbadoTracker, config?: AppConfirmationOperationConfig);
830
+ constructor(tracker: CorbadoTracker, explicitSpecType?: AppConfirmationOperationSpecType);
833
831
  }
834
832
 
835
833
  /**
@@ -838,7 +836,7 @@ declare class AppConfirmationOperationFull extends OperationFull {
838
836
  * - `invisible`: a widget that never presents UI and always solves itself.
839
837
  */
840
838
  type CaptchaOperationSpecType = "visible" | "invisible";
841
- type CaptchaOperationConfig = OperationConfig & {
839
+ type CaptchaOperationConfig = {
842
840
  explicitSpecType?: CaptchaOperationSpecType;
843
841
  };
844
842
  declare class CaptchaOperationFull extends OperationFull {
@@ -853,10 +851,9 @@ type ProvideDataOperationSpecType = "signup" | "login" | "recovery" | "enrollmen
853
851
  type ProvideDataOperationStart = {
854
852
  /** Stable name of the data field collected by this subflow, when known. */
855
853
  fieldName?: string;
856
- /** The classifier drops the attempt if no spec type arrives on any of its events — supply it here or on a step's start data as soon as known. */
857
854
  explicitSpecType?: ProvideDataOperationSpecType;
858
855
  };
859
- type ProvideDataOperationConfig = ProvideDataOperationStart & OperationConfig & {
856
+ type ProvideDataOperationConfig = ProvideDataOperationStart & {
860
857
  /** The input field whose low-level interaction signals should be collected. */
861
858
  inputHtmlField?: HTMLInputElement;
862
859
  };
@@ -873,6 +870,7 @@ declare class ProvideDataOperationFull extends OperationFull {
873
870
  }
874
871
 
875
872
  interface TrackerOptions {
873
+ /** All persisted SDK state and cross-tab locks are isolated by this project id. */
876
874
  projectId: string;
877
875
  apiBaseUrl: string;
878
876
  apiEventPath?: string;
@@ -903,8 +901,6 @@ interface TrackerOptions {
903
901
  * It will be removed in a future release.
904
902
  */
905
903
  flushInterval?: number;
906
- /** Generates new Observe session ids; returned values must be UUID-compatible. Existing stored sessions are still reused. */
907
- sessionIdGenerator?: () => string;
908
904
  }
909
905
  declare class CorbadoTracker {
910
906
  private options;
@@ -915,6 +911,8 @@ declare class CorbadoTracker {
915
911
  private sessionStorage;
916
912
  /** Dedicated localStorage engine for reliability state (config cache, outbox, continuity session, seq). */
917
913
  private persistentStorage;
914
+ /** Seq/continuity Web Lock name; project-scoped together with the storage keys it guards. */
915
+ private readonly seqLockName;
918
916
  /**
919
917
  * Reliability config for this load. A boot with a cached server config is a snapshot (immutable
920
918
  * mid-load); a boot on the built-in defaults upgrades once to the first server-returned config
@@ -997,19 +995,21 @@ declare class CorbadoTracker {
997
995
  */
998
996
  private resolveExperiments;
999
997
  private isTrackingBlocked;
1000
- private createSessionId;
1001
998
  private resolveSessionId;
1002
999
  /**
1003
1000
  * Resolve the session id from localStorage so it survives reloads and is shared across tabs of the
1004
1001
  * same browser. Rotates after `config.sessionInactivityMs` of inactivity (server-controlled,
1005
1002
  * boot-snapshot like the rest of the config), resetting the seq counter.
1006
1003
  *
1007
- * This is the ONLY place an inactivity rotation happens. Rotating here is safe because the load
1008
- * that triggers it also re-announces its flow (an integration emits `flow_started` on page load),
1009
- * so the fresh session id gets a classifiable flow. Mid-page there is no such re-announcement:
1010
- * rotating between two tracked events would leave the started flow unfinished in the old session
1011
- * and the remaining events without a flow start in the new one — one gap counted as a drop-off,
1012
- * one completion counted as nothing. `nextSeq` therefore never rotates on inactivity.
1004
+ * Inactivity rotation happens at boot only, here and on the per-tab path {@link resolveSessionId}
1005
+ * takes without continuity. Boot is chosen on an assumption, not a guarantee: that a load
1006
+ * re-announces its flow, so the fresh session id gets a classifiable flow. That holds where a
1007
+ * flow is opened per load. Where one is opened once and carried across loads it does not, and a
1008
+ * boot rotation splits that flow — such a project needs a window long enough to span the journey.
1009
+ * Mid-page the assumption is not even available: nothing re-announces between two tracked events,
1010
+ * so rotating there would leave the started flow unfinished in the old session and the remaining
1011
+ * events without a flow start in the new one — one gap counted as a drop-off, one completion
1012
+ * counted as nothing. `nextSeq` therefore never rotates on inactivity, on either path.
1013
1013
  */
1014
1014
  private getContinuitySessionId;
1015
1015
  /**
@@ -1017,6 +1017,24 @@ declare class CorbadoTracker {
1017
1017
  * section measures from the last write that actually happened — whoever made it.
1018
1018
  */
1019
1019
  private persistContinuitySession;
1020
+ /**
1021
+ * Read the per-tab session record. A bare string is the format that predates dating: it carries no
1022
+ * `lastActiveAt`, so its window can only start on the load that reads it. That load rewrites it in
1023
+ * the dated shape, so a tab converts once and ages normally from then on, and the case drains as
1024
+ * the rollout replaces the bundles that write it.
1025
+ */
1026
+ private readPerTabSession;
1027
+ /**
1028
+ * Persist the per-tab record and remember when, sharing the throttle bookkeeping with the
1029
+ * continuity record — a load resolves its session on one path or the other, never both.
1030
+ *
1031
+ * Only a load that received a server config stamps the window; any other carries forward what the
1032
+ * tab already knows. So a defaults boot never downgrades a tab that has already learned the
1033
+ * project's threshold to the built-in one, and the window survives a rotation within the tab.
1034
+ */
1035
+ private persistPerTabSession;
1036
+ /** The window this tab measures against: what a configured load recorded, else this load's own. */
1037
+ private perTabInactivityMs;
1020
1038
  /**
1021
1039
  * Return the next sequence number. With session continuity the counter is persisted so ordering
1022
1040
  * survives reloads/redirects; the read-increment-write runs under a cross-tab Web Lock
@@ -1046,11 +1064,7 @@ declare class CorbadoTracker {
1046
1064
  trackSubflowStepStarted(subflowType: SubflowType, stepName: string, data: Record<string, any>, options?: StepOptions, ignoreAsInteraction?: boolean): void;
1047
1065
  trackSubflowStepFinished(subflowType: SubflowType, stepName: string, data: Record<string, any>, options?: StepOptions): void;
1048
1066
  trackSubflowStepError(subflowType: SubflowType, stepName: string, data: Record<string, any>, options?: StepOptions): void;
1049
- /**
1050
- * @remarks
1051
- * Records an additional error occurrence against the subflow. Carries no outcome semantics —
1052
- * step errors are the intended channel; not part of a normal integration.
1053
- */
1067
+ trackSubflowFinished(subflowType: SubflowType, data: Record<string, any>, options?: StepOptions): void;
1054
1068
  trackSubflowError(subflowType: SubflowType, data: Record<string, any>, options?: StepOptions): void;
1055
1069
  /**
1056
1070
  * Error situations:
@@ -1070,6 +1084,9 @@ declare class CorbadoTracker {
1070
1084
  *
1071
1085
  * @param data - Flow metadata, including one flow (`flowName`) or multiple candidates (`flowNames`).
1072
1086
  * @param tags - Optional key-value tags for filtering and segmentation.
1087
+ * @param experiments - Optional per-call experiment overrides.
1088
+ * @param contexts - Optional structured event context (e.g. technical metadata that is not an
1089
+ * analytical dimension). Written to the event's `contexts` field verbatim.
1073
1090
  *
1074
1091
  * @example
1075
1092
  * ```typescript
@@ -1080,7 +1097,7 @@ declare class CorbadoTracker {
1080
1097
  * });
1081
1098
  * ```
1082
1099
  */
1083
- flowStarted(data: FlowStarted | MultiFlowStarted, tags?: Record<string, string>, experiments?: Record<string, string>): void;
1100
+ flowStarted(data: FlowStarted | MultiFlowStarted, tags?: Record<string, string>, experiments?: Record<string, string>, contexts?: Record<string, unknown>): void;
1084
1101
  /**
1085
1102
  * Track when the user commits to a specific flow.
1086
1103
  *
@@ -1178,22 +1195,6 @@ declare class CorbadoTracker {
1178
1195
  * ```
1179
1196
  */
1180
1197
  flowAutoFinished(data: FlowAutoFinished, tags?: Record<string, string>, experiments?: Record<string, string>): void;
1181
- /**
1182
- * Attach a cross-environment transaction id to the current flow.
1183
- *
1184
- * @remarks
1185
- * Use this when the flow continues in another environment (for example a native app or another
1186
- * device) and both sides report under the same transaction id. Emits a single `flow_enriched`
1187
- * event carrying the id in its user reference; call it once, as soon as the id is known.
1188
- *
1189
- * @param id - The cross-environment transaction id.
1190
- *
1191
- * @example
1192
- * ```typescript
1193
- * tracker.setCrossEnvironmentTransactionId("cet_123");
1194
- * ```
1195
- */
1196
- setCrossEnvironmentTransactionId(id: string): void;
1197
1198
  /**
1198
1199
  * Track when you present authentication method choices to the user.
1199
1200
  *
@@ -1218,15 +1219,7 @@ declare class CorbadoTracker {
1218
1219
  */
1219
1220
  authMethodsDecisionStarted(data: AuthMethodDecisionStarted, tags?: Record<string, string>, experiments?: Record<string, string>, options?: Pick<StepOptions, "explicitTimestamp">): void;
1220
1221
  authMethodsDecisionFinished(data: AuthMethodDecisionFinished, tags?: Record<string, string>, experiments?: Record<string, string>): void;
1221
- /**
1222
- * @deprecated Use {@link CorbadoTracker.authMethodsDecisionStarted} instead (its `options`
1223
- * already accept free-form strings).
1224
- */
1225
1222
  authDecisionStarted(data: AuthDecisionStarted, tags?: Record<string, string>, experiments?: Record<string, string>): void;
1226
- /**
1227
- * @deprecated Use {@link CorbadoTracker.authMethodsDecisionFinished} instead (its `options`
1228
- * already accept free-form strings).
1229
- */
1230
1223
  authDecisionFinished(data: AuthDecisionFinished, tags?: Record<string, string>, experiments?: Record<string, string>): void;
1231
1224
  /**
1232
1225
  * Enqueue a "low" event (granular DOM/window/visualviewport/PWM signal) for the current session.
@@ -1285,17 +1278,17 @@ declare class CorbadoTracker {
1285
1278
  * @internal
1286
1279
  */
1287
1280
  lowEventFlushKeepalive(): void;
1288
- passkeyLoginFullOperation(config?: PasskeyLoginOperationConfig): PasskeyLoginOperationFull;
1281
+ passkeyLoginFullOperation(): PasskeyLoginOperationFull;
1289
1282
  passkeyEnrollmentFullOperation(config?: PasskeyEnrollmentOperationConfig): PasskeyEnrollmentOperationFull;
1290
1283
  passwordLoginFullOperation(autoTrackConfig?: PasswordLoginAutoTrackConfig): PasswordLoginOperationFull;
1291
1284
  passwordEnrollmentFullOperation(autoTrackConfig?: PasswordEnrollmentAutoTrackConfig): PasswordEnrollmentOperationFull;
1292
- emailLinkOperationFull(config?: EmailLinkOperationConfig): EmailLinkOperationFull;
1285
+ emailLinkOperationFull(): EmailLinkOperationFull;
1293
1286
  emailOtpOperationFull(config?: EmailOTPOperationConfig): EmailOtpOperationFull;
1294
1287
  smsOtpOperationFull(config?: SmsOTPOperationConfig): SmsOtpOperationFull;
1295
1288
  provideIdentifierOperationFull(config?: OperationFullProvideIdentifierWithCUIConfig): OperationFullProvideIdentifierWithCUI;
1296
1289
  provideDataOperationFull(config?: ProvideDataOperationConfig): ProvideDataOperationFull;
1297
- socialLoginOperationFull(config?: SocialLoginOperationConfig): SocialLoginOperationFull;
1298
- appConfirmationOperationFull(config?: AppConfirmationOperationConfig): AppConfirmationOperationFull;
1290
+ socialLoginOperationFull(): SocialLoginOperationFull;
1291
+ appConfirmationOperationFull(explicitSpecType?: AppConfirmationOperationSpecType): AppConfirmationOperationFull;
1299
1292
  captchaOperationFull(config?: CaptchaOperationConfig): CaptchaOperationFull;
1300
1293
  /**
1301
1294
  * Flush any pending events and release all resources (timers, event listeners).
@@ -1369,6 +1362,28 @@ interface StorageEngine {
1369
1362
  setItem<T>(key: string, value: T): void;
1370
1363
  removeItem(key: string): void;
1371
1364
  }
1365
+ /**
1366
+ * Suffix a storage key or cross-tab lock name with a namespace. One shared helper so keys and the
1367
+ * Web Lock names guarding them can never disagree on the derived name.
1368
+ */
1369
+ declare function namespacedKey(key: string, namespace: string): string;
1370
+ /**
1371
+ * Wraps a storage engine so every key is suffixed with a fixed namespace (see {@link namespacedKey}).
1372
+ *
1373
+ * @remarks
1374
+ * All trackers use their project id as the namespace: all SDK state flows through the engines
1375
+ * created in the tracker constructor, so wrapping them scopes every persisted key (session, seq,
1376
+ * outbox, config cache, experiments, tab id, client-env handle, debug dumps) in one place. Lock
1377
+ * names are not storage keys and must be scoped separately by the call sites that own them.
1378
+ */
1379
+ declare class NamespacedStorage implements StorageEngine {
1380
+ private readonly engine;
1381
+ private readonly namespace;
1382
+ constructor(engine: StorageEngine, namespace: string);
1383
+ getItem<T>(key: string): T | null;
1384
+ setItem<T>(key: string, value: T): void;
1385
+ removeItem(key: string): void;
1386
+ }
1372
1387
  declare class LocalStorage implements StorageEngine {
1373
1388
  private logger;
1374
1389
  constructor(logger: Logger);
@@ -1468,6 +1483,11 @@ interface QueueOptions {
1468
1483
  onConfigReceived?: (config: SdkReliabilityConfig) => void;
1469
1484
  /** Whether to send the opt-in config header on the first flush of this load. Defaults to true. */
1470
1485
  requestConfig?: boolean;
1486
+ /**
1487
+ * Web Lock name for the durable outbox, scoped alongside the storage engine's keys (see
1488
+ * {@link EventStore}). Defaults to the shared {@link OUTBOX_LOCK_NAME}.
1489
+ */
1490
+ outboxLockName?: string;
1471
1491
  }
1472
1492
  /**
1473
1493
  * @remarks When `window` is defined, `visibilitychange` (when the document becomes hidden) and `pagehide`
@@ -1530,6 +1550,8 @@ declare class RequestQueue {
1530
1550
  * (config.flushOnFlowTypeFinished).
1531
1551
  */
1532
1552
  private priorityFlowTypes;
1553
+ /** Scoped Web Lock name for the durable outbox; undefined = EventStore's shared default. */
1554
+ private outboxLockName?;
1533
1555
  private store?;
1534
1556
  /**
1535
1557
  * Once the server has answered the config request with a 2xx (200 = fresh config cached for the
@@ -1762,7 +1784,7 @@ declare const DEFAULT_MAX_SERIALIZED_LENGTH: number;
1762
1784
  *
1763
1785
  * @remarks
1764
1786
  * Every mutation is a read-merge-write against storage, executed under a cross-tab Web Lock
1765
- * ({@link OUTBOX_LOCK_NAME}) so concurrent tabs sharing the same localStorage cannot interleave
1787
+ * (default {@link OUTBOX_LOCK_NAME}) so concurrent tabs sharing the same localStorage cannot interleave
1766
1788
  * between the read and the write (which would silently drop the other tab's entries). Where the
1767
1789
  * Web Locks API is unavailable the mutation runs unlocked, matching the historical best-effort
1768
1790
  * behavior. Mutations never reject; failures are logged.
@@ -1773,10 +1795,22 @@ declare class EventStore {
1773
1795
  private readonly logger;
1774
1796
  private readonly maxEntries;
1775
1797
  private readonly maxSerializedLength;
1798
+ /**
1799
+ * Web Lock name guarding mutations. Must be scoped together with the storage the engine writes
1800
+ * to: a project-scoped outbox key guarded by the shared lock would serialize unrelated trackers,
1801
+ * and a shared key guarded by scoped locks would lose the cross-tab atomicity guarantee.
1802
+ */
1803
+ private readonly lockName;
1776
1804
  private entries;
1777
1805
  /** Malformed entries are dropped on every read; report only once per instance to avoid log spam. */
1778
1806
  private reportedMalformed;
1779
- constructor(storage: StorageEngine, logger: Logger, maxEntries?: number, maxSerializedLength?: number);
1807
+ constructor(storage: StorageEngine, logger: Logger, maxEntries?: number, maxSerializedLength?: number,
1808
+ /**
1809
+ * Web Lock name guarding mutations. Must be scoped together with the storage the engine writes
1810
+ * to: a project-scoped outbox key guarded by the shared lock would serialize unrelated trackers,
1811
+ * and a shared key guarded by scoped locks would lose the cross-tab atomicity guarantee.
1812
+ */
1813
+ lockName?: string);
1780
1814
  private read;
1781
1815
  private mutate;
1782
1816
  /** Evict oldest entries until the serialized outbox fits {@link maxSerializedLength}. */
@@ -1794,7 +1828,13 @@ declare class EventStore {
1794
1828
  size(): number;
1795
1829
  }
1796
1830
 
1831
+ /**
1832
+ * Create a tracker and make it the default for all package-level helpers.
1833
+ * Each call replaces the default. For multiple projects, retain the returned instances and call
1834
+ * their methods, or construct {@link CorbadoTracker} instances directly without changing the default.
1835
+ */
1797
1836
  declare function init(options: TrackerOptions): CorbadoTracker;
1837
+ /** Return the default tracker from the most recent {@link init} call. */
1798
1838
  declare function getTracker(): CorbadoTracker | undefined;
1799
1839
  declare function resetSession(): string | undefined;
1800
1840
  /**
@@ -1802,11 +1842,6 @@ declare function resetSession(): string | undefined;
1802
1842
  * could be established. See {@link CorbadoTracker.getSessionId}.
1803
1843
  */
1804
1844
  declare function getSessionId(): string | undefined;
1805
- /**
1806
- * Attach a cross-environment transaction id to the current flow of the global tracker. See
1807
- * {@link CorbadoTracker.setCrossEnvironmentTransactionId}.
1808
- */
1809
- declare function setCrossEnvironmentTransactionId(id: string): void;
1810
1845
  declare function setExperiment(key: string, variant: string): void;
1811
1846
  declare function setExperiments(assignments: Record<string, string>): void;
1812
1847
  declare function clearExperiment(key: string): void;
@@ -1817,4 +1852,4 @@ declare function logInfo(message: string): void;
1817
1852
  declare function logError(message: string): void;
1818
1853
  declare function destroy(): Promise<void>;
1819
1854
 
1820
- 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, type NormalizedError, OUTBOX_LOCK_NAME, OUTBOX_STORAGE_KEY, type ObserveSdkConfigSnapshot, type OperationConfig, 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 PasswordEnrollmentAutoTrackConfig, PasswordEnrollmentOperationFull, type PasswordEnrollmentTypedError, type PasswordLoginAutoTrackConfig, type PasswordLoginCUICeremonyStart, type PasswordLoginCUIGetOptionsFinished, type PasswordLoginCUIGetOptionsStart, type PasswordLoginCUISpecType, type PasswordLoginCUITypedError, 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, parseReliabilityConfig, resetSession, setCrossEnvironmentTransactionId, setExperiment, setExperiments, telemetry };
1855
+ export { type AppConfirmationOperationCeremonyTypedError, 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, 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, PasskeyLoginOperationFull, type PasskeyLoginPostResponseStart, type PasskeyLoginStartable, type PasskeyLoginSubmitted, type PasskeyOperationEnrollmentExplicitSpecType, type PasskeyOperationLoginExplicitSpecType, type PasswordEnrollmentAutoTrackConfig, PasswordEnrollmentOperationFull, type PasswordEnrollmentTypedError, type PasswordLoginAutoTrackConfig, type PasswordLoginCUICeremonyStart, type PasswordLoginCUIGetOptionsFinished, type PasswordLoginCUIGetOptionsStart, type PasswordLoginCUISpecType, type PasswordLoginCUITypedError, 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, 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, telemetry };