@corbado/observe 1.10.1 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/analysis/client.mjs +37 -1595
  2. package/dist/analysis/default-tracker.mjs +16 -0
  3. package/dist/analysis/index.mjs +29 -41
  4. package/dist/analysis/plugins/cookie-storage.mjs +11 -0
  5. package/dist/analysis/plugins/cross-origin-session.mjs +171 -0
  6. package/dist/analysis/plugins/probes.mjs +69 -0
  7. package/dist/analysis/plugins/raw-errors.mjs +8 -0
  8. package/dist/analysis/probe-lane.mjs +175 -0
  9. package/dist/analysis/queue.mjs +18 -141
  10. package/dist/analysis/session-keys.mjs +11 -0
  11. package/dist/analysis/tracker-core.mjs +1352 -0
  12. package/dist/analysis/tracker-features.mjs +80 -0
  13. package/dist/analysis/tracker-functions.mjs +103 -0
  14. package/dist/analysis/utils/appconfirmation-operation-full.mjs +5 -1
  15. package/dist/analysis/utils/captcha-operation-full.mjs +5 -1
  16. package/dist/analysis/utils/email-link-operation-full.mjs +9 -1
  17. package/dist/analysis/utils/email-otp-operation-full.mjs +5 -1
  18. package/dist/analysis/utils/form-operation-full.mjs +5 -1
  19. package/dist/analysis/utils/key-operation-full.mjs +9 -1
  20. package/dist/analysis/utils/operation-full-provide-identifier-with-cui.mjs +8 -1
  21. package/dist/analysis/utils/operation-full.mjs +4 -2
  22. package/dist/analysis/utils/passkey-deletion-operation-full.mjs +5 -1
  23. package/dist/analysis/utils/passkey-enrollment-operation-full.mjs +5 -1
  24. package/dist/analysis/utils/passkey-login-operation-full.mjs +5 -1
  25. package/dist/analysis/utils/password-enrollment-operation-full.mjs +5 -1
  26. package/dist/analysis/utils/password-login-operation-full.mjs +5 -1
  27. package/dist/analysis/utils/provide-data-operation-full.mjs +5 -1
  28. package/dist/analysis/utils/sms-otp-operation-full.mjs +5 -1
  29. package/dist/analysis/utils/social-operation-login.mjs +5 -1
  30. package/dist/analysis/utils/sso-operation-login.mjs +5 -1
  31. package/dist/analysis/utils/totp-operation-full.mjs +5 -1
  32. package/dist/analysis/utils/trusted-device-operation-full.mjs +9 -1
  33. package/dist/analysis/version.mjs +1 -1
  34. package/dist/cdn/script.global.js +4 -4
  35. package/dist/index.d.mts +1366 -883
  36. package/dist/index.d.ts +1366 -883
  37. package/dist/index.js +4 -4
  38. package/dist/index.mjs +4 -4
  39. package/package.json +1 -1
package/dist/index.d.ts CHANGED
@@ -796,116 +796,6 @@ type SdkReliabilityConfigOverrides = Partial<Omit<SdkReliabilityConfig, "retry"
796
796
  pmd?: boolean;
797
797
  };
798
798
 
799
- /**
800
- * Where low events go. `flushKeepalive` is requested on `pagehide` teardown so lows batched after
801
- * the queue's own lifecycle flush still get out; operations wire it to the client's
802
- * `lowEventFlushKeepalive()`, which is gated by the server-controlled `tlf` trigger switch
803
- * (default true = historical behavior, can be disabled remotely).
804
- */
805
- interface LowEventSink {
806
- reserveCaptureSeq?(): number;
807
- enqueueLowEvent(low: LowEvent): void;
808
- flushKeepalive(): void;
809
- registerInputs?(fields: readonly HTMLInputElement[], flush: () => void): () => void;
810
- beginCeremony?(initiator?: LowEventInitiator): {
811
- settle(tailMs: number): void;
812
- destroy(): void;
813
- };
814
- }
815
-
816
- /**
817
- * Limits for optional raw-error serialization. Modeled on Sentry's client options
818
- * (`normalizeDepth`, `normalizeMaxBreadth`, `maxValueLength`, `normalizeToSize`, the
819
- * stack-frame limit and the linked-errors limit) with defaults tuned for an authentication
820
- * event stream rather than an error monitor. Every value is clamped to {@link RAW_ERROR_BOUNDS};
821
- * invalid values fall back to the default. A fixed 1024-node budget per depth attempt and
822
- * incremental text-byte accounting also bound work before the final JSON-size check.
823
- */
824
- type SerializeRawErrorOptions = {
825
- /** Include `stack` strings. Default false. */
826
- stack?: boolean;
827
- /** Stack lines kept after the header line when `stack` is on. Default 50 (Sentry: 50). */
828
- maxStackFrames?: number;
829
- /** Object nesting depth below the envelope. Default 3 (Sentry `normalizeDepth`: 3). */
830
- depth?: number;
831
- /** Keys per object and items per array, Map or Set. Default 30 (Sentry `normalizeMaxBreadth`: 1000). */
832
- maxBreadth?: number;
833
- /** Characters kept per string. Default 1024 (Sentry `maxValueLength`: 250). */
834
- maxValueLength?: number;
835
- /** `cause` hops followed. Default 3 (Sentry linked errors: 5, Datadog: 10). */
836
- maxCauseDepth?: number;
837
- /** Maximum UTF-8 JSON size in bytes. Depth is reduced until the output fits; omit diagnostics that cannot fit. Default 32768 (Sentry `normalizeToSize`: 100 KiB). */
838
- maxBytes?: number;
839
- };
840
- /** Envelope produced by {@link serializeRawError}. */
841
- type RawErrorEnvelope = {
842
- /** Class tag of the original value: `DOMException`, `Error`, `Object`, `Response`, `number`, `null`, `unserializable`, … */
843
- type: string;
844
- /** Bounded plain-JSON copy of the value; absent when it could not be serialized within the limits. */
845
- value?: unknown;
846
- /** Set when even the shallowest serialization exceeded `maxBytes`. */
847
- truncated?: true;
848
- };
849
- type Limits = Required<Omit<SerializeRawErrorOptions, "stack">> & {
850
- stack: boolean;
851
- };
852
- /** Inclusive bounds for every numeric limit; defaults sit inside them. */
853
- declare const RAW_ERROR_BOUNDS: {
854
- readonly maxStackFrames: {
855
- readonly min: 1;
856
- readonly max: 100;
857
- readonly default: 50;
858
- };
859
- readonly depth: {
860
- readonly min: 0;
861
- readonly max: 10;
862
- readonly default: 3;
863
- };
864
- readonly maxBreadth: {
865
- readonly min: 1;
866
- readonly max: 1000;
867
- readonly default: 30;
868
- };
869
- readonly maxValueLength: {
870
- readonly min: 1;
871
- readonly max: 10000;
872
- readonly default: 1024;
873
- };
874
- readonly maxCauseDepth: {
875
- readonly min: 0;
876
- readonly max: 10;
877
- readonly default: 3;
878
- };
879
- readonly maxBytes: {
880
- readonly min: 0;
881
- readonly max: 65536;
882
- readonly default: 32768;
883
- };
884
- };
885
- /** Resolve caller options into clamped limits. Exported for tests and integrations that want to inspect the effective values. */
886
- declare function resolveRawErrorLimits(options?: SerializeRawErrorOptions): Limits;
887
- /**
888
- * Serialize an arbitrary thrown value for the `rawError` diagnostic field.
889
- *
890
- * Copies standard error fields and serializable own properties within the configured limits.
891
- * Standard fields are read through the prototype chain so DOMException and cross-realm errors
892
- * serialize. Output is plain JSON, bounded in depth, breadth, string length, cause chain and
893
- * UTF-8 size, and never throws.
894
- *
895
- * The result is an envelope `{ type, value }`: `type` is the value's class tag (`DOMException`,
896
- * `Error`, `Object`, `number`, …) and `value` is a bounded diagnostic copy. Keeping the class tag
897
- * outside value preserves the library's own `type` field. When the value cannot be serialized
898
- * within the limits the envelope carries `truncated: true` or the type `unserializable` and no
899
- * `value`.
900
- *
901
- * Stacks are omitted unless `stack: true`; they carry page URLs and add the most bytes.
902
- * Binary data (ArrayBuffer, typed arrays) is reported by type and length only, never by content.
903
- *
904
- * @param value - Original thrown value or an explicit diagnostic projection.
905
- * @param options - Limits; see {@link SerializeRawErrorOptions} for defaults and {@link RAW_ERROR_BOUNDS} for clamping.
906
- */
907
- declare function serializeRawError(value: unknown, options?: SerializeRawErrorOptions): RawErrorEnvelope | undefined;
908
-
909
799
  /** Sink that escalates a diagnostic message to the telemetry stream. */
910
800
  type TelemetrySink = (level: TelemetryLevel, message: string) => void;
911
801
  interface Logger {
@@ -928,152 +818,6 @@ interface CreateLoggerOptions {
928
818
  }
929
819
  declare function createLogger(options: CreateLoggerOptions): Logger;
930
820
 
931
- /** Ceremony context lease on the shared observer. Never installs its own window listeners. */
932
- declare class LowEventWindowTracker {
933
- private logger;
934
- private sink;
935
- private lease?;
936
- private destroyed;
937
- constructor(logger: Logger, sink: LowEventSink);
938
- arm(initiator?: LowEventInitiator, conditional?: boolean): void;
939
- scheduleDisarm(delayMs: number): void;
940
- disarm(): void;
941
- destroy(): void;
942
- }
943
-
944
- /**
945
- * How long window low-event listeners stay armed after a ceremony settles: focus return and
946
- * picker dismiss animations land shortly after the WebAuthn promise resolves/rejects.
947
- */
948
- declare const CEREMONY_LOW_EVENT_TAIL_MS = 1500;
949
- /**
950
- * Optional diagnostic context for both normal and typed step errors.
951
- *
952
- * Use `rawError` when a library error contains useful context beyond its classified name,
953
- * code and message, such as a nested cause, an error array or a response status.
954
- * Serialization requires SDK config `rawErrors: true` (default true). Config refreshes apply
955
- * to subsequent errors; diagnostics already queued are unchanged.
956
- * It is emitted as a bounded `{ type, value }` envelope in `stepData.rawError` for raw-event
957
- * inspection. The envelope type describes the JavaScript value; the library's own fields
958
- * stay inside value. See {@link serializeRawError} for serialization limits.
959
- *
960
- * @remarks
961
- * The first argument to `.error()` or `.errorTyped()` supplies the classified diagnostic.
962
- * `rawError` does not fill missing classified fields or affect outcomes, error-group assignment
963
- * or severity: a code-only typed error remains code-only even if its raw diagnostic has a name
964
- * and message. Existing StepOptions such as userReference and explicitTimestamp can accompany
965
- * rawError; calls without it behave as before.
966
- *
967
- * Supply a deliberate diagnostic object without credentials, cookies or personal data.
968
- * Arrays retain their structure in rawError; arrays passed directly to `.error()` become a
969
- * string message. Keep the original error for application handling; serialization makes a copy.
970
- *
971
- * @example
972
- * ```ts
973
- * // Normal error with additional provider context.
974
- * passkey.ceremony.error(originalError, { rawError: providerDiagnostic });
975
- *
976
- * // Typed error with the original error available for inspection.
977
- * password.postResponse.errorTyped(
978
- * { code: "invalid_password" },
979
- * { rawError: originalError },
980
- * );
981
- *
982
- * // A classified code and message plus additional raw context.
983
- * password.postResponse.error(
984
- * { code: "invalid_password", name: "AuthenticationError", message: "The password was rejected" },
985
- * { rawError: providerDiagnostic },
986
- * );
987
- * ```
988
- */
989
- type ErrorStepOptions = StepOptions & {
990
- /** Explicit opt-in. Serialized with bounded depth and UTF-8 size; stacks are omitted by default and binary contents are summarized. */
991
- rawError?: unknown;
992
- /** Per-call limits for `rawError` serialization (depth, breadth, string length, cause chain, bytes, stack). See {@link SerializeRawErrorOptions}. */
993
- rawErrorLimits?: SerializeRawErrorOptions;
994
- };
995
- type StepHelper<TStart = {}, TFinished = {}, TTypedError = never> = {
996
- start: (data: TStart, options?: StepOptions) => void;
997
- finished: (data: TFinished, options?: StepOptions) => void;
998
- error: (error: unknown, options?: ErrorStepOptions) => void;
999
- } & ([TTypedError] extends [never] ? {} : {
1000
- errorTyped: (error: TTypedError, options?: ErrorStepOptions) => void;
1001
- });
1002
- declare abstract class OperationFull {
1003
- private tracker;
1004
- private operationName;
1005
- private startReference?;
1006
- private captureSpecType?;
1007
- private captureSessionId?;
1008
- private readonly lowFlushers;
1009
- private readonly lowPrefillCapturers;
1010
- protected lowEventSink(sourceKind: LowEventSourceKind, fieldRole?: LowEventFieldRole): LowEventSink;
1011
- protected createLowCollector<T extends {
1012
- capturePrefill(newCapture?: boolean): void;
1013
- }>(create: () => T): T | undefined;
1014
- protected registerLowFlusher(flush: () => void): void;
1015
- private captureOptions;
1016
- constructor(tracker: CorbadoTracker, operationName: SubflowType);
1017
- /** Anchor (subflowStartEventId) of the current start; undefined before the first start. */
1018
- protected get captureReference(): string | undefined;
1019
- /** Session the current start was tracked under. */
1020
- protected get captureSession(): string | undefined;
1021
- /**
1022
- * Continue an attempt started elsewhere (e.g. on another page of the same session) without
1023
- * emitting a subflow_started: later steps and low events carry the given anchor and session.
1024
- */
1025
- protected adoptCapture(reference: string, sessionId: string, specType?: string): void;
1026
- /**
1027
- * Emits an additional subflow_started; construction already emits the initial start.
1028
- * `data` supports SubflowTrigger fields (`actor`, `explicitSpecType`, `ignoreAsInteraction`)
1029
- * plus free-form extras; see SubflowTrigger for programmatic interaction suppression.
1030
- */
1031
- subflowStart(data: any, options?: StepOptions): void;
1032
- /**
1033
- * Capture values initialized by the application after constructing this operation, without
1034
- * dispatching DOM input events. Call immediately after initialization, before user editing.
1035
- * Each field/group emits at most one prefill per subflow start; values are never recorded.
1036
- */
1037
- capturePrefill(): void;
1038
- private captureInputPrefills;
1039
- /**
1040
- * @deprecated `subflow_trigger` will be removed in the next major version.
1041
- */
1042
- trigger(data: SubflowTrigger, options?: StepOptions): void;
1043
- customStep<TStart = {}, TFinished = {}>(stepName: string): StepHelper<TStart, TFinished>;
1044
- protected subflowStepStarted(stepName: string, data: any, options?: StepOptions, ignoreAsInteraction?: boolean): void;
1045
- protected subflowStepFinished(stepName: string, data: any, options?: StepOptions): void;
1046
- protected subflowStepError(stepName: string, data: any, options?: ErrorStepOptions): void;
1047
- /**
1048
- * Decorate a (ceremony) step so window low-event collection follows its lifecycle: `start` arms
1049
- * the tracker, `finished`/`error`/`errorTyped` schedule disarming after
1050
- * {@link CEREMONY_LOW_EVENT_TAIL_MS}. A `start` during the tail (ceremony retry) keeps the
1051
- * tracker armed.
1052
- */
1053
- protected withWindowLowEvents<S extends StepHelper<never, never, never>>(step: S, windowTracker: LowEventWindowTracker): S;
1054
- protected defineStep<TStart = {}, TFinished = {}, TTypedError = never>(stepName: string, ignoreAsInteractionOnStart?: boolean): StepHelper<TStart, TFinished, TTypedError>;
1055
- }
1056
-
1057
- /** Shared configuration for direct key signing and authority registration. */
1058
- type KeyOperationConfig = {
1059
- /** Reserved for future variants; no spec types are currently defined. */
1060
- explicitSpecType?: undefined;
1061
- };
1062
- declare class KeySigningOperationFull extends OperationFull {
1063
- /** Resolve an eligible key and prepare the input for an actual signing attempt. */
1064
- readonly prepare: StepHelper;
1065
- /** Sign and assemble the usable signed artifact. Does not include submitting it. */
1066
- readonly sign: StepHelper;
1067
- constructor(tracker: CorbadoTracker, config?: KeyOperationConfig);
1068
- }
1069
- declare class KeyRegistrationOperationFull extends OperationFull {
1070
- /** Build the request that will establish the key's authority. */
1071
- readonly prepare: StepHelper;
1072
- /** Submit and await acceptance: finish only when the key is authorized and usable. */
1073
- readonly postResponse: StepHelper;
1074
- constructor(tracker: CorbadoTracker, config?: KeyOperationConfig);
1075
- }
1076
-
1077
821
  type WindowCaptureContext = Pick<LowEvent, "subflowStartEventId" | "fieldRole" | "initiator"> & {
1078
822
  sessionId?: string;
1079
823
  };
@@ -1219,9 +963,867 @@ declare class SessionStorage implements StorageEngine {
1219
963
  removeItem(key: string): void;
1220
964
  }
1221
965
 
1222
- declare const INPUT_HANDOFF: unique symbol;
1223
- declare const WEBAUTHN_PAYLOAD_HANDOFF: unique symbol;
1224
- declare const WEBAUTHN_ERROR_HANDOFF: unique symbol;
966
+ /**
967
+ * Limits for optional raw-error serialization. Modeled on Sentry's client options
968
+ * (`normalizeDepth`, `normalizeMaxBreadth`, `maxValueLength`, `normalizeToSize`, the
969
+ * stack-frame limit and the linked-errors limit) with defaults tuned for an authentication
970
+ * event stream rather than an error monitor. Every value is clamped to {@link RAW_ERROR_BOUNDS};
971
+ * invalid values fall back to the default. A fixed 1024-node budget per depth attempt and
972
+ * incremental text-byte accounting also bound work before the final JSON-size check.
973
+ */
974
+ type SerializeRawErrorOptions = {
975
+ /** Include `stack` strings. Default false. */
976
+ stack?: boolean;
977
+ /** Stack lines kept after the header line when `stack` is on. Default 50 (Sentry: 50). */
978
+ maxStackFrames?: number;
979
+ /** Object nesting depth below the envelope. Default 3 (Sentry `normalizeDepth`: 3). */
980
+ depth?: number;
981
+ /** Keys per object and items per array, Map or Set. Default 30 (Sentry `normalizeMaxBreadth`: 1000). */
982
+ maxBreadth?: number;
983
+ /** Characters kept per string. Default 1024 (Sentry `maxValueLength`: 250). */
984
+ maxValueLength?: number;
985
+ /** `cause` hops followed. Default 3 (Sentry linked errors: 5, Datadog: 10). */
986
+ maxCauseDepth?: number;
987
+ /** Maximum UTF-8 JSON size in bytes. Depth is reduced until the output fits; omit diagnostics that cannot fit. Default 32768 (Sentry `normalizeToSize`: 100 KiB). */
988
+ maxBytes?: number;
989
+ };
990
+ /** Envelope produced by {@link serializeRawError}. */
991
+ type RawErrorEnvelope = {
992
+ /** Class tag of the original value: `DOMException`, `Error`, `Object`, `Response`, `number`, `null`, `unserializable`, … */
993
+ type: string;
994
+ /** Bounded plain-JSON copy of the value; absent when it could not be serialized within the limits. */
995
+ value?: unknown;
996
+ /** Set when even the shallowest serialization exceeded `maxBytes`. */
997
+ truncated?: true;
998
+ };
999
+ type Limits = Required<Omit<SerializeRawErrorOptions, "stack">> & {
1000
+ stack: boolean;
1001
+ };
1002
+ /** Inclusive bounds for every numeric limit; defaults sit inside them. */
1003
+ declare const RAW_ERROR_BOUNDS: {
1004
+ readonly maxStackFrames: {
1005
+ readonly min: 1;
1006
+ readonly max: 100;
1007
+ readonly default: 50;
1008
+ };
1009
+ readonly depth: {
1010
+ readonly min: 0;
1011
+ readonly max: 10;
1012
+ readonly default: 3;
1013
+ };
1014
+ readonly maxBreadth: {
1015
+ readonly min: 1;
1016
+ readonly max: 1000;
1017
+ readonly default: 30;
1018
+ };
1019
+ readonly maxValueLength: {
1020
+ readonly min: 1;
1021
+ readonly max: 10000;
1022
+ readonly default: 1024;
1023
+ };
1024
+ readonly maxCauseDepth: {
1025
+ readonly min: 0;
1026
+ readonly max: 10;
1027
+ readonly default: 3;
1028
+ };
1029
+ readonly maxBytes: {
1030
+ readonly min: 0;
1031
+ readonly max: 65536;
1032
+ readonly default: 32768;
1033
+ };
1034
+ };
1035
+ /** Resolve caller options into clamped limits. Exported for tests and integrations that want to inspect the effective values. */
1036
+ declare function resolveRawErrorLimits(options?: SerializeRawErrorOptions): Limits;
1037
+ /**
1038
+ * Serialize an arbitrary thrown value for the `rawError` diagnostic field.
1039
+ *
1040
+ * Copies standard error fields and serializable own properties within the configured limits.
1041
+ * Standard fields are read through the prototype chain so DOMException and cross-realm errors
1042
+ * serialize. Output is plain JSON, bounded in depth, breadth, string length, cause chain and
1043
+ * UTF-8 size, and never throws.
1044
+ *
1045
+ * The result is an envelope `{ type, value }`: `type` is the value's class tag (`DOMException`,
1046
+ * `Error`, `Object`, `number`, …) and `value` is a bounded diagnostic copy. Keeping the class tag
1047
+ * outside value preserves the library's own `type` field. When the value cannot be serialized
1048
+ * within the limits the envelope carries `truncated: true` or the type `unserializable` and no
1049
+ * `value`.
1050
+ *
1051
+ * Stacks are omitted unless `stack: true`; they carry page URLs and add the most bytes.
1052
+ * Binary data (ArrayBuffer, typed arrays) is reported by type and length only, never by content.
1053
+ *
1054
+ * @param value - Original thrown value or an explicit diagnostic projection.
1055
+ * @param options - Limits; see {@link SerializeRawErrorOptions} for defaults and {@link RAW_ERROR_BOUNDS} for clamping.
1056
+ */
1057
+ declare function serializeRawError(value: unknown, options?: SerializeRawErrorOptions): RawErrorEnvelope | undefined;
1058
+
1059
+ interface TrackerOptions {
1060
+ /** All persisted SDK state and cross-tab locks are isolated by this project id. */
1061
+ projectId: string;
1062
+ apiBaseUrl: string;
1063
+ apiEventPath?: string;
1064
+ /**
1065
+ * Per-field overrides over server config and defaults. A complete policy disables remote fetching.
1066
+ * Data-collection switches (`pmd`) are deprecated here: use {@link TrackerOptions.fixedDataConfig}.
1067
+ */
1068
+ sdkConfig?: SdkReliabilityConfigOverrides;
1069
+ /**
1070
+ * Opt-in: fix the data-collection switches (password-manager and private-mode detection) instead of
1071
+ * taking them from the server config or the cached `cbo_sdk_config_cache`. Batches then carry
1072
+ * `meta.fixedData: true`. Omitted (default): unchanged, server-driven behaviour. See {@link FixedDataConfig}.
1073
+ */
1074
+ fixedDataConfig?: FixedDataConfig;
1075
+ /** Config endpoint override for integrations that proxy Observe under a different path. */
1076
+ apiConfigPath?: string;
1077
+ storage?: "cookie" | "local";
1078
+ cookieDomain?: string;
1079
+ debug?: boolean;
1080
+ logger?: Logger;
1081
+ /** Minimum time between attaching cached device info to events. */
1082
+ deviceInfoDebounceTime?: number;
1083
+ /**
1084
+ * @deprecated No effect: device info is collected with built-in deadlines (a fast snapshot within
1085
+ * 300 ms, slower fields as a later update within 6000 ms). Still accepted so existing integrations
1086
+ * keep compiling. It will be removed in a future release.
1087
+ */
1088
+ deviceInfoCollectorTimeout?: number;
1089
+ defaultTags?: Record<string, string>;
1090
+ /**
1091
+ * Experiment assignments to seed at init (experiment key → variant). Merged over any persisted
1092
+ * assignments and then attached to every event the tracker produces (see {@link CorbadoTracker.setExperiment}).
1093
+ */
1094
+ experiments?: Record<string, string>;
1095
+ /**
1096
+ * Data policy code to seed at init: a project-scoped non-negative integer (0..255) selecting a
1097
+ * policy configured in Corbado (0 is the project default). Overlays any persisted code and is then
1098
+ * sent as `meta.dataPolicy` on every batch (see {@link CorbadoTracker.setDataPolicy}).
1099
+ */
1100
+ dataPolicy?: number;
1101
+ /**
1102
+ * Version of the integration that drives the SDK (e.g. an autocapture bundle `"1.1.22"`), sent as
1103
+ * `sdk.integrationVersion` on every batch so analyses can cohort sessions by integration version.
1104
+ * At most 32 characters of `[0-9A-Za-z.+_-]`; any other value is ignored (logged in debug mode).
1105
+ */
1106
+ integrationVersion?: string;
1107
+ applicationId?: string;
1108
+ /**
1109
+ * @deprecated The flush interval is server-controlled via the SDK reliability config
1110
+ * (`flushIntervalMs`). This option only applies as long as no server config has been received
1111
+ * (i.e. before the first config response is cached); once a server config is cached it wins.
1112
+ * It will be removed in a future release.
1113
+ */
1114
+ flushInterval?: number;
1115
+ }
1116
+ /**
1117
+ * Options of {@link CorbadoTrackerCore} ({@link initCore}). The same as {@link TrackerOptions}, except that
1118
+ * optional features are selected by importing them and passing them in `plugins` instead of by option
1119
+ * values, so a bundle that does not import a feature does not contain its code:
1120
+ *
1121
+ * - `storage: "cookie"` / `cookieDomain` → `plugins: [cookieStorage({ cookieDomain })]`
1122
+ * - `fixedDataConfig.crossOriginSession` → `plugins: [crossOriginSession({ cookieDomain })]` (the core
1123
+ * ignores this field of `fixedDataConfig`; `pmd` and `privateMode` apply as on the full tracker)
1124
+ * - raw-error serialization of `error(e, { rawError })` → `plugins: [rawErrors()]`
1125
+ * - the SDK probe lane (`probe(tracker, input)`) → `plugins: [probes()]`
1126
+ */
1127
+ interface TrackerCoreOptions extends Omit<TrackerOptions, "storage" | "cookieDomain"> {
1128
+ /** Optional features, see {@link TrackerPlugin}. Each is installed once, in array order. */
1129
+ plugins?: readonly TrackerPlugin[];
1130
+ }
1131
+ /**
1132
+ * Storage engine a plugin supplies for the tracker's device-level state (device id, device info cache).
1133
+ * @internal
1134
+ */
1135
+ type TrackerStorageEngine = {
1136
+ engine: StorageEngine;
1137
+ /** Reported as the device info storage source. */
1138
+ source: "cookie";
1139
+ };
1140
+ /**
1141
+ * Session reconciliation a plugin adds to the tracker (the cross-origin session).
1142
+ * @internal
1143
+ */
1144
+ interface SessionBridge {
1145
+ /** Resolve this load's session (at boot and on recovery); replaces the local-only resolution. */
1146
+ resolve(): string;
1147
+ /** Seq to allocate in `sessionId` instead of `seq` (above another origin's reservation). */
1148
+ claim(sessionId: string, seq: number, now: number): number;
1149
+ /** `meta.crossOriginSession` of a batch of `sessionId`. */
1150
+ meta(sessionId: string): "adopted" | "own" | undefined;
1151
+ /** The tracker started a new session. */
1152
+ reset(sessionId: string): void;
1153
+ /** The tracker is destroyed. */
1154
+ stop(): void;
1155
+ }
1156
+ /**
1157
+ * Optional tracker feature for {@link CorbadoTrackerCore}, created by a factory function and passed in
1158
+ * {@link TrackerCoreOptions.plugins}: `cookieStorage()`, `crossOriginSession()`, `rawErrors()`, `probes()`.
1159
+ *
1160
+ * @remarks
1161
+ * The hooks are internal; integrations only pass the objects the factories return. A failing plugin
1162
+ * never breaks the tracker or the host page: its error is logged and the tracker continues without it.
1163
+ * The full {@link CorbadoTracker} ({@link init}) installs every feature its options ask for, so its
1164
+ * behaviour does not depend on plugins.
1165
+ */
1166
+ interface TrackerPlugin {
1167
+ /** @internal Storage engine for the device-level state (default: localStorage). */
1168
+ readonly storage?: (logger: Logger) => TrackerStorageEngine | undefined;
1169
+ /** @internal Session reconciliation; called once the tracker's config and storage exist. */
1170
+ readonly session?: (tracker: CorbadoTrackerCore) => SessionBridge | undefined;
1171
+ /** @internal Raw-error serializer behind `error(e, { rawError })` of the typed operations. */
1172
+ readonly rawErrors?: RawErrorSerializer;
1173
+ /** @internal Runs at the end of the constructor, once the queue exists. */
1174
+ readonly setup?: (tracker: CorbadoTrackerCore) => void;
1175
+ }
1176
+ /** @internal Serializer of the `rawError` option of operation step errors. */
1177
+ type RawErrorSerializer = (value: unknown, options?: SerializeRawErrorOptions) => RawErrorEnvelope | undefined;
1178
+ /**
1179
+ * The part of the tracker every integration runs: sessions, sequencing, the event queue, device info,
1180
+ * flows, subflow steps, low events, telemetry, experiments and data policy. Created by {@link initCore}.
1181
+ *
1182
+ * @remarks
1183
+ * Optional features are standalone functions that take the tracker (typed operations such as
1184
+ * `passkeyLoginFullOperation(tracker, config)`, `setUser(tracker, user)`, `resetSession(tracker)`) or
1185
+ * plugins passed at construction ({@link TrackerCoreOptions.plugins}), so a bundle only contains what it
1186
+ * imports. {@link CorbadoTracker} ({@link init}) extends this class with every feature as a method.
1187
+ *
1188
+ * **Constructor**
1189
+ * - If `apiBaseUrl` is non-empty and missing `http://` or `https://`: logs via `logger.critical` (does not throw).
1190
+ * - If `apiBaseUrl` is non-empty and ends with `/`: logs via `logger.critical` (does not throw).
1191
+ * - Session bootstrap (`resolveSessionId`): on failure logs `Failed to get session id` and continues with an empty session id (does not throw).
1192
+ * - A plugin hook that throws: logs `Failed to install tracker plugin` and continues without it (does not throw).
1193
+ *
1194
+ * **Typed tracking helpers** (`flowStarted`, `flowDecided`, and the other public methods that call `track`)
1195
+ * - Error handling for queued events is defined on {@link CorbadoTrackerCore.track}.
1196
+ */
1197
+ declare class CorbadoTrackerCore {
1198
+ private options;
1199
+ private logger;
1200
+ private queue;
1201
+ private sessionId;
1202
+ private storage;
1203
+ private sessionStorage;
1204
+ /** Dedicated localStorage engine for reliability state (config cache, outbox, continuity session, seq). */
1205
+ private persistentStorage;
1206
+ /** Seq/continuity Web Lock name; project-scoped together with the storage keys it guards. */
1207
+ private readonly seqLockName;
1208
+ /** Current resolved policy. Continuity and persistence stay enabled once activated within a document. */
1209
+ private config;
1210
+ private readonly configManager?;
1211
+ private readonly configOverrides;
1212
+ /** Resolved `fixedDataConfig`; undefined when not given (server-driven data switches). */
1213
+ private readonly fixedData?;
1214
+ private deviceInfoManager;
1215
+ private deviceCollector;
1216
+ /**
1217
+ * Cached per-tab id stamped onto every event's meta (see {@link EventMeta.tabId}). Resolved
1218
+ * lazily from the collector's sessionStorage-backed id; stable for the whole page lifetime.
1219
+ */
1220
+ private eventTabId?;
1221
+ private seq;
1222
+ /**
1223
+ * When the continuity record's `lastActiveAt` was last persisted. Throttles that write inside the
1224
+ * seq critical section (see {@link SESSION_ACTIVITY_WRITE_INTERVAL_MS}). 0 = not written yet on
1225
+ * this load, so the first allocation always persists.
1226
+ */
1227
+ private lastActivityWriteAt;
1228
+ /** Persistent experiment assignments (experiment key → variant), attached to every produced event. */
1229
+ private experiments;
1230
+ /**
1231
+ * Persistent data policy code, stamped into every batch's `meta.dataPolicy` once set. Never
1232
+ * cleared (only overwritten): it survives reloads, session rotation, resetSession and destroy.
1233
+ */
1234
+ private dataPolicy?;
1235
+ /** Self-instrumentation state: re-entrancy guard, readiness, per-load dedupe, and pre-queue buffer. */
1236
+ private telemetryReporting;
1237
+ private telemetryReady;
1238
+ private readonly reportedTelemetryKeys;
1239
+ private pendingSelfTelemetry;
1240
+ private windowObserver?;
1241
+ private passwordManagerSampler?;
1242
+ /** Session reconciliation of a plugin (the cross-origin session); undefined when none is installed. */
1243
+ private bridge?;
1244
+ /** Raw-error serializer of a plugin; undefined = operation step errors drop `rawError`. */
1245
+ private rawErrors?;
1246
+ /** @internal Shared passive page observation and per-operation context registration. */
1247
+ getWindowObserver(): SharedWindowObserver;
1248
+ /**
1249
+ * @param options - Tracker options; `options.plugins` selects the optional features.
1250
+ * @param plugins - Plugins installed before `options.plugins` (used by {@link CorbadoTracker}).
1251
+ */
1252
+ constructor(options: TrackerCoreOptions, plugins?: readonly TrackerPlugin[]);
1253
+ /** Runs `install` per plugin; a missing or throwing plugin is logged and skipped (never throws). */
1254
+ private eachPlugin;
1255
+ /**
1256
+ * Whether this tracker is the full {@link CorbadoTracker} (created by {@link init} or its constructor).
1257
+ * @internal
1258
+ */
1259
+ isFullTracker(): this is CorbadoTracker;
1260
+ /** Apply init overrides on every refresh; continuity and persistence only activate within a document. */
1261
+ private handleConfig;
1262
+ /**
1263
+ * Returns the logger used by this tracker.
1264
+ * @internal
1265
+ */
1266
+ getLogger(): Logger;
1267
+ private applicationTag;
1268
+ /**
1269
+ * Register several experiment assignments at once (experiment key → variant). Additive: existing
1270
+ * assignments for other keys are kept. See {@link CorbadoTracker.setExperiment}.
1271
+ *
1272
+ * Never throws: invalid input is ignored with a debug log.
1273
+ */
1274
+ setExperiments(assignments: Record<string, string>): void;
1275
+ /** Returns a copy of the currently active experiment assignments. */
1276
+ getExperiments(): Record<string, string>;
1277
+ /**
1278
+ * Returns the currently active public SDK configuration, including live updates.
1279
+ *
1280
+ * @returns A frozen snapshot, created fresh on every call.
1281
+ */
1282
+ /** @internal Project-scoped localStorage used by operation helpers (e.g. email-link continuity). */
1283
+ getPersistentStorage(): StorageEngine | undefined;
1284
+ getSdkConfig(): ObserveSdkConfigSnapshot;
1285
+ /**
1286
+ * Set the data policy code for this tracker (e.g. `setDataPolicy(1)` once the user agreed to
1287
+ * extended processing; `setDataPolicy(0)` to return to the project default). Codes are
1288
+ * project-scoped non-negative integers (0..255) selecting a policy configured in Corbado; they
1289
+ * carry no ordering.
1290
+ *
1291
+ * The code is persisted (localStorage, project-scoped) and sent as `meta.dataPolicy` on every
1292
+ * subsequent batch, across reloads and session rotation. It is never cleared, only overwritten.
1293
+ * The server records the latest code it receives for a session (last write wins). Invalid codes
1294
+ * are ignored with a debug log; never throws.
1295
+ */
1296
+ setDataPolicy(code: number): void;
1297
+ /** Returns the current data policy code, or undefined when none has ever been set. */
1298
+ getDataPolicy(): number | undefined;
1299
+ private static isValidDataPolicy;
1300
+ private loadPersistedDataPolicy;
1301
+ private persistDataPolicy;
1302
+ private static isValidExperimentKey;
1303
+ private static isValidExperimentVariant;
1304
+ private loadPersistedExperiments;
1305
+ private persistExperiments;
1306
+ /**
1307
+ * Resolves the experiments to attach to one event: the persistent assignments with any per-call
1308
+ * override merged on top. Returns undefined when there are none (so the field is omitted).
1309
+ */
1310
+ private resolveExperiments;
1311
+ private isTrackingBlocked;
1312
+ /**
1313
+ * Resolve the session of this load: locally ({@link resolveSessionId}), or through the session bridge
1314
+ * of a plugin (cross-origin session) when one is installed. Used at boot and by the recovery in
1315
+ * `getSessionId`.
1316
+ */
1317
+ private resolveSession;
1318
+ private resolveSessionId;
1319
+ /**
1320
+ * Resolve the session id from localStorage so it survives reloads and is shared across tabs of the
1321
+ * same browser. Rotates after `config.sessionInactivityMs` of inactivity (server-controlled,
1322
+ * evaluated at boot), resetting the seq counter.
1323
+ *
1324
+ * Inactivity rotation happens at boot only, here and on the per-tab path {@link resolveSessionId}
1325
+ * takes without continuity. Boot is chosen on an assumption, not a guarantee: that a load
1326
+ * re-announces its flow, so the fresh session id gets a classifiable flow. That holds where a
1327
+ * flow is opened per load. Where one is opened once and carried across loads it does not, and a
1328
+ * boot rotation splits that flow — such a project needs a window long enough to span the journey.
1329
+ * Mid-page the assumption is not even available: nothing re-announces between two tracked events,
1330
+ * so rotating there would leave the started flow unfinished in the old session and the remaining
1331
+ * events without a flow start in the new one — one gap counted as a drop-off, one completion
1332
+ * counted as nothing. `nextSeq` therefore never rotates on inactivity, on either path.
1333
+ */
1334
+ private getContinuitySessionId;
1335
+ /**
1336
+ * Persist the continuity record and remember when, so the throttled refresh in the seq critical
1337
+ * section measures from the last write that actually happened — whoever made it.
1338
+ */
1339
+ private persistContinuitySession;
1340
+ /**
1341
+ * Read the per-tab session record. A bare string is the format that predates dating: it carries no
1342
+ * `lastActiveAt`, so its window can only start on the load that reads it. That load rewrites it in
1343
+ * the dated shape, so a tab converts once and ages normally from then on, and the case drains as
1344
+ * the rollout replaces the bundles that write it.
1345
+ */
1346
+ private readPerTabSession;
1347
+ /**
1348
+ * Persist the per-tab record and remember when, sharing the throttle bookkeeping with the
1349
+ * continuity record — a load resolves its session on one path or the other, never both.
1350
+ *
1351
+ * An explicit timeout override or server config stamps the window. Otherwise carry forward what
1352
+ * the tab already knows, so a defaults boot does not replace a previously configured threshold.
1353
+ */
1354
+ private persistPerTabSession;
1355
+ /** Explicit init timeout wins; otherwise retain the window a prior configured load recorded. */
1356
+ private perTabInactivityMs;
1357
+ /**
1358
+ * Return the next sequence number. With session continuity the counter is persisted so ordering
1359
+ * survives reloads/redirects; the read-increment-write runs under a cross-tab Web Lock
1360
+ * ({@link SEQ_LOCK_NAME}) so two tabs sharing the session cannot allocate the same seq (where Web
1361
+ * Locks are unavailable or exceed the configured timeout it degrades to the historical best-effort merge).
1362
+ * Lock grants are FIFO, so seq order matches `track()` call order within a tab. Tracking also keeps the
1363
+ * continuity session's `lastActiveAt` fresh (throttled, see {@link SESSION_ACTIVITY_WRITE_INTERVAL_MS}),
1364
+ * so the window the NEXT boot evaluates measures real user
1365
+ * inactivity instead of time-since-page-load (a long-lived active tab must not rotate the session
1366
+ * on the next reload). It never rotates the session itself: the inactivity window is evaluated at
1367
+ * boot only ({@link getContinuitySessionId} documents why). Consequence: while a page is never
1368
+ * reloaded — foreground idle, bfcache restore, long-lived SPA tab — a session can outlive
1369
+ * `sessionInactivityMs`. That inflates flow durations but keeps flow counts correct, which is the
1370
+ * better half of the trade. An empty store while this load already has a session id means
1371
+ * persistence is failing (or was cleared); the in-memory id is reused then — never re-minted — so
1372
+ * a broken store degrades to one session per page load instead of one session per event.
1373
+ */
1374
+ private nextSeq;
1375
+ private resolveTrackingSourcePath;
1376
+ /**
1377
+ * Per-tab id for event meta, cached after the first successful resolution: the id is
1378
+ * sessionStorage-backed and stable for the whole page lifetime.
1379
+ */
1380
+ private resolveEventTabId;
1381
+ /** @internal */
1382
+ trackSubflowStarted(subflowType: SubflowType, data: Record<string, any>, options?: StepOptions, eventId?: string): void;
1383
+ /** @internal */
1384
+ trackSubflowTrigger(subflowType: SubflowType, data: Record<string, any>, options?: StepOptions): void;
1385
+ /** @internal */
1386
+ trackSubflowStepStarted(subflowType: SubflowType, stepName: string, data: Record<string, any>, options?: StepOptions, ignoreAsInteraction?: boolean): void;
1387
+ /** @internal */
1388
+ trackSubflowStepFinished(subflowType: SubflowType, stepName: string, data: Record<string, any>, options?: StepOptions): void;
1389
+ /** @internal */
1390
+ trackSubflowStepError(subflowType: SubflowType, stepName: string, data: Record<string, any>, options?: StepOptions): void;
1391
+ /**
1392
+ * Error situations:
1393
+ * - Blocked user agent (see `isBlockedUserAgent`): skip with a debug log and return
1394
+ * - Any error before the event is enqueued (e.g. `JSON.stringify` in debug logging, `queue.enqueue`): log `Failed to process event "<name>" before enqueue`
1395
+ *
1396
+ * @internal
1397
+ */
1398
+ track(name: AuthEventName, data: Record<string, any>, userReference?: UserReference, tags?: Record<string, string>, contexts?: Record<string, any>, explicitTimestamp?: number, experiments?: Record<string, string>, capture?: {
1399
+ id?: string;
1400
+ subflowStartEventId?: string;
1401
+ sessionId?: string;
1402
+ initiator?: StepOptions["initiator"];
1403
+ }): Promise<void>;
1404
+ /**
1405
+ * Track when an authentication flow (or flow selection screen) becomes visible.
1406
+ *
1407
+ * @remarks
1408
+ * Call this once when the user first enters an auth touchpoint (for example account login,
1409
+ * checkout login, or account recovery). If users can choose between multiple flows
1410
+ * (such as login vs signup), pass `flowNames` and optionally `defaultFlowName`.
1411
+ *
1412
+ * The returned handle can attach identity after completion with `await flow.enrich({ userId })`.
1413
+ * Enrichment requires a backend supporting explicit event targeting.
1414
+ *
1415
+ * @param data - Flow metadata, including one flow (`flowName`) or multiple candidates (`flowNames`).
1416
+ * @param tags - Optional key-value tags for filtering and segmentation.
1417
+ * @param experiments - Optional per-call experiment overrides.
1418
+ * @param contexts - Optional structured event context (e.g. technical metadata that is not an
1419
+ * analytical dimension). Written to the event's `contexts` field verbatim.
1420
+ * @param options - Optional `explicitTimestamp` (epoch ms) when the flow became visible earlier than
1421
+ * this call, e.g. because an integration confirms a screen only after it stayed up for a while.
1422
+ *
1423
+ * @example
1424
+ * ```typescript
1425
+ * tracker.flowStarted({
1426
+ * flowNames: ["login", "signup"],
1427
+ * defaultFlowName: "login",
1428
+ * touchpoint: "account",
1429
+ * });
1430
+ * ```
1431
+ */
1432
+ flowStarted(data: FlowStarted | MultiFlowStarted, tags?: Record<string, string>, experiments?: Record<string, string>, contexts?: Record<string, unknown>, options?: Pick<StepOptions, "explicitTimestamp">): FlowHandle;
1433
+ /**
1434
+ * Track when the user commits to a specific flow.
1435
+ *
1436
+ * @remarks
1437
+ * Use this after presenting alternatives and once you know which path the user takes
1438
+ * (for example when identifier checks route to login vs signup).
1439
+ *
1440
+ * @param data - Selected flow name.
1441
+ * @param tags - Optional key-value tags for filtering and segmentation.
1442
+ *
1443
+ * @example
1444
+ * ```typescript
1445
+ * tracker.flowDecided({flowName: "signup"});
1446
+ * ```
1447
+ */
1448
+ flowDecided(data: FlowDecided, tags?: Record<string, string>, experiments?: Record<string, string>): void;
1449
+ /**
1450
+ * Track when a flow successfully completes.
1451
+ *
1452
+ * @remarks
1453
+ * Fire this when the user has finished the target flow end-to-end, such as completed login,
1454
+ * signup, or recovery. Record identity with `setUser()` while the flow is active,
1455
+ * or enrich it after completion through the handle returned by `flowStarted()` or by this call.
1456
+ *
1457
+ * The returned handle targets the flow this event finished, so identity learned only after
1458
+ * completion — for example from a profile request that follows account creation — can be
1459
+ * attached with `await finished.enrich({ userId })` even on a page that never saw the flow start.
1460
+ * Enrichment requires a backend supporting explicit flow-event targeting.
1461
+ *
1462
+ * Legacy identity fields in `data` remain supported but are deprecated.
1463
+ *
1464
+ * @param data - Finished flow name, optional explicit outcome, and deprecated user reference fields.
1465
+ * @param tags - Optional key-value tags for filtering and segmentation.
1466
+ *
1467
+ * @example
1468
+ * ```typescript
1469
+ * const finished = tracker.flowFinished({ flowName: "signup" });
1470
+ * const userId = await hashUserId(createdAccountId);
1471
+ * await finished.enrich({ userId });
1472
+ * ```
1473
+ */
1474
+ flowFinished(data: FlowFinished, tags?: Record<string, string>, experiments?: Record<string, string>): FlowHandle;
1475
+ /** Emits `flow_enriched` against an explicit target, in the session that emitted the target. */
1476
+ private flowHandle;
1477
+ /**
1478
+ * Track when an in-progress flow is reset and restarted.
1479
+ *
1480
+ * @remarks
1481
+ * Use this when users abandon the current path and return to the beginning of the same flow,
1482
+ * for example after switching account/identifier and reopening the first step.
1483
+ *
1484
+ * @param data - Flow name being reset.
1485
+ * @param tags - Optional key-value tags for filtering and segmentation.
1486
+ *
1487
+ * @example
1488
+ * ```typescript
1489
+ * tracker.flowReset({flowName: "login"});
1490
+ * ```
1491
+ */
1492
+ flowReset(data: FlowReset | MultiFlowReset, tags?: Record<string, string>, experiments?: Record<string, string>): void;
1493
+ /**
1494
+ * Track when a flow is considered finished because another flow finished it implicitly.
1495
+ *
1496
+ * @remarks
1497
+ * Use this for automatic completions where no separate explicit finish action happens in the
1498
+ * current flow. Set `flowName` to the auto-finished flow and `finishedByFlowName` to the flow
1499
+ * that caused it. Record identity with `setUser()` while the intended flow is still
1500
+ * current, before it is auto-finished.
1501
+ *
1502
+ * Legacy identity fields in `data` remain supported but are deprecated.
1503
+ *
1504
+ * @param data - Auto-finished flow, finishing flow, and deprecated user reference fields.
1505
+ * @param tags - Optional key-value tags for filtering and segmentation.
1506
+ *
1507
+ * @example
1508
+ * ```typescript
1509
+ * tracker.flowAutoFinished({
1510
+ * flowName: "signup",
1511
+ * finishedByFlowName: "login",
1512
+ * });
1513
+ * ```
1514
+ */
1515
+ flowAutoFinished(data: FlowAutoFinished, tags?: Record<string, string>, experiments?: Record<string, string>): void;
1516
+ /**
1517
+ * Track when you present authentication method choices to the user.
1518
+ *
1519
+ * @remarks
1520
+ * Use this whenever a decision point is shown with a concrete method set, such as
1521
+ * identifier entry options (`d1`) or post-identifier options (`d3`). Set
1522
+ * `explicitDecisionValue` when the options are re-offered after a user action and you want
1523
+ * to capture what triggered that transition.
1524
+ *
1525
+ * @param data - Decision identifier, offered options, and optional transition reason.
1526
+ * @param tags - Optional key-value tags for filtering and segmentation.
1527
+ * @param experiments - Optional per-call experiment assignments.
1528
+ * @param options - Optional explicit event timestamp.
1529
+ *
1530
+ * @example
1531
+ * ```typescript
1532
+ * tracker.authMethodsDecisionStarted({
1533
+ * decisionName: "d3",
1534
+ * options: ["passkey", "social-google", "password", "reset-flow"],
1535
+ * });
1536
+ * ```
1537
+ */
1538
+ authMethodsDecisionStarted(data: AuthMethodDecisionStarted, tags?: Record<string, string>, experiments?: Record<string, string>, options?: Pick<StepOptions, "explicitTimestamp">): void;
1539
+ authMethodsDecisionFinished(data: AuthMethodDecisionFinished, tags?: Record<string, string>, experiments?: Record<string, string>): void;
1540
+ /**
1541
+ * Enqueue a "low" event (granular DOM/window/visualviewport/PWM signal) for the current session.
1542
+ *
1543
+ * @remarks
1544
+ * Low events are sent in the `lows` array of the events endpoint payload, alongside any
1545
+ * pending typed events. Blocked user agents are skipped silently.
1546
+ *
1547
+ * @internal
1548
+ */
1549
+ enqueueLowEvent(low: LowEvent, capturedSessionId?: string): void;
1550
+ /**
1551
+ * Record a diagnostic telemetry entry (a `level` + free-form `message`) for the current session.
1552
+ *
1553
+ * @remarks
1554
+ * Telemetry is delivered in the `telemetry` array of the events endpoint payload, tied to the same
1555
+ * session, and is never classified as an auth-flow event. By default a telemetry entry piggybacks
1556
+ * the next normal flush (it does not trigger one on its own); this is server-controlled. Collection
1557
+ * can be turned off server-side via the `telemetry` config flag. Blocked user agents are skipped.
1558
+ *
1559
+ * The message is truncated to {@link TELEMETRY_MESSAGE_MAX} characters. Never pass credentials or
1560
+ * PII — telemetry is for diagnostics only. Like all SDK entry points, this never throws.
1561
+ */
1562
+ telemetry(level: TelemetryLevel, message: string): void;
1563
+ /**
1564
+ * Queue hook run right before an event batch is sent: a device info snapshot that no event carried
1565
+ * yet (typically the fast snapshot after a burst of events at page load, or the privateMode update)
1566
+ * rides the first event of this page in the batch that has none. Events of other pages (outbox
1567
+ * replays) are never touched. A snapshot no event can carry goes as the batch's request-level device
1568
+ * info instead (queue option `standaloneDeviceInfo`).
1569
+ *
1570
+ * Error situations:
1571
+ * - Any error: log "Failed to attach device info to batch" and send the batch unchanged
1572
+ */
1573
+ private attachUndeliveredDeviceInfo;
1574
+ /**
1575
+ * Escalate an internal SDK diagnostic to the telemetry stream (self-instrumentation). This is the
1576
+ * sink behind {@link Logger.reportTelemetry}; chosen internal failure sites route here so faults
1577
+ * that are otherwise only visible with `debug: true` become observable in the field.
1578
+ *
1579
+ * @remarks
1580
+ * Bounded and deduped per load (a persistent fault — blocked storage, a downed endpoint — cannot
1581
+ * flood the stream), re-entrancy-guarded so it can never recurse, and it never throws into the
1582
+ * host. Diagnostics raised before the queue exists (early boot) are buffered and replayed once the
1583
+ * queue is ready. Messages must be stable and low-cardinality (no raw error objects / PII).
1584
+ */
1585
+ private reportTelemetry;
1586
+ /**
1587
+ * Synchronously flush any pending events and low events via beacon. Use during page-unload
1588
+ * style teardown where async flushing is unreliable.
1589
+ *
1590
+ * @param reason What triggered the flush; recorded as `meta.flushReason` on the batch. Defaults
1591
+ * to a direct call by the host app.
1592
+ *
1593
+ * @internal
1594
+ */
1595
+ flushKeepalive(reason?: FlushReason): void;
1596
+ /**
1597
+ * Keepalive flush requested by a low-event tracker's `pagehide` teardown. Gated by the
1598
+ * server-controlled trigger switch `tlf` (boot-snapshot, default true = historical behavior):
1599
+ * disabling it server-side makes low-event delivery rely solely on the queue's own triggers.
1600
+ *
1601
+ * @internal
1602
+ */
1603
+ lowEventFlushKeepalive(): void;
1604
+ /**
1605
+ * Flush any pending events and release all resources (timers, event listeners).
1606
+ *
1607
+ * @remarks
1608
+ * After calling destroy, the tracker must not be used. Operation objects
1609
+ * returned by factory methods (e.g. `passwordLoginFullOperation`) that hold
1610
+ * DOM references must be destroyed separately by the caller.
1611
+ * The final flush is gated by the server-controlled trigger switch `td` (default true);
1612
+ * resources are released either way.
1613
+ */
1614
+ destroy(): Promise<void>;
1615
+ /**
1616
+ * Return the Observe session id this tracker is currently reporting under.
1617
+ *
1618
+ * @remarks
1619
+ * Use this to route a server-side event into the same session the browser reports to: read the id,
1620
+ * pass it to your own backend, and let the backend use it as the `sessionID` of its ingest call.
1621
+ * Reading it here is the supported path — the storage layout behind it is an implementation detail
1622
+ * that has already changed once (per-tab `sessionStorage` to the cross-tab continuity record).
1623
+ *
1624
+ * The value is **not stable for the lifetime of the page**. It changes on
1625
+ * {@link CorbadoTracker.resetSession}, when this tab adopts a continuity session another tab
1626
+ * rotated to, and when a failed bootstrap recovers. Read it at the moment you need it; never cache
1627
+ * it across a request.
1628
+ *
1629
+ * `undefined` means no session id could be established at all — an environment without Web Crypto,
1630
+ * where tracking is not working either. Skip the server-side event instead of sending an empty id:
1631
+ * the ingest API requires a UUID and would reject the batch.
1632
+ *
1633
+ * @returns The current session id, or `undefined` if none could be established.
1634
+ *
1635
+ * @example
1636
+ * ```typescript
1637
+ * const sessionId = tracker.getSessionId();
1638
+ * if (sessionId) {
1639
+ * await fetch("/api/checkout", {
1640
+ * method: "POST",
1641
+ * body: JSON.stringify({ ...payload, observeSessionId: sessionId }),
1642
+ * });
1643
+ * }
1644
+ * ```
1645
+ */
1646
+ getSessionId(): string | undefined;
1647
+ }
1648
+
1649
+ /**
1650
+ * Where low events go. `flushKeepalive` is requested on `pagehide` teardown so lows batched after
1651
+ * the queue's own lifecycle flush still get out; operations wire it to the client's
1652
+ * `lowEventFlushKeepalive()`, which is gated by the server-controlled `tlf` trigger switch
1653
+ * (default true = historical behavior, can be disabled remotely).
1654
+ */
1655
+ interface LowEventSink {
1656
+ reserveCaptureSeq?(): number;
1657
+ enqueueLowEvent(low: LowEvent): void;
1658
+ flushKeepalive(): void;
1659
+ registerInputs?(fields: readonly HTMLInputElement[], flush: () => void): () => void;
1660
+ beginCeremony?(initiator?: LowEventInitiator): {
1661
+ settle(tailMs: number): void;
1662
+ destroy(): void;
1663
+ };
1664
+ }
1665
+
1666
+ /** Ceremony context lease on the shared observer. Never installs its own window listeners. */
1667
+ declare class LowEventWindowTracker {
1668
+ private logger;
1669
+ private sink;
1670
+ private lease?;
1671
+ private destroyed;
1672
+ constructor(logger: Logger, sink: LowEventSink);
1673
+ arm(initiator?: LowEventInitiator, conditional?: boolean): void;
1674
+ scheduleDisarm(delayMs: number): void;
1675
+ disarm(): void;
1676
+ destroy(): void;
1677
+ }
1678
+
1679
+ /**
1680
+ * How long window low-event listeners stay armed after a ceremony settles: focus return and
1681
+ * picker dismiss animations land shortly after the WebAuthn promise resolves/rejects.
1682
+ */
1683
+ declare const CEREMONY_LOW_EVENT_TAIL_MS = 1500;
1684
+ /**
1685
+ * Optional diagnostic context for both normal and typed step errors.
1686
+ *
1687
+ * Use `rawError` when a library error contains useful context beyond its classified name,
1688
+ * code and message, such as a nested cause, an error array or a response status.
1689
+ * Serialization requires SDK config `rawErrors: true` (default true). Config refreshes apply
1690
+ * to subsequent errors; diagnostics already queued are unchanged.
1691
+ * It is emitted as a bounded `{ type, value }` envelope in `stepData.rawError` for raw-event
1692
+ * inspection. The envelope type describes the JavaScript value; the library's own fields
1693
+ * stay inside value. See {@link serializeRawError} for serialization limits.
1694
+ *
1695
+ * @remarks
1696
+ * The first argument to `.error()` or `.errorTyped()` supplies the classified diagnostic.
1697
+ * `rawError` does not fill missing classified fields or affect outcomes, error-group assignment
1698
+ * or severity: a code-only typed error remains code-only even if its raw diagnostic has a name
1699
+ * and message. Existing StepOptions such as userReference and explicitTimestamp can accompany
1700
+ * rawError; calls without it behave as before.
1701
+ *
1702
+ * Supply a deliberate diagnostic object without credentials, cookies or personal data.
1703
+ * Arrays retain their structure in rawError; arrays passed directly to `.error()` become a
1704
+ * string message. Keep the original error for application handling; serialization makes a copy.
1705
+ *
1706
+ * @example
1707
+ * ```ts
1708
+ * // Normal error with additional provider context.
1709
+ * passkey.ceremony.error(originalError, { rawError: providerDiagnostic });
1710
+ *
1711
+ * // Typed error with the original error available for inspection.
1712
+ * password.postResponse.errorTyped(
1713
+ * { code: "invalid_password" },
1714
+ * { rawError: originalError },
1715
+ * );
1716
+ *
1717
+ * // A classified code and message plus additional raw context.
1718
+ * password.postResponse.error(
1719
+ * { code: "invalid_password", name: "AuthenticationError", message: "The password was rejected" },
1720
+ * { rawError: providerDiagnostic },
1721
+ * );
1722
+ * ```
1723
+ */
1724
+ type ErrorStepOptions = StepOptions & {
1725
+ /** Explicit opt-in. Serialized with bounded depth and UTF-8 size; stacks are omitted by default and binary contents are summarized. */
1726
+ rawError?: unknown;
1727
+ /** Per-call limits for `rawError` serialization (depth, breadth, string length, cause chain, bytes, stack). See {@link SerializeRawErrorOptions}. */
1728
+ rawErrorLimits?: SerializeRawErrorOptions;
1729
+ };
1730
+ type StepHelper<TStart = {}, TFinished = {}, TTypedError = never> = {
1731
+ start: (data: TStart, options?: StepOptions) => void;
1732
+ finished: (data: TFinished, options?: StepOptions) => void;
1733
+ error: (error: unknown, options?: ErrorStepOptions) => void;
1734
+ } & ([TTypedError] extends [never] ? {} : {
1735
+ errorTyped: (error: TTypedError, options?: ErrorStepOptions) => void;
1736
+ });
1737
+ declare abstract class OperationFull {
1738
+ private tracker;
1739
+ private operationName;
1740
+ private startReference?;
1741
+ private captureSpecType?;
1742
+ private captureSessionId?;
1743
+ private readonly lowFlushers;
1744
+ private readonly lowPrefillCapturers;
1745
+ protected lowEventSink(sourceKind: LowEventSourceKind, fieldRole?: LowEventFieldRole): LowEventSink;
1746
+ protected createLowCollector<T extends {
1747
+ capturePrefill(newCapture?: boolean): void;
1748
+ }>(create: () => T): T | undefined;
1749
+ protected registerLowFlusher(flush: () => void): void;
1750
+ private captureOptions;
1751
+ constructor(tracker: CorbadoTrackerCore, operationName: SubflowType);
1752
+ /** Anchor (subflowStartEventId) of the current start; undefined before the first start. */
1753
+ protected get captureReference(): string | undefined;
1754
+ /** Session the current start was tracked under. */
1755
+ protected get captureSession(): string | undefined;
1756
+ /**
1757
+ * Continue an attempt started elsewhere (e.g. on another page of the same session) without
1758
+ * emitting a subflow_started: later steps and low events carry the given anchor and session.
1759
+ */
1760
+ protected adoptCapture(reference: string, sessionId: string, specType?: string): void;
1761
+ /**
1762
+ * Emits an additional subflow_started; construction already emits the initial start.
1763
+ * `data` supports SubflowTrigger fields (`actor`, `explicitSpecType`, `ignoreAsInteraction`)
1764
+ * plus free-form extras; see SubflowTrigger for programmatic interaction suppression.
1765
+ */
1766
+ subflowStart(data: any, options?: StepOptions): void;
1767
+ /**
1768
+ * Capture values initialized by the application after constructing this operation, without
1769
+ * dispatching DOM input events. Call immediately after initialization, before user editing.
1770
+ * Each field/group emits at most one prefill per subflow start; values are never recorded.
1771
+ */
1772
+ capturePrefill(): void;
1773
+ private captureInputPrefills;
1774
+ /**
1775
+ * @deprecated `subflow_trigger` will be removed in the next major version.
1776
+ */
1777
+ trigger(data: SubflowTrigger, options?: StepOptions): void;
1778
+ customStep<TStart = {}, TFinished = {}>(stepName: string): StepHelper<TStart, TFinished>;
1779
+ protected subflowStepStarted(stepName: string, data: any, options?: StepOptions, ignoreAsInteraction?: boolean): void;
1780
+ protected subflowStepFinished(stepName: string, data: any, options?: StepOptions): void;
1781
+ protected subflowStepError(stepName: string, data: any, options?: ErrorStepOptions): void;
1782
+ /**
1783
+ * Decorate a (ceremony) step so window low-event collection follows its lifecycle: `start` arms
1784
+ * the tracker, `finished`/`error`/`errorTyped` schedule disarming after
1785
+ * {@link CEREMONY_LOW_EVENT_TAIL_MS}. A `start` during the tail (ceremony retry) keeps the
1786
+ * tracker armed.
1787
+ */
1788
+ protected withWindowLowEvents<S extends StepHelper<never, never, never>>(step: S, windowTracker: LowEventWindowTracker): S;
1789
+ protected defineStep<TStart = {}, TFinished = {}, TTypedError = never>(stepName: string, ignoreAsInteractionOnStart?: boolean): StepHelper<TStart, TFinished, TTypedError>;
1790
+ }
1791
+
1792
+ /** Shared configuration for direct key signing and authority registration. */
1793
+ type KeyOperationConfig = {
1794
+ /** Reserved for future variants; no spec types are currently defined. */
1795
+ explicitSpecType?: undefined;
1796
+ };
1797
+ declare class KeySigningOperationFull extends OperationFull {
1798
+ /** Resolve an eligible key and prepare the input for an actual signing attempt. */
1799
+ readonly prepare: StepHelper;
1800
+ /** Sign and assemble the usable signed artifact. Does not include submitting it. */
1801
+ readonly sign: StepHelper;
1802
+ constructor(tracker: CorbadoTrackerCore, config?: KeyOperationConfig);
1803
+ }
1804
+ declare class KeyRegistrationOperationFull extends OperationFull {
1805
+ /** Build the request that will establish the key's authority. */
1806
+ readonly prepare: StepHelper;
1807
+ /** Submit and await acceptance: finish only when the key is authorized and usable. */
1808
+ readonly postResponse: StepHelper;
1809
+ constructor(tracker: CorbadoTrackerCore, config?: KeyOperationConfig);
1810
+ }
1811
+ /**
1812
+ * Create a {@link KeySigningOperationFull} for `tracker`: the standalone form of `CorbadoTracker.keySigningOperationFull()`, for trackers
1813
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
1814
+ * Same semantics and documentation as the method.
1815
+ */
1816
+ declare function keySigningOperationFull(tracker: CorbadoTrackerCore, config?: KeyOperationConfig): KeySigningOperationFull;
1817
+ /**
1818
+ * Create a {@link KeyRegistrationOperationFull} for `tracker`: the standalone form of `CorbadoTracker.keyRegistrationOperationFull()`, for trackers
1819
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
1820
+ * Same semantics and documentation as the method.
1821
+ */
1822
+ declare function keyRegistrationOperationFull(tracker: CorbadoTrackerCore, config?: KeyOperationConfig): KeyRegistrationOperationFull;
1823
+
1824
+ declare const INPUT_HANDOFF: unique symbol;
1825
+ declare const WEBAUTHN_PAYLOAD_HANDOFF: unique symbol;
1826
+ declare const WEBAUTHN_ERROR_HANDOFF: unique symbol;
1225
1827
  /**
1226
1828
  * An input element released to the SDK input tracking only (e.g. by `@corbado/autocapture`'s
1227
1829
  * `dom.handoff`). Opaque: it has no readable members, so project code cannot inspect the element
@@ -1315,7 +1917,7 @@ declare class PasskeyLoginOperationFull extends OperationFull {
1315
1917
  readonly ceremony: HandoffStepHelper<PasskeyLoginCeremonyStart, PasskeyLoginCeremonyFinished>;
1316
1918
  readonly postResponse: HandoffStepHelper<PasskeyLoginPostResponseStart>;
1317
1919
  private lowEventTracker;
1318
- constructor(tracker: CorbadoTracker, config?: PasskeyLoginOperationConfig);
1920
+ constructor(tracker: CorbadoTrackerCore, config?: PasskeyLoginOperationConfig);
1319
1921
  /**
1320
1922
  * @deprecated `subflow_trigger` is not supported for passkey-login and will be removed in the
1321
1923
  * next major version.
@@ -1323,6 +1925,12 @@ declare class PasskeyLoginOperationFull extends OperationFull {
1323
1925
  trigger(data: SubflowTrigger, options?: StepOptions): void;
1324
1926
  destroy(): void;
1325
1927
  }
1928
+ /**
1929
+ * Create a {@link PasskeyLoginOperationFull} for `tracker`: the standalone form of `CorbadoTracker.passkeyLoginFullOperation()`, for trackers
1930
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
1931
+ * Same semantics and documentation as the method.
1932
+ */
1933
+ declare function passkeyLoginFullOperation(tracker: CorbadoTrackerCore, config?: PasskeyLoginOperationConfig): PasskeyLoginOperationFull;
1326
1934
 
1327
1935
  type EmailOTPOperationSpecType = "email-otp-login" | "email-otp-enrollment";
1328
1936
  type EmailOTPOperationSendOTPStart = {
@@ -1344,7 +1952,7 @@ declare class EmailOtpOperationFull extends OperationFull {
1344
1952
  readonly send: StepHelper<EmailOTPOperationSendOTPStart>;
1345
1953
  readonly postResponse: StepHelper<EmailOTPOperationPostResponseStart>;
1346
1954
  readonly resend: StepHelper;
1347
- constructor(tracker: CorbadoTracker, config?: EmailOTPOperationConfig);
1955
+ constructor(tracker: CorbadoTrackerCore, config?: EmailOTPOperationConfig);
1348
1956
  /**
1349
1957
  * Rebind the ordered OTP group without starting a new subflow. An empty list detaches it.
1350
1958
  * Also takes opaque {@link SdkInputHandoff}s (additive overload); at runtime they are the input elements.
@@ -1353,6 +1961,13 @@ declare class EmailOtpOperationFull extends OperationFull {
1353
1961
  setInputFields(fields: readonly HTMLInputElement[]): void;
1354
1962
  destroy(): void;
1355
1963
  }
1964
+ /**
1965
+ * Create a {@link EmailOtpOperationFull} for `tracker`: the standalone form of `CorbadoTracker.emailOtpOperationFull()`, for trackers
1966
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
1967
+ * Same semantics and documentation as the method.
1968
+ */
1969
+ declare function emailOtpOperationFull(tracker: CorbadoTrackerCore, config?: WithHandoffs<EmailOTPOperationConfig>): EmailOtpOperationFull;
1970
+ declare function emailOtpOperationFull(tracker: CorbadoTrackerCore, config?: EmailOTPOperationConfig): EmailOtpOperationFull;
1356
1971
 
1357
1972
  type SmsOTPOperationSpecType = "sms-otp-login" | "sms-otp-enrollment";
1358
1973
  type SmsOTPOperationPostResponseStart = {
@@ -1369,7 +1984,7 @@ declare class SmsOtpOperationFull extends OperationFull {
1369
1984
  readonly send: StepHelper;
1370
1985
  readonly postResponse: StepHelper<SmsOTPOperationPostResponseStart>;
1371
1986
  readonly resend: StepHelper;
1372
- constructor(tracker: CorbadoTracker, config?: SmsOTPOperationConfig);
1987
+ constructor(tracker: CorbadoTrackerCore, config?: SmsOTPOperationConfig);
1373
1988
  /**
1374
1989
  * Rebind the ordered OTP group without starting a new subflow. An empty list detaches it.
1375
1990
  * Also takes opaque {@link SdkInputHandoff}s (additive overload); at runtime they are the input elements.
@@ -1378,6 +1993,13 @@ declare class SmsOtpOperationFull extends OperationFull {
1378
1993
  setInputFields(fields: readonly HTMLInputElement[]): void;
1379
1994
  destroy(): void;
1380
1995
  }
1996
+ /**
1997
+ * Create a {@link SmsOtpOperationFull} for `tracker`: the standalone form of `CorbadoTracker.smsOtpOperationFull()`, for trackers
1998
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
1999
+ * Same semantics and documentation as the method.
2000
+ */
2001
+ declare function smsOtpOperationFull(tracker: CorbadoTrackerCore, config?: WithHandoffs<SmsOTPOperationConfig>): SmsOtpOperationFull;
2002
+ declare function smsOtpOperationFull(tracker: CorbadoTrackerCore, config?: SmsOTPOperationConfig): SmsOtpOperationFull;
1381
2003
 
1382
2004
  type EmailLinkOperationSpecType = "email-link-login" | "email-link-enrollment";
1383
2005
  type EmailLinkOperationSendStart = {
@@ -1416,7 +2038,7 @@ declare class EmailLinkOperationFull extends OperationFull {
1416
2038
  readonly resend: StepHelper;
1417
2039
  /** Transaction ID of this email link; hand it to the page that continues it. */
1418
2040
  readonly transactionId: string;
1419
- constructor(tracker: CorbadoTracker, config?: EmailLinkOperationConfig);
2041
+ constructor(tracker: CorbadoTrackerCore, config?: EmailLinkOperationConfig);
1420
2042
  }
1421
2043
  /**
1422
2044
  * Page 2 of an email-link journey (the link's target): continues the `email-link` subflow started
@@ -1442,7 +2064,7 @@ declare class EmailLinkContinuationOperation extends OperationFull {
1442
2064
  private deferred;
1443
2065
  private readonly onPageHide;
1444
2066
  private removePageHide?;
1445
- constructor(tracker: CorbadoTracker, config?: EmailLinkContinuationConfig);
2067
+ constructor(tracker: CorbadoTrackerCore, config?: EmailLinkContinuationConfig);
1446
2068
  /** Transaction ID of the continued email link, when known. */
1447
2069
  get transactionId(): string | undefined;
1448
2070
  /**
@@ -1461,6 +2083,18 @@ declare class EmailLinkContinuationOperation extends OperationFull {
1461
2083
  /** Defer step calls until the detached start is emitted; mark the continued link on completion. */
1462
2084
  private deferrable;
1463
2085
  }
2086
+ /**
2087
+ * Create a {@link EmailLinkOperationFull} for `tracker`: the standalone form of `CorbadoTracker.emailLinkOperationFull()`, for trackers
2088
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
2089
+ * Same semantics and documentation as the method.
2090
+ */
2091
+ declare function emailLinkOperationFull(tracker: CorbadoTrackerCore, config?: EmailLinkOperationConfig): EmailLinkOperationFull;
2092
+ /**
2093
+ * Create a {@link EmailLinkContinuationOperation} for `tracker`: the standalone form of `CorbadoTracker.continueEmailLinkOperation()`, for trackers
2094
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
2095
+ * Same semantics and documentation as the method.
2096
+ */
2097
+ declare function continueEmailLinkOperation(tracker: CorbadoTrackerCore, config?: EmailLinkContinuationConfig): EmailLinkContinuationOperation;
1464
2098
 
1465
2099
  /**
1466
2100
  * Passkey-enrollment spec types. Two vocabularies coexist:
@@ -1516,9 +2150,15 @@ declare class PasskeyEnrollmentOperationFull extends OperationFull {
1516
2150
  readonly ceremony: HandoffStepHelper<PasskeyEnrollmentCeremonyStart, PasskeyEnrollmentCeremonyFinished>;
1517
2151
  readonly postResponse: HandoffStepHelper<PasskeyEnrollmentPostResponseStart>;
1518
2152
  private lowEventTracker;
1519
- constructor(tracker: CorbadoTracker, config?: PasskeyEnrollmentOperationConfig);
2153
+ constructor(tracker: CorbadoTrackerCore, config?: PasskeyEnrollmentOperationConfig);
1520
2154
  destroy(): void;
1521
2155
  }
2156
+ /**
2157
+ * Create a {@link PasskeyEnrollmentOperationFull} for `tracker`: the standalone form of `CorbadoTracker.passkeyEnrollmentFullOperation()`, for trackers
2158
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
2159
+ * Same semantics and documentation as the method.
2160
+ */
2161
+ declare function passkeyEnrollmentFullOperation(tracker: CorbadoTrackerCore, config?: PasskeyEnrollmentOperationConfig): PasskeyEnrollmentOperationFull;
1522
2162
 
1523
2163
  /** The user dismissed the confirmation dialog without confirming the deletion. */
1524
2164
  type PasskeyDeletionUserConfirmationTypedError = {
@@ -1535,8 +2175,14 @@ declare class PasskeyDeletionOperationFull extends OperationFull {
1535
2175
  readonly userConfirmation: StepHelper<{}, {}, PasskeyDeletionUserConfirmationTypedError>;
1536
2176
  /** The deletion request: finish only when the passkey was actually deleted. */
1537
2177
  readonly deletion: StepHelper<{}, {}, PasskeyDeletionDeletionTypedError>;
1538
- constructor(tracker: CorbadoTracker, _config?: PasskeyDeletionOperationConfig);
2178
+ constructor(tracker: CorbadoTrackerCore, _config?: PasskeyDeletionOperationConfig);
1539
2179
  }
2180
+ /**
2181
+ * Create a {@link PasskeyDeletionOperationFull} for `tracker`: the standalone form of `CorbadoTracker.passkeyDeletionOperationFull()`, for trackers
2182
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
2183
+ * Same semantics and documentation as the method.
2184
+ */
2185
+ declare function passkeyDeletionOperationFull(tracker: CorbadoTrackerCore, config?: PasskeyDeletionOperationConfig): PasskeyDeletionOperationFull;
1540
2186
 
1541
2187
  type PasswordLoginTypedError = {
1542
2188
  code: PasswordLoginTypedErrorCode;
@@ -1588,7 +2234,7 @@ declare class PasswordLoginOperationFull extends OperationFull {
1588
2234
  };
1589
2235
  private lowEventTracker?;
1590
2236
  private identifierLowEventTracker?;
1591
- constructor(tracker: CorbadoTracker, config?: PasswordLoginConfig);
2237
+ constructor(tracker: CorbadoTrackerCore, config?: PasswordLoginConfig);
1592
2238
  /**
1593
2239
  * @deprecated `subflow_trigger` is not supported for password-login and will be removed in the
1594
2240
  * next major version.
@@ -1596,6 +2242,13 @@ declare class PasswordLoginOperationFull extends OperationFull {
1596
2242
  trigger(data: SubflowTrigger, options?: StepOptions): void;
1597
2243
  destroy(): void;
1598
2244
  }
2245
+ /**
2246
+ * Create a {@link PasswordLoginOperationFull} for `tracker`: the standalone form of `CorbadoTracker.passwordLoginFullOperation()`, for trackers
2247
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
2248
+ * Same semantics and documentation as the method.
2249
+ */
2250
+ declare function passwordLoginFullOperation(tracker: CorbadoTrackerCore, config?: WithHandoffs<PasswordLoginConfig>): PasswordLoginOperationFull;
2251
+ declare function passwordLoginFullOperation(tracker: CorbadoTrackerCore, config?: PasswordLoginConfig): PasswordLoginOperationFull;
1599
2252
 
1600
2253
  type PasswordEnrollmentTypedError = {
1601
2254
  code: PasswordEnrollmentTypedErrorCode;
@@ -1612,9 +2265,16 @@ declare class PasswordEnrollmentOperationFull extends OperationFull {
1612
2265
  readonly clientValidation: StepHelper;
1613
2266
  readonly postResponse: StepHelper<{}, {}, PasswordEnrollmentTypedError>;
1614
2267
  private lowEventTracker?;
1615
- constructor(tracker: CorbadoTracker, config?: PasswordEnrollmentConfig);
2268
+ constructor(tracker: CorbadoTrackerCore, config?: PasswordEnrollmentConfig);
1616
2269
  destroy(): void;
1617
2270
  }
2271
+ /**
2272
+ * Create a {@link PasswordEnrollmentOperationFull} for `tracker`: the standalone form of `CorbadoTracker.passwordEnrollmentFullOperation()`, for trackers
2273
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
2274
+ * Same semantics and documentation as the method.
2275
+ */
2276
+ declare function passwordEnrollmentFullOperation(tracker: CorbadoTrackerCore, config?: WithHandoffs<PasswordEnrollmentConfig>): PasswordEnrollmentOperationFull;
2277
+ declare function passwordEnrollmentFullOperation(tracker: CorbadoTrackerCore, config?: PasswordEnrollmentConfig): PasswordEnrollmentOperationFull;
1618
2278
 
1619
2279
  type PasskeyLoginCUITypedError = {
1620
2280
  code: PasskeyLoginCUITypedErrorCode;
@@ -1658,9 +2318,16 @@ declare class OperationFullProvideIdentifierWithCUI extends OperationFull {
1658
2318
  clientValidation: StepHelper;
1659
2319
  postResponse: StepHelper<ProvideIdentifierPostResponseStart>;
1660
2320
  };
1661
- constructor(tracker: CorbadoTracker, config?: OperationFullProvideIdentifierWithCUIConfig);
2321
+ constructor(tracker: CorbadoTrackerCore, config?: OperationFullProvideIdentifierWithCUIConfig);
1662
2322
  destroy(): void;
1663
2323
  }
2324
+ /**
2325
+ * Create a {@link OperationFullProvideIdentifierWithCUI} for `tracker`: the standalone form of `CorbadoTracker.provideIdentifierOperationFull()`, for trackers
2326
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
2327
+ * Same semantics and documentation as the method.
2328
+ */
2329
+ declare function provideIdentifierOperationFull(tracker: CorbadoTrackerCore, config?: WithHandoffs<OperationFullProvideIdentifierWithCUIConfig>): OperationFullProvideIdentifierWithCUI;
2330
+ declare function provideIdentifierOperationFull(tracker: CorbadoTrackerCore, config?: OperationFullProvideIdentifierWithCUIConfig): OperationFullProvideIdentifierWithCUI;
1664
2331
 
1665
2332
  type SocialLoginSpecType = "pre-identifier" | "post-identifier";
1666
2333
  /**
@@ -1689,8 +2356,14 @@ type SocialLoginOperationConfig = {
1689
2356
  declare class SocialLoginOperationFull extends OperationFull {
1690
2357
  readonly getRedirectUrl: StepHelper<SocialLoginGetRedirectUrlStart, SocialLoginGetRedirectUrlFinished>;
1691
2358
  readonly exchangeCode: StepHelper<SocialLoginExchangeCodeStart, SocialLoginExchangeCodeFinished>;
1692
- constructor(tracker: CorbadoTracker, config?: SocialLoginOperationConfig);
2359
+ constructor(tracker: CorbadoTrackerCore, config?: SocialLoginOperationConfig);
1693
2360
  }
2361
+ /**
2362
+ * Create a {@link SocialLoginOperationFull} for `tracker`: the standalone form of `CorbadoTracker.socialLoginOperationFull()`, for trackers
2363
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
2364
+ * Same semantics and documentation as the method.
2365
+ */
2366
+ declare function socialLoginOperationFull(tracker: CorbadoTrackerCore, config?: SocialLoginOperationConfig): SocialLoginOperationFull;
1694
2367
 
1695
2368
  type SsoLoginSpecType = "pre-identifier" | "post-identifier";
1696
2369
  type SsoLoginGetRedirectUrlStart = {
@@ -1711,8 +2384,14 @@ type SsoLoginOperationConfig = {
1711
2384
  declare class SsoLoginOperationFull extends OperationFull {
1712
2385
  readonly getRedirectUrl: StepHelper<SsoLoginGetRedirectUrlStart, SsoLoginGetRedirectUrlFinished>;
1713
2386
  readonly exchangeCode: StepHelper<SsoLoginExchangeCodeStart, SsoLoginExchangeCodeFinished>;
1714
- constructor(tracker: CorbadoTracker, config?: SsoLoginOperationConfig);
2387
+ constructor(tracker: CorbadoTrackerCore, config?: SsoLoginOperationConfig);
1715
2388
  }
2389
+ /**
2390
+ * Create a {@link SsoLoginOperationFull} for `tracker`: the standalone form of `CorbadoTracker.ssoLoginOperationFull()`, for trackers
2391
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
2392
+ * Same semantics and documentation as the method.
2393
+ */
2394
+ declare function ssoLoginOperationFull(tracker: CorbadoTrackerCore, config?: SsoLoginOperationConfig): SsoLoginOperationFull;
1716
2395
 
1717
2396
  type TotpOperationSpecType = "totp-login" | "totp-enrollment";
1718
2397
  type TotpOperationPostResponseStart = {
@@ -1727,7 +2406,7 @@ type TotpOperationConfig = {
1727
2406
  declare class TotpOperationFull extends OperationFull {
1728
2407
  private lowEventTracker?;
1729
2408
  readonly postResponse: StepHelper<TotpOperationPostResponseStart>;
1730
- constructor(tracker: CorbadoTracker, config?: TotpOperationConfig);
2409
+ constructor(tracker: CorbadoTrackerCore, config?: TotpOperationConfig);
1731
2410
  /**
1732
2411
  * Rebind the ordered code input group without starting a new subflow. An empty list detaches it.
1733
2412
  * Also takes opaque {@link SdkInputHandoff}s (additive overload); at runtime they are the input elements.
@@ -1736,6 +2415,13 @@ declare class TotpOperationFull extends OperationFull {
1736
2415
  setInputFields(fields: readonly HTMLInputElement[]): void;
1737
2416
  destroy(): void;
1738
2417
  }
2418
+ /**
2419
+ * Create a {@link TotpOperationFull} for `tracker`: the standalone form of `CorbadoTracker.totpOperationFull()`, for trackers
2420
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
2421
+ * Same semantics and documentation as the method.
2422
+ */
2423
+ declare function totpOperationFull(tracker: CorbadoTrackerCore, config?: WithHandoffs<TotpOperationConfig>): TotpOperationFull;
2424
+ declare function totpOperationFull(tracker: CorbadoTrackerCore, config?: TotpOperationConfig): TotpOperationFull;
1739
2425
 
1740
2426
  /** How the confirmation is reached: a QR handoff, an app on the browser's device, or a push to an already-enrolled device. */
1741
2427
  type AppConfirmationOperationSpecType = "qr-code" | "same-device" | "push";
@@ -1755,8 +2441,14 @@ declare class AppConfirmationOperationFull extends OperationFull {
1755
2441
  readonly retry: StepHelper;
1756
2442
  /** Optional separate browser exchange after approval; omit when the final poll already proves acceptance. */
1757
2443
  readonly postResponse: StepHelper;
1758
- constructor(tracker: CorbadoTracker, config?: AppConfirmationOperationConfig);
2444
+ constructor(tracker: CorbadoTrackerCore, config?: AppConfirmationOperationConfig);
1759
2445
  }
2446
+ /**
2447
+ * Create a {@link AppConfirmationOperationFull} for `tracker`: the standalone form of `CorbadoTracker.appConfirmationOperationFull()`, for trackers
2448
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
2449
+ * Same semantics and documentation as the method.
2450
+ */
2451
+ declare function appConfirmationOperationFull(tracker: CorbadoTrackerCore, config?: AppConfirmationOperationConfig): AppConfirmationOperationFull;
1760
2452
 
1761
2453
  /**
1762
2454
  * Which captcha widget the integration observed.
@@ -1772,8 +2464,14 @@ declare class CaptchaOperationFull extends OperationFull {
1772
2464
  readonly ceremony: StepHelper;
1773
2465
  /** Submission of the captcha token and the server's verdict on it. */
1774
2466
  readonly postResponse: StepHelper;
1775
- constructor(tracker: CorbadoTracker, config?: CaptchaOperationConfig);
2467
+ constructor(tracker: CorbadoTrackerCore, config?: CaptchaOperationConfig);
1776
2468
  }
2469
+ /**
2470
+ * Create a {@link CaptchaOperationFull} for `tracker`: the standalone form of `CorbadoTracker.captchaOperationFull()`, for trackers
2471
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
2472
+ * Same semantics and documentation as the method.
2473
+ */
2474
+ declare function captchaOperationFull(tracker: CorbadoTrackerCore, config?: CaptchaOperationConfig): CaptchaOperationFull;
1777
2475
 
1778
2476
  type FormOperationConfig = {
1779
2477
  /**
@@ -1808,7 +2506,7 @@ declare class FormOperationFull extends OperationFull {
1808
2506
  /** The user leaves the form forward without submitting it. */
1809
2507
  readonly skip: StepHelper;
1810
2508
  private readonly inputBinding?;
1811
- constructor(tracker: CorbadoTracker, config: FormOperationConfig);
2509
+ constructor(tracker: CorbadoTrackerCore, config: FormOperationConfig);
1812
2510
  /**
1813
2511
  * Bind the fields the form shows now, without starting a new subflow. An empty list detaches all.
1814
2512
  * Also takes opaque {@link SdkInputHandoff}s (additive overload); at runtime they are the input elements.
@@ -1817,6 +2515,13 @@ declare class FormOperationFull extends OperationFull {
1817
2515
  setInputFields(fields: readonly HTMLInputElement[]): void;
1818
2516
  destroy(): void;
1819
2517
  }
2518
+ /**
2519
+ * Create a {@link FormOperationFull} for `tracker`: the standalone form of `CorbadoTracker.formOperationFull()`, for trackers
2520
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
2521
+ * Same semantics and documentation as the method.
2522
+ */
2523
+ declare function formOperationFull(tracker: CorbadoTrackerCore, config: WithHandoffs<FormOperationConfig>): FormOperationFull;
2524
+ declare function formOperationFull(tracker: CorbadoTrackerCore, config: FormOperationConfig): FormOperationFull;
1820
2525
 
1821
2526
  type TrustedDevicePurpose = "additional-verification" | "mfa-exemption";
1822
2527
  type TrustedDeviceStorage = "cookie" | "indexeddb" | "localstore" | "sessionstore";
@@ -1861,7 +2566,7 @@ declare class TrustedDeviceCheckOperationFull extends OperationFull {
1861
2566
  readonly getOptions: StepHelper<{}, TrustedDeviceCheckStepResult, TrustedDeviceCheckTypedError>;
1862
2567
  readonly ceremony: StepHelper<{}, TrustedDeviceCheckStepResult, TrustedDeviceCheckTypedError>;
1863
2568
  readonly postResponse: StepHelper<{}, TrustedDeviceCheckResult, TrustedDeviceCheckTypedError>;
1864
- constructor(tracker: CorbadoTracker, config: TrustedDeviceCheckConfig);
2569
+ constructor(tracker: CorbadoTrackerCore, config: TrustedDeviceCheckConfig);
1865
2570
  private checkStep;
1866
2571
  }
1867
2572
  /** Finish registration/renewal after host acceptance. Explicit user opt-out reports skipped without creating a binding. */
@@ -1869,8 +2574,20 @@ declare class TrustedDeviceEnrollmentOperationFull extends OperationFull {
1869
2574
  readonly getOptions: StepHelper<{}, {}>;
1870
2575
  readonly ceremony: StepHelper<{}, {}>;
1871
2576
  readonly postResponse: StepHelper<{}, TrustedDeviceEnrollmentResult>;
1872
- constructor(tracker: CorbadoTracker, config: TrustedDeviceOperationConfig);
2577
+ constructor(tracker: CorbadoTrackerCore, config: TrustedDeviceOperationConfig);
1873
2578
  }
2579
+ /**
2580
+ * Create a {@link TrustedDeviceCheckOperationFull} for `tracker`: the standalone form of `CorbadoTracker.trustedDeviceCheckOperationFull()`, for trackers
2581
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
2582
+ * Same semantics and documentation as the method.
2583
+ */
2584
+ declare function trustedDeviceCheckOperationFull(tracker: CorbadoTrackerCore, config: TrustedDeviceCheckConfig): TrustedDeviceCheckOperationFull;
2585
+ /**
2586
+ * Create a {@link TrustedDeviceEnrollmentOperationFull} for `tracker`: the standalone form of `CorbadoTracker.trustedDeviceEnrollmentOperationFull()`, for trackers
2587
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
2588
+ * Same semantics and documentation as the method.
2589
+ */
2590
+ declare function trustedDeviceEnrollmentOperationFull(tracker: CorbadoTrackerCore, config: TrustedDeviceOperationConfig): TrustedDeviceEnrollmentOperationFull;
1874
2591
 
1875
2592
  type ProvideDataOperationSpecType = "signup" | "login" | "recovery" | "enrollment";
1876
2593
  type ProvideDataOperationStart = {
@@ -1881,293 +2598,61 @@ type ProvideDataOperationStart = {
1881
2598
  };
1882
2599
  type ProvideDataOperationConfig = ProvideDataOperationStart & {
1883
2600
  /** The input field whose low-level interaction signals should be collected. */
1884
- inputHtmlField?: HTMLInputElement;
1885
- };
1886
- type ProvideDataOperationPostResponseStart = {
1887
- explicitSpecType?: ProvideDataOperationSpecType;
1888
- };
1889
- /** Tracks a user-triggered data submission and its server response. */
1890
- declare class ProvideDataOperationFull extends OperationFull {
1891
- readonly clientValidation: StepHelper;
1892
- readonly postResponse: StepHelper<ProvideDataOperationPostResponseStart>;
1893
- private lowEventTracker?;
1894
- constructor(tracker: CorbadoTracker, config?: ProvideDataOperationConfig);
1895
- destroy(): void;
1896
- }
1897
-
1898
- interface TrackerOptions {
1899
- /** All persisted SDK state and cross-tab locks are isolated by this project id. */
1900
- projectId: string;
1901
- apiBaseUrl: string;
1902
- apiEventPath?: string;
1903
- /**
1904
- * Per-field overrides over server config and defaults. A complete policy disables remote fetching.
1905
- * Data-collection switches (`pmd`) are deprecated here: use {@link TrackerOptions.fixedDataConfig}.
1906
- */
1907
- sdkConfig?: SdkReliabilityConfigOverrides;
1908
- /**
1909
- * Opt-in: fix the data-collection switches (password-manager and private-mode detection) instead of
1910
- * taking them from the server config or the cached `cbo_sdk_config_cache`. Batches then carry
1911
- * `meta.fixedData: true`. Omitted (default): unchanged, server-driven behaviour. See {@link FixedDataConfig}.
1912
- */
1913
- fixedDataConfig?: FixedDataConfig;
1914
- /** Config endpoint override for integrations that proxy Observe under a different path. */
1915
- apiConfigPath?: string;
1916
- storage?: "cookie" | "local";
1917
- cookieDomain?: string;
1918
- debug?: boolean;
1919
- logger?: Logger;
1920
- /** Minimum time between attaching cached device info to events. */
1921
- deviceInfoDebounceTime?: number;
1922
- /**
1923
- * @deprecated No effect: device info is collected with built-in deadlines (a fast snapshot within
1924
- * 300 ms, slower fields as a later update within 6000 ms). Still accepted so existing integrations
1925
- * keep compiling. It will be removed in a future release.
1926
- */
1927
- deviceInfoCollectorTimeout?: number;
1928
- defaultTags?: Record<string, string>;
1929
- /**
1930
- * Experiment assignments to seed at init (experiment key → variant). Merged over any persisted
1931
- * assignments and then attached to every event the tracker produces (see {@link CorbadoTracker.setExperiment}).
1932
- */
1933
- experiments?: Record<string, string>;
1934
- /**
1935
- * Data policy code to seed at init: a project-scoped non-negative integer (0..255) selecting a
1936
- * policy configured in Corbado (0 is the project default). Overlays any persisted code and is then
1937
- * sent as `meta.dataPolicy` on every batch (see {@link CorbadoTracker.setDataPolicy}).
1938
- */
1939
- dataPolicy?: number;
1940
- /**
1941
- * Version of the integration that drives the SDK (e.g. an autocapture bundle `"1.1.22"`), sent as
1942
- * `sdk.integrationVersion` on every batch so analyses can cohort sessions by integration version.
1943
- * At most 32 characters of `[0-9A-Za-z.+_-]`; any other value is ignored (logged in debug mode).
1944
- */
1945
- integrationVersion?: string;
1946
- applicationId?: string;
1947
- /**
1948
- * @deprecated The flush interval is server-controlled via the SDK reliability config
1949
- * (`flushIntervalMs`). This option only applies as long as no server config has been received
1950
- * (i.e. before the first config response is cached); once a server config is cached it wins.
1951
- * It will be removed in a future release.
1952
- */
1953
- flushInterval?: number;
1954
- }
1955
- declare class CorbadoTracker {
1956
- private options;
1957
- private logger;
1958
- private queue;
1959
- private sessionId;
1960
- private storage;
1961
- private sessionStorage;
1962
- /** Dedicated localStorage engine for reliability state (config cache, outbox, continuity session, seq). */
1963
- private persistentStorage;
1964
- /** Seq/continuity Web Lock name; project-scoped together with the storage keys it guards. */
1965
- private readonly seqLockName;
1966
- /** Current resolved policy. Continuity and persistence stay enabled once activated within a document. */
1967
- private config;
1968
- private readonly configManager?;
1969
- private readonly configOverrides;
1970
- /** Resolved `fixedDataConfig`; undefined when not given (server-driven data switches). */
1971
- private readonly fixedData?;
1972
- private deviceInfoManager;
1973
- private deviceCollector;
1974
- /**
1975
- * Cached per-tab id stamped onto every event's meta (see {@link EventMeta.tabId}). Resolved
1976
- * lazily from the collector's sessionStorage-backed id; stable for the whole page lifetime.
1977
- */
1978
- private eventTabId?;
1979
- private seq;
1980
- /**
1981
- * When the continuity record's `lastActiveAt` was last persisted. Throttles that write inside the
1982
- * seq critical section (see {@link SESSION_ACTIVITY_WRITE_INTERVAL_MS}). 0 = not written yet on
1983
- * this load, so the first allocation always persists.
1984
- */
1985
- private lastActivityWriteAt;
1986
- /** Persistent experiment assignments (experiment key → variant), attached to every produced event. */
1987
- private experiments;
1988
- /**
1989
- * Persistent data policy code, stamped into every batch's `meta.dataPolicy` once set. Never
1990
- * cleared (only overwritten): it survives reloads, session rotation, resetSession and destroy.
1991
- */
1992
- private dataPolicy?;
1993
- /** Self-instrumentation state: re-entrancy guard, readiness, per-load dedupe, and pre-queue buffer. */
1994
- private telemetryReporting;
1995
- private telemetryReady;
1996
- private readonly reportedTelemetryKeys;
1997
- private pendingSelfTelemetry;
1998
- /** Default probe page id (one per tracker instance) and the probe seq counter per page id. */
1999
- private probePageId?;
2000
- private readonly probeSeqs;
2001
- private windowObserver?;
2002
- private passwordManagerSampler?;
2003
- /** Cross-origin session cookie (`fixedDataConfig.crossOriginSession`); undefined when off. */
2004
- private crossOrigin?;
2005
- /** The session this load took from the cross-origin cookie, if any (`meta.crossOriginSession`). */
2006
- private crossOriginAdoptedId?;
2007
- /** @internal Shared passive page observation and per-operation context registration. */
2008
- getWindowObserver(): SharedWindowObserver;
2009
- constructor(options: TrackerOptions);
2010
- /** Apply init overrides on every refresh; continuity and persistence only activate within a document. */
2011
- private handleConfig;
2012
- /**
2013
- * Returns the logger used by this tracker.
2014
- * @internal
2015
- */
2016
- getLogger(): Logger;
2017
- private applicationTag;
2018
- /**
2019
- * Register the user's variant for an experiment (e.g. `setExperiment("button_color", "blue")`).
2020
- *
2021
- * @remarks
2022
- * Corbado Observe does not assign variants — your app decides, and this records the assignment so
2023
- * Observe can attribute flows to it. The assignment persists (localStorage) across reloads and
2024
- * `resetSession`, and is attached to every event the tracker produces until you change or clear it.
2025
- * Multiple experiments can be active at once. Set it close to where the variant actually affects the
2026
- * user (or use the per-call `experiments` argument on a tracking method) to avoid over-attributing
2027
- * exposure; call {@link clearExperiment} when it no longer applies (e.g. on logout).
2028
- *
2029
- * Never throws: invalid input is ignored with a debug log.
2030
- */
2031
- setExperiment(key: string, variant: string): void;
2032
- /**
2033
- * Register several experiment assignments at once (experiment key → variant). Additive: existing
2034
- * assignments for other keys are kept. See {@link setExperiment}.
2035
- */
2036
- setExperiments(assignments: Record<string, string>): void;
2037
- /** Remove a single experiment assignment. */
2038
- clearExperiment(key: string): void;
2039
- /** Remove all experiment assignments. */
2040
- clearExperiments(): void;
2041
- /** Returns a copy of the currently active experiment assignments. */
2042
- getExperiments(): Record<string, string>;
2043
- /**
2044
- * Returns the currently active public SDK configuration, including live updates.
2045
- *
2046
- * @returns A frozen snapshot, created fresh on every call.
2047
- */
2048
- /** @internal Project-scoped localStorage used by operation helpers (e.g. email-link continuity). */
2049
- getPersistentStorage(): StorageEngine | undefined;
2050
- getSdkConfig(): ObserveSdkConfigSnapshot;
2051
- /**
2052
- * Set the data policy code for this tracker (e.g. `setDataPolicy(1)` once the user agreed to
2053
- * extended processing; `setDataPolicy(0)` to return to the project default). Codes are
2054
- * project-scoped non-negative integers (0..255) selecting a policy configured in Corbado; they
2055
- * carry no ordering.
2056
- *
2057
- * The code is persisted (localStorage, project-scoped) and sent as `meta.dataPolicy` on every
2058
- * subsequent batch, across reloads and session rotation. It is never cleared, only overwritten.
2059
- * The server records the latest code it receives for a session (last write wins). Invalid codes
2060
- * are ignored with a debug log; never throws.
2061
- */
2062
- setDataPolicy(code: number): void;
2063
- /** Returns the current data policy code, or undefined when none has ever been set. */
2064
- getDataPolicy(): number | undefined;
2065
- private static isValidDataPolicy;
2066
- private loadPersistedDataPolicy;
2067
- private persistDataPolicy;
2068
- private static isValidExperimentKey;
2069
- private static isValidExperimentVariant;
2070
- private loadPersistedExperiments;
2071
- private persistExperiments;
2072
- /**
2073
- * Resolves the experiments to attach to one event: the persistent assignments with any per-call
2074
- * override merged on top. Returns undefined when there are none (so the field is omitted).
2075
- */
2076
- private resolveExperiments;
2077
- private isTrackingBlocked;
2078
- /** The cross-origin session cookie when `fixedDataConfig.crossOriginSession` is set and usable here. */
2079
- private createCrossOriginSession;
2080
- /**
2081
- * Last activity of the local session records BEFORE this load rewrites them (both paths, by id), so the
2082
- * cross-origin boot can tell a session that was active here from one this load just created.
2083
- */
2084
- private readLocalSessionActivity;
2085
- /**
2086
- * Reconcile the session this load resolved locally with the cross-origin cookie before the first event:
2087
- * adopt the cookie's session (and persist it locally, so reloads and same-origin tabs follow) or keep
2088
- * the local one, and continue the seq at or above the cookie's mark. Never throws.
2089
- */
2090
- private bootCrossOriginSession;
2091
- /**
2092
- * Resolve the session of this load: locally ({@link resolveSessionId}), then reconciled with the
2093
- * cross-origin cookie when that option is on. Used at boot and by the recovery in `getSessionId`.
2094
- */
2095
- private resolveSession;
2096
- /** `meta.crossOriginSession` of a batch of `sessionId`; undefined while the option is off on this page. */
2097
- private crossOriginSessionMeta;
2098
- private resolveSessionId;
2099
- /**
2100
- * Resolve the session id from localStorage so it survives reloads and is shared across tabs of the
2101
- * same browser. Rotates after `config.sessionInactivityMs` of inactivity (server-controlled,
2102
- * evaluated at boot), resetting the seq counter.
2103
- *
2104
- * Inactivity rotation happens at boot only, here and on the per-tab path {@link resolveSessionId}
2105
- * takes without continuity. Boot is chosen on an assumption, not a guarantee: that a load
2106
- * re-announces its flow, so the fresh session id gets a classifiable flow. That holds where a
2107
- * flow is opened per load. Where one is opened once and carried across loads it does not, and a
2108
- * boot rotation splits that flow — such a project needs a window long enough to span the journey.
2109
- * Mid-page the assumption is not even available: nothing re-announces between two tracked events,
2110
- * so rotating there would leave the started flow unfinished in the old session and the remaining
2111
- * events without a flow start in the new one — one gap counted as a drop-off, one completion
2112
- * counted as nothing. `nextSeq` therefore never rotates on inactivity, on either path.
2113
- */
2114
- private getContinuitySessionId;
2115
- /**
2116
- * Persist the continuity record and remember when, so the throttled refresh in the seq critical
2117
- * section measures from the last write that actually happened — whoever made it.
2118
- */
2119
- private persistContinuitySession;
2120
- /**
2121
- * Read the per-tab session record. A bare string is the format that predates dating: it carries no
2122
- * `lastActiveAt`, so its window can only start on the load that reads it. That load rewrites it in
2123
- * the dated shape, so a tab converts once and ages normally from then on, and the case drains as
2124
- * the rollout replaces the bundles that write it.
2125
- */
2126
- private readPerTabSession;
2601
+ inputHtmlField?: HTMLInputElement;
2602
+ };
2603
+ type ProvideDataOperationPostResponseStart = {
2604
+ explicitSpecType?: ProvideDataOperationSpecType;
2605
+ };
2606
+ /** Tracks a user-triggered data submission and its server response. */
2607
+ declare class ProvideDataOperationFull extends OperationFull {
2608
+ readonly clientValidation: StepHelper;
2609
+ readonly postResponse: StepHelper<ProvideDataOperationPostResponseStart>;
2610
+ private lowEventTracker?;
2611
+ constructor(tracker: CorbadoTrackerCore, config?: ProvideDataOperationConfig);
2612
+ destroy(): void;
2613
+ }
2614
+ /**
2615
+ * Create a {@link ProvideDataOperationFull} for `tracker`: the standalone form of `CorbadoTracker.provideDataOperationFull()`, for trackers
2616
+ * created by `initCore()` (a bundle that does not import this function does not contain the operation).
2617
+ * Same semantics and documentation as the method.
2618
+ */
2619
+ declare function provideDataOperationFull(tracker: CorbadoTrackerCore, config?: WithHandoffs<ProvideDataOperationConfig>): ProvideDataOperationFull;
2620
+ declare function provideDataOperationFull(tracker: CorbadoTrackerCore, config?: ProvideDataOperationConfig): ProvideDataOperationFull;
2621
+
2622
+ /**
2623
+ * The full tracker created by {@link init}: {@link CorbadoTrackerCore} plus every optional feature as a
2624
+ * method (typed operations, `setUser`, `setFlowTags`, `resetSession`, ...), and the option-driven
2625
+ * features (`storage: "cookie"`, `fixedDataConfig.crossOriginSession`, raw-error serialization, probes)
2626
+ * installed from its options.
2627
+ *
2628
+ * @remarks
2629
+ * Each feature method delegates to the standalone function of the same name (e.g.
2630
+ * `tracker.totpOperationFull(config)` is `totpOperationFull(tracker, config)`), so its behaviour is the
2631
+ * same on both trackers. Integrations that care about bundle size use {@link initCore} and import the
2632
+ * functions they call.
2633
+ */
2634
+ declare class CorbadoTracker extends CorbadoTrackerCore {
2635
+ constructor(options: TrackerOptions);
2636
+ /** @internal */
2637
+ isFullTracker(): this is CorbadoTracker;
2127
2638
  /**
2128
- * Persist the per-tab record and remember when, sharing the throttle bookkeeping with the
2129
- * continuity record — a load resolves its session on one path or the other, never both.
2639
+ * Register the user's variant for an experiment (e.g. `setExperiment("button_color", "blue")`).
2130
2640
  *
2131
- * An explicit timeout override or server config stamps the window. Otherwise carry forward what
2132
- * the tab already knows, so a defaults boot does not replace a previously configured threshold.
2133
- */
2134
- private persistPerTabSession;
2135
- /** Explicit init timeout wins; otherwise retain the window a prior configured load recorded. */
2136
- private perTabInactivityMs;
2137
- /**
2138
- * Return the next sequence number. With session continuity the counter is persisted so ordering
2139
- * survives reloads/redirects; the read-increment-write runs under a cross-tab Web Lock
2140
- * ({@link SEQ_LOCK_NAME}) so two tabs sharing the session cannot allocate the same seq (where Web
2141
- * Locks are unavailable or exceed the configured timeout it degrades to the historical best-effort merge).
2142
- * Lock grants are FIFO, so seq order matches `track()` call order within a tab. Tracking also keeps the
2143
- * continuity session's `lastActiveAt` fresh (throttled, see {@link SESSION_ACTIVITY_WRITE_INTERVAL_MS}),
2144
- * so the window the NEXT boot evaluates measures real user
2145
- * inactivity instead of time-since-page-load (a long-lived active tab must not rotate the session
2146
- * on the next reload). It never rotates the session itself: the inactivity window is evaluated at
2147
- * boot only ({@link getContinuitySessionId} documents why). Consequence: while a page is never
2148
- * reloaded — foreground idle, bfcache restore, long-lived SPA tab — a session can outlive
2149
- * `sessionInactivityMs`. That inflates flow durations but keeps flow counts correct, which is the
2150
- * better half of the trade. An empty store while this load already has a session id means
2151
- * persistence is failing (or was cleared); the in-memory id is reused then — never re-minted — so
2152
- * a broken store degrades to one session per page load instead of one session per event.
2153
- */
2154
- private nextSeq;
2155
- private resolveTrackingSourcePath;
2156
- /**
2157
- * Per-tab id for event meta, cached after the first successful resolution: the id is
2158
- * sessionStorage-backed and stable for the whole page lifetime.
2641
+ * @remarks
2642
+ * Corbado Observe does not assign variants — your app decides, and this records the assignment so
2643
+ * Observe can attribute flows to it. The assignment persists (localStorage) across reloads and
2644
+ * `resetSession`, and is attached to every event the tracker produces until you change or clear it.
2645
+ * Multiple experiments can be active at once. Set it close to where the variant actually affects the
2646
+ * user (or use the per-call `experiments` argument on a tracking method) to avoid over-attributing
2647
+ * exposure; call {@link clearExperiment} when it no longer applies (e.g. on logout).
2648
+ *
2649
+ * Never throws: invalid input is ignored with a debug log.
2159
2650
  */
2160
- private resolveEventTabId;
2161
- /** @internal */
2162
- trackSubflowStarted(subflowType: SubflowType, data: Record<string, any>, options?: StepOptions, eventId?: string): void;
2163
- /** @internal */
2164
- trackSubflowTrigger(subflowType: SubflowType, data: Record<string, any>, options?: StepOptions): void;
2165
- /** @internal */
2166
- trackSubflowStepStarted(subflowType: SubflowType, stepName: string, data: Record<string, any>, options?: StepOptions, ignoreAsInteraction?: boolean): void;
2167
- /** @internal */
2168
- trackSubflowStepFinished(subflowType: SubflowType, stepName: string, data: Record<string, any>, options?: StepOptions): void;
2169
- /** @internal */
2170
- trackSubflowStepError(subflowType: SubflowType, stepName: string, data: Record<string, any>, options?: StepOptions): void;
2651
+ setExperiment(key: string, variant: string): void;
2652
+ /** Remove a single experiment assignment. */
2653
+ clearExperiment(key: string): void;
2654
+ /** Remove all experiment assignments. */
2655
+ clearExperiments(): void;
2171
2656
  /**
2172
2657
  * @remarks
2173
2658
  * @internal
@@ -2175,64 +2660,6 @@ declare class CorbadoTracker {
2175
2660
  * step errors are the intended channel; not part of a normal integration.
2176
2661
  */
2177
2662
  trackSubflowError(subflowType: SubflowType, data: Record<string, any>, options?: StepOptions): void;
2178
- /**
2179
- * Error situations:
2180
- * - Blocked user agent (see `isBlockedUserAgent`): skip with a debug log and return
2181
- * - Any error before the event is enqueued (e.g. `JSON.stringify` in debug logging, `queue.enqueue`): log `Failed to process event "<name>" before enqueue`
2182
- *
2183
- * @internal
2184
- */
2185
- track(name: AuthEventName, data: Record<string, any>, userReference?: UserReference, tags?: Record<string, string>, contexts?: Record<string, any>, explicitTimestamp?: number, experiments?: Record<string, string>, capture?: {
2186
- id?: string;
2187
- subflowStartEventId?: string;
2188
- sessionId?: string;
2189
- initiator?: StepOptions["initiator"];
2190
- }): Promise<void>;
2191
- /**
2192
- * Track when an authentication flow (or flow selection screen) becomes visible.
2193
- *
2194
- * @remarks
2195
- * Call this once when the user first enters an auth touchpoint (for example account login,
2196
- * checkout login, or account recovery). If users can choose between multiple flows
2197
- * (such as login vs signup), pass `flowNames` and optionally `defaultFlowName`.
2198
- *
2199
- * The returned handle can attach identity after completion with `await flow.enrich({ userId })`.
2200
- * Enrichment requires a backend supporting explicit event targeting.
2201
- *
2202
- * @param data - Flow metadata, including one flow (`flowName`) or multiple candidates (`flowNames`).
2203
- * @param tags - Optional key-value tags for filtering and segmentation.
2204
- * @param experiments - Optional per-call experiment overrides.
2205
- * @param contexts - Optional structured event context (e.g. technical metadata that is not an
2206
- * analytical dimension). Written to the event's `contexts` field verbatim.
2207
- * @param options - Optional `explicitTimestamp` (epoch ms) when the flow became visible earlier than
2208
- * this call, e.g. because an integration confirms a screen only after it stayed up for a while.
2209
- *
2210
- * @example
2211
- * ```typescript
2212
- * tracker.flowStarted({
2213
- * flowNames: ["login", "signup"],
2214
- * defaultFlowName: "login",
2215
- * touchpoint: "account",
2216
- * });
2217
- * ```
2218
- */
2219
- flowStarted(data: FlowStarted | MultiFlowStarted, tags?: Record<string, string>, experiments?: Record<string, string>, contexts?: Record<string, unknown>, options?: Pick<StepOptions, "explicitTimestamp">): FlowHandle;
2220
- /**
2221
- * Track when the user commits to a specific flow.
2222
- *
2223
- * @remarks
2224
- * Use this after presenting alternatives and once you know which path the user takes
2225
- * (for example when identifier checks route to login vs signup).
2226
- *
2227
- * @param data - Selected flow name.
2228
- * @param tags - Optional key-value tags for filtering and segmentation.
2229
- *
2230
- * @example
2231
- * ```typescript
2232
- * tracker.flowDecided({flowName: "signup"});
2233
- * ```
2234
- */
2235
- flowDecided(data: FlowDecided, tags?: Record<string, string>, experiments?: Record<string, string>): void;
2236
2663
  /**
2237
2664
  * Track a business/marketing conversion that is not part of an authentication flow.
2238
2665
  *
@@ -2257,73 +2684,6 @@ declare class CorbadoTracker {
2257
2684
  * ```
2258
2685
  */
2259
2686
  conversion(data: Conversion, tags?: Record<string, string>, experiments?: Record<string, string>): void;
2260
- /**
2261
- * Track when a flow successfully completes.
2262
- *
2263
- * @remarks
2264
- * Fire this when the user has finished the target flow end-to-end, such as completed login,
2265
- * signup, or recovery. Record identity with `setUser()` while the flow is active,
2266
- * or enrich it after completion through the handle returned by `flowStarted()` or by this call.
2267
- *
2268
- * The returned handle targets the flow this event finished, so identity learned only after
2269
- * completion — for example from a profile request that follows account creation — can be
2270
- * attached with `await finished.enrich({ userId })` even on a page that never saw the flow start.
2271
- * Enrichment requires a backend supporting explicit flow-event targeting.
2272
- *
2273
- * Legacy identity fields in `data` remain supported but are deprecated.
2274
- *
2275
- * @param data - Finished flow name, optional explicit outcome, and deprecated user reference fields.
2276
- * @param tags - Optional key-value tags for filtering and segmentation.
2277
- *
2278
- * @example
2279
- * ```typescript
2280
- * const finished = tracker.flowFinished({ flowName: "signup" });
2281
- * const userId = await hashUserId(createdAccountId);
2282
- * await finished.enrich({ userId });
2283
- * ```
2284
- */
2285
- flowFinished(data: FlowFinished, tags?: Record<string, string>, experiments?: Record<string, string>): FlowHandle;
2286
- /** Emits `flow_enriched` against an explicit target, in the session that emitted the target. */
2287
- private flowHandle;
2288
- /**
2289
- * Track when an in-progress flow is reset and restarted.
2290
- *
2291
- * @remarks
2292
- * Use this when users abandon the current path and return to the beginning of the same flow,
2293
- * for example after switching account/identifier and reopening the first step.
2294
- *
2295
- * @param data - Flow name being reset.
2296
- * @param tags - Optional key-value tags for filtering and segmentation.
2297
- *
2298
- * @example
2299
- * ```typescript
2300
- * tracker.flowReset({flowName: "login"});
2301
- * ```
2302
- */
2303
- flowReset(data: FlowReset | MultiFlowReset, tags?: Record<string, string>, experiments?: Record<string, string>): void;
2304
- /**
2305
- * Track when a flow is considered finished because another flow finished it implicitly.
2306
- *
2307
- * @remarks
2308
- * Use this for automatic completions where no separate explicit finish action happens in the
2309
- * current flow. Set `flowName` to the auto-finished flow and `finishedByFlowName` to the flow
2310
- * that caused it. Record identity with `setUser()` while the intended flow is still
2311
- * current, before it is auto-finished.
2312
- *
2313
- * Legacy identity fields in `data` remain supported but are deprecated.
2314
- *
2315
- * @param data - Auto-finished flow, finishing flow, and deprecated user reference fields.
2316
- * @param tags - Optional key-value tags for filtering and segmentation.
2317
- *
2318
- * @example
2319
- * ```typescript
2320
- * tracker.flowAutoFinished({
2321
- * flowName: "signup",
2322
- * finishedByFlowName: "login",
2323
- * });
2324
- * ```
2325
- */
2326
- flowAutoFinished(data: FlowAutoFinished, tags?: Record<string, string>, experiments?: Record<string, string>): void;
2327
2687
  /**
2328
2688
  * Record a newly known user reference for the current active flow.
2329
2689
  *
@@ -2377,62 +2737,15 @@ declare class CorbadoTracker {
2377
2737
  */
2378
2738
  setFlowTags(tags: Record<string, string>, options?: SetFlowTagsOptions): void;
2379
2739
  /**
2380
- * Track when you present authentication method choices to the user.
2381
- *
2382
- * @remarks
2383
- * Use this whenever a decision point is shown with a concrete method set, such as
2384
- * identifier entry options (`d1`) or post-identifier options (`d3`). Set
2385
- * `explicitDecisionValue` when the options are re-offered after a user action and you want
2386
- * to capture what triggered that transition.
2387
- *
2388
- * @param data - Decision identifier, offered options, and optional transition reason.
2389
- * @param tags - Optional key-value tags for filtering and segmentation.
2390
- * @param experiments - Optional per-call experiment assignments.
2391
- * @param options - Optional explicit event timestamp.
2392
- *
2393
- * @example
2394
- * ```typescript
2395
- * tracker.authMethodsDecisionStarted({
2396
- * decisionName: "d3",
2397
- * options: ["passkey", "social-google", "password", "reset-flow"],
2398
- * });
2399
- * ```
2400
- */
2401
- authMethodsDecisionStarted(data: AuthMethodDecisionStarted, tags?: Record<string, string>, experiments?: Record<string, string>, options?: Pick<StepOptions, "explicitTimestamp">): void;
2402
- authMethodsDecisionFinished(data: AuthMethodDecisionFinished, tags?: Record<string, string>, experiments?: Record<string, string>): void;
2403
- /**
2404
- * @deprecated Use {@link CorbadoTracker.authMethodsDecisionStarted} instead (its `options`
2405
- * already accept free-form strings).
2406
- */
2407
- authDecisionStarted(data: AuthDecisionStarted, tags?: Record<string, string>, experiments?: Record<string, string>): void;
2408
- /**
2409
- * @deprecated Use {@link CorbadoTracker.authMethodsDecisionFinished} instead (its `options`
2410
- * already accept free-form strings).
2411
- */
2412
- authDecisionFinished(data: AuthDecisionFinished, tags?: Record<string, string>, experiments?: Record<string, string>): void;
2413
- /**
2414
- * Enqueue a "low" event (granular DOM/window/visualviewport/PWM signal) for the current session.
2415
- *
2416
- * @remarks
2417
- * Low events are sent in the `lows` array of the events endpoint payload, alongside any
2418
- * pending typed events. Blocked user agents are skipped silently.
2419
- *
2420
- * @internal
2421
- */
2422
- enqueueLowEvent(low: LowEvent, capturedSessionId?: string): void;
2423
- /**
2424
- * Record a diagnostic telemetry entry (a `level` + free-form `message`) for the current session.
2425
- *
2426
- * @remarks
2427
- * Telemetry is delivered in the `telemetry` array of the events endpoint payload, tied to the same
2428
- * session, and is never classified as an auth-flow event. By default a telemetry entry piggybacks
2429
- * the next normal flush (it does not trigger one on its own); this is server-controlled. Collection
2430
- * can be turned off server-side via the `telemetry` config flag. Blocked user agents are skipped.
2431
- *
2432
- * The message is truncated to {@link TELEMETRY_MESSAGE_MAX} characters. Never pass credentials or
2433
- * PII — telemetry is for diagnostics only. Like all SDK entry points, this never throws.
2740
+ * @deprecated Use {@link CorbadoTracker.authMethodsDecisionStarted} instead (its `options`
2741
+ * already accept free-form strings).
2434
2742
  */
2435
- telemetry(level: TelemetryLevel, message: string): void;
2743
+ authDecisionStarted(data: AuthDecisionStarted, tags?: Record<string, string>, experiments?: Record<string, string>): void;
2744
+ /**
2745
+ * @deprecated Use {@link CorbadoTracker.authMethodsDecisionFinished} instead (its `options`
2746
+ * already accept free-form strings).
2747
+ */
2748
+ authDecisionFinished(data: AuthDecisionFinished, tags?: Record<string, string>, experiments?: Record<string, string>): void;
2436
2749
  /**
2437
2750
  * Queue a probe item (diagnostic capture produced by a Corbado autocapture bundle).
2438
2751
  *
@@ -2446,53 +2759,10 @@ declare class CorbadoTracker {
2446
2759
  * @internal
2447
2760
  */
2448
2761
  probe(input: ProbeInput): void;
2449
- private defaultProbePageId;
2450
- private nextProbeSeq;
2451
2762
  /** Convenience wrapper for {@link CorbadoTracker.telemetry} at `info` level. */
2452
2763
  logInfo(message: string): void;
2453
2764
  /** Convenience wrapper for {@link CorbadoTracker.telemetry} at `error` level. */
2454
2765
  logError(message: string): void;
2455
- /**
2456
- * Queue hook run right before an event batch is sent: a device info snapshot that no event carried
2457
- * yet (typically the fast snapshot after a burst of events at page load, or the privateMode update)
2458
- * rides the first event of this page in the batch that has none. Events of other pages (outbox
2459
- * replays) are never touched. A snapshot no event can carry goes as the batch's request-level device
2460
- * info instead (queue option `standaloneDeviceInfo`).
2461
- *
2462
- * Error situations:
2463
- * - Any error: log "Failed to attach device info to batch" and send the batch unchanged
2464
- */
2465
- private attachUndeliveredDeviceInfo;
2466
- /**
2467
- * Escalate an internal SDK diagnostic to the telemetry stream (self-instrumentation). This is the
2468
- * sink behind {@link Logger.reportTelemetry}; chosen internal failure sites route here so faults
2469
- * that are otherwise only visible with `debug: true` become observable in the field.
2470
- *
2471
- * @remarks
2472
- * Bounded and deduped per load (a persistent fault — blocked storage, a downed endpoint — cannot
2473
- * flood the stream), re-entrancy-guarded so it can never recurse, and it never throws into the
2474
- * host. Diagnostics raised before the queue exists (early boot) are buffered and replayed once the
2475
- * queue is ready. Messages must be stable and low-cardinality (no raw error objects / PII).
2476
- */
2477
- private reportTelemetry;
2478
- /**
2479
- * Synchronously flush any pending events and low events via beacon. Use during page-unload
2480
- * style teardown where async flushing is unreliable.
2481
- *
2482
- * @param reason What triggered the flush; recorded as `meta.flushReason` on the batch. Defaults
2483
- * to a direct call by the host app.
2484
- *
2485
- * @internal
2486
- */
2487
- flushKeepalive(reason?: FlushReason): void;
2488
- /**
2489
- * Keepalive flush requested by a low-event tracker's `pagehide` teardown. Gated by the
2490
- * server-controlled trigger switch `tlf` (boot-snapshot, default true = historical behavior):
2491
- * disabling it server-side makes low-event delivery rely solely on the queue's own triggers.
2492
- *
2493
- * @internal
2494
- */
2495
- lowEventFlushKeepalive(): void;
2496
2766
  passkeyLoginFullOperation(config?: PasskeyLoginOperationConfig): PasskeyLoginOperationFull;
2497
2767
  passkeyEnrollmentFullOperation(config?: PasskeyEnrollmentOperationConfig): PasskeyEnrollmentOperationFull;
2498
2768
  /**
@@ -2739,49 +3009,6 @@ declare class CorbadoTracker {
2739
3009
  * ```
2740
3010
  */
2741
3011
  trustedDeviceEnrollmentOperationFull(config: TrustedDeviceOperationConfig): TrustedDeviceEnrollmentOperationFull;
2742
- /**
2743
- * Flush any pending events and release all resources (timers, event listeners).
2744
- *
2745
- * @remarks
2746
- * After calling destroy, the tracker must not be used. Operation objects
2747
- * returned by factory methods (e.g. `passwordLoginFullOperation`) that hold
2748
- * DOM references must be destroyed separately by the caller.
2749
- * The final flush is gated by the server-controlled trigger switch `td` (default true);
2750
- * resources are released either way.
2751
- */
2752
- destroy(): Promise<void>;
2753
- /**
2754
- * Return the Observe session id this tracker is currently reporting under.
2755
- *
2756
- * @remarks
2757
- * Use this to route a server-side event into the same session the browser reports to: read the id,
2758
- * pass it to your own backend, and let the backend use it as the `sessionID` of its ingest call.
2759
- * Reading it here is the supported path — the storage layout behind it is an implementation detail
2760
- * that has already changed once (per-tab `sessionStorage` to the cross-tab continuity record).
2761
- *
2762
- * The value is **not stable for the lifetime of the page**. It changes on
2763
- * {@link CorbadoTracker.resetSession}, when this tab adopts a continuity session another tab
2764
- * rotated to, and when a failed bootstrap recovers. Read it at the moment you need it; never cache
2765
- * it across a request.
2766
- *
2767
- * `undefined` means no session id could be established at all — an environment without Web Crypto,
2768
- * where tracking is not working either. Skip the server-side event instead of sending an empty id:
2769
- * the ingest API requires a UUID and would reject the batch.
2770
- *
2771
- * @returns The current session id, or `undefined` if none could be established.
2772
- *
2773
- * @example
2774
- * ```typescript
2775
- * const sessionId = tracker.getSessionId();
2776
- * if (sessionId) {
2777
- * await fetch("/api/checkout", {
2778
- * method: "POST",
2779
- * body: JSON.stringify({ ...payload, observeSessionId: sessionId }),
2780
- * });
2781
- * }
2782
- * ```
2783
- */
2784
- getSessionId(): string | undefined;
2785
3012
  /**
2786
3013
  * Store an opaque context string with the cross-origin session, for the integration's own use on the
2787
3014
  * next origin (e.g. a journey id and stage). Requires `fixedDataConfig.crossOriginSession`.
@@ -2819,6 +3046,198 @@ declare class CorbadoTracker {
2819
3046
  declare const SDK_NAME = "@corbado/observe";
2820
3047
  declare const SDK_VERSION: string;
2821
3048
 
3049
+ /**
3050
+ * Start a new session for `tracker` (the default tracker when omitted) and return its id.
3051
+ *
3052
+ * @remarks
3053
+ * The seq restarts at 0; experiments and the data policy are kept (they are user-level facts). With the
3054
+ * cross-origin session the shared cookie moves to the new session (without a context string).
3055
+ *
3056
+ * @internal
3057
+ */
3058
+ declare function resetSession(): string | undefined;
3059
+ declare function resetSession(tracker: CorbadoTrackerCore): string;
3060
+ /**
3061
+ * Record a newly known user reference for the current active flow of `tracker` (the default tracker
3062
+ * when omitted). Call after the flow starts and before it finishes; matching has no grace period.
3063
+ *
3064
+ * @remarks
3065
+ * Emits one `flow_enriched` with `match: { flowType: "*", at: "during" }` and `expFol: true` in its data.
3066
+ * The enrichment belongs to the current flow at emission time. Calling after `flowFinished()` cannot
3067
+ * enrich that finished flow. If a parent or another flow is current then, the enrichment belongs to
3068
+ * that flow instead. An empty reference does not clear identity. Cross-environment transaction IDs must
3069
+ * be UUIDs; both environments must report the shared ID while their respective flows are active.
3070
+ *
3071
+ * @example
3072
+ * ```typescript
3073
+ * tracker.flowStarted({ flowName: "login" });
3074
+ * setUser(tracker, { userId: "usr_123", identifier: "max@example.com" });
3075
+ * tracker.flowFinished({ flowName: "login" });
3076
+ * ```
3077
+ */
3078
+ declare function setUser(user: UserReference): void;
3079
+ declare function setUser(tracker: CorbadoTrackerCore, user: UserReference): void;
3080
+ /**
3081
+ * Attach tags to the flow of `tracker` (the default tracker when omitted) that is open right now.
3082
+ *
3083
+ * @remarks
3084
+ * Emits one `flow_enriched` carrying `tags` and no user reference, with data
3085
+ * `{ match: { flowType, at: "during" } }` plus `expCh` / `expFol` when the options set them.
3086
+ *
3087
+ * - The tags land on the innermost flow open at call time (of `flowType` when given; default `"*"`, any type).
3088
+ * - `expandToChildren` (default `true`): child flows of that flow inherit the tags.
3089
+ * - `expandToFollowing` (default `true`): later sibling flows inherit the tags until the next
3090
+ * sibling of the same flow type as the tagged flow.
3091
+ * - Per key the last `setFlowTags()` value wins; it also overrides a same-key tag passed to that
3092
+ * flow's own tracking calls (e.g. `flowStarted()`).
3093
+ * - Call while the target flow is open. An enrichment after the flow's last container event
3094
+ * (for example after `flowFinished()`) matches no flow and is dropped with a
3095
+ * `flow_enriched/no_matching_flow` classification warning.
3096
+ * - Tag keys and values are case-sensitive. Entries with an empty key or a non-string value are
3097
+ * dropped with a warning; nothing is sent when no valid entry remains.
3098
+ *
3099
+ * @example
3100
+ * ```typescript
3101
+ * tracker.flowStarted({ flowName: "login" });
3102
+ * setFlowTags(tracker, { entryPoint: "checkout" });
3103
+ * tracker.flowFinished({ flowName: "login" });
3104
+ * ```
3105
+ */
3106
+ declare function setFlowTags(tags: Record<string, string>, options?: SetFlowTagsOptions): void;
3107
+ declare function setFlowTags(tracker: CorbadoTrackerCore, tags: Record<string, string>, options?: SetFlowTagsOptions): void;
3108
+ /**
3109
+ * Register the user's variant for an experiment on `tracker` (the default tracker when omitted), e.g.
3110
+ * `setExperiment(tracker, "button_color", "blue")`. See `CorbadoTracker.setExperiment`.
3111
+ * Never throws: invalid input is ignored with a debug log.
3112
+ */
3113
+ declare function setExperiment(key: string, variant: string): void;
3114
+ declare function setExperiment(tracker: CorbadoTrackerCore, key: string, variant: string): void;
3115
+ /** Remove a single experiment assignment of `tracker` (the default tracker when omitted). */
3116
+ declare function clearExperiment(key: string): void;
3117
+ declare function clearExperiment(tracker: CorbadoTrackerCore, key: string): void;
3118
+ /** Remove all experiment assignments of `tracker` (the default tracker when omitted). */
3119
+ declare function clearExperiments(tracker?: CorbadoTrackerCore): void;
3120
+ /** Telemetry entry at `info` level on `tracker` (the default tracker when omitted); see `telemetry`. */
3121
+ declare function logInfo(message: string): void;
3122
+ declare function logInfo(tracker: CorbadoTrackerCore, message: string): void;
3123
+ /** Telemetry entry at `error` level on `tracker` (the default tracker when omitted); see `telemetry`. */
3124
+ declare function logError(message: string): void;
3125
+ declare function logError(tracker: CorbadoTrackerCore, message: string): void;
3126
+ /**
3127
+ * Track a business/marketing conversion that is not part of an authentication flow on `tracker`.
3128
+ * Standalone form of `CorbadoTracker.conversion` (same semantics).
3129
+ */
3130
+ declare function conversion(tracker: CorbadoTrackerCore, data: Conversion, tags?: Record<string, string>, experiments?: Record<string, string>): void;
3131
+ /**
3132
+ * @deprecated Use `tracker.authMethodsDecisionStarted` instead (its `options` already accept free-form
3133
+ * strings). Standalone form of `CorbadoTracker.authDecisionStarted`.
3134
+ */
3135
+ declare function authDecisionStarted(tracker: CorbadoTrackerCore, data: AuthDecisionStarted, tags?: Record<string, string>, experiments?: Record<string, string>): void;
3136
+ /**
3137
+ * @deprecated Use `tracker.authMethodsDecisionFinished` instead (its `options` already accept free-form
3138
+ * strings). Standalone form of `CorbadoTracker.authDecisionFinished`.
3139
+ */
3140
+ declare function authDecisionFinished(tracker: CorbadoTrackerCore, data: AuthDecisionFinished, tags?: Record<string, string>, experiments?: Record<string, string>): void;
3141
+ /**
3142
+ * Records an additional error occurrence against the subflow. Carries no outcome semantics — step
3143
+ * errors are the intended channel; not part of a normal integration.
3144
+ * @internal
3145
+ */
3146
+ declare function trackSubflowError(tracker: CorbadoTrackerCore, subflowType: SubflowType, data: Record<string, any>, options?: StepOptions): void;
3147
+
3148
+ type CookieStorageOptions = {
3149
+ /** `Domain` attribute of the cookies (e.g. `example.com` to share them across subdomains). */
3150
+ cookieDomain?: string;
3151
+ };
3152
+ /**
3153
+ * Tracker plugin: keep the device-level state (device id and device info cache) in first-party
3154
+ * cookies instead of localStorage — the equivalent of `storage: "cookie"` / `cookieDomain` of
3155
+ * {@link init}.
3156
+ *
3157
+ * @example
3158
+ * ```ts
3159
+ * const tracker = initCore({ projectId, apiBaseUrl, plugins: [cookieStorage({ cookieDomain: "example.com" })] });
3160
+ * ```
3161
+ */
3162
+ declare function cookieStorage(options?: CookieStorageOptions): TrackerPlugin;
3163
+
3164
+ /**
3165
+ * Tracker plugin: share the session with the other origins of one site through a first-party cookie
3166
+ * (see {@link CrossOriginSessionConfig}) — the equivalent of `fixedDataConfig.crossOriginSession` of
3167
+ * {@link init}. Read and write the integration's context string with {@link setCrossOriginContext} /
3168
+ * {@link getCrossOriginContext}.
3169
+ *
3170
+ * @example
3171
+ * ```ts
3172
+ * const tracker = initCore({ projectId, apiBaseUrl, plugins: [crossOriginSession({ cookieDomain: "example.com" })] });
3173
+ * ```
3174
+ */
3175
+ declare function crossOriginSession(config: CrossOriginSessionConfig): TrackerPlugin;
3176
+ /**
3177
+ * Store an opaque context string with the cross-origin session of `tracker`, for the integration's own
3178
+ * use on the next origin (e.g. a journey id and stage). Requires the {@link crossOriginSession} plugin
3179
+ * (on the full tracker: `fixedDataConfig.crossOriginSession`).
3180
+ *
3181
+ * @remarks
3182
+ * The value travels in the shared cookie only (see {@link CrossOriginSessionConfig}): it is never sent
3183
+ * to Corbado, but the browser sends the cookie with every request to every subdomain of the configured
3184
+ * domain. It belongs to the current session: a tracker that adopts the session reads it with
3185
+ * {@link getCrossOriginContext}, and a new session (inactivity, `resetSession`) starts without it. At
3186
+ * most 128 characters of `A-Z a-z 0-9 . _ ~ -`; never put personal data in it. `null`, `undefined` or
3187
+ * `""` clears it.
3188
+ *
3189
+ * Never throws.
3190
+ *
3191
+ * @returns `true` when the value was accepted and written; `false` when it is invalid or the feature
3192
+ * is off on this page (not configured, cookie blocked, domain mismatch, not HTTPS).
3193
+ */
3194
+ declare function setCrossOriginContext(tracker: CorbadoTrackerCore, context: string | null | undefined): boolean;
3195
+ /**
3196
+ * The context string stored with the current cross-origin session of `tracker` (see
3197
+ * {@link setCrossOriginContext}), or `undefined` when none is set, the session has no context, or the
3198
+ * feature is off on this page. Never throws.
3199
+ */
3200
+ declare function getCrossOriginContext(tracker: CorbadoTrackerCore): string | undefined;
3201
+
3202
+ /**
3203
+ * Tracker plugin: serialize the `rawError` option of operation step errors
3204
+ * (`op.step.error(error, { rawError })`) into `stepData.rawError` (see `serializeRawError`).
3205
+ *
3206
+ * @remarks
3207
+ * Without it a {@link CorbadoTrackerCore} drops `rawError` (the step error itself is still sent), so
3208
+ * the serializer is not part of a bundle that does not import this plugin. The full `CorbadoTracker`
3209
+ * ({@link init}) always installs it. Serialization stays gated by the server config `rawErrors`.
3210
+ *
3211
+ * @example
3212
+ * ```ts
3213
+ * const tracker = initCore({ projectId, apiBaseUrl, plugins: [rawErrors()] });
3214
+ * ```
3215
+ */
3216
+ declare function rawErrors(): TrackerPlugin;
3217
+
3218
+ /**
3219
+ * Tracker plugin: the SDK probe lane (diagnostic captures of Corbado autocapture bundles, sent with
3220
+ * {@link probe}). The full `CorbadoTracker` ({@link init}) always installs it.
3221
+ *
3222
+ * @experimental Internal: used by Corbado autocapture bundles. Not part of the documented API.
3223
+ * @internal
3224
+ */
3225
+ declare function probes(): TrackerPlugin;
3226
+ /**
3227
+ * Queue a probe item (diagnostic capture produced by a Corbado autocapture bundle). Requires the
3228
+ * {@link probes} plugin; without it the item is dropped (debug log).
3229
+ *
3230
+ * @remarks
3231
+ * The SDK fills `id` (uuidv7), `seq` (per `pageId`), `pageId` (default: one random id per tracker
3232
+ * instance) and `ts` (default: now). Items are held in memory only (never the durable outbox) and
3233
+ * ride the regular batches; they are the lowest priority at page unload. Invalid input is dropped.
3234
+ * The payload must already be redacted. Blocked user agents are skipped. Never throws.
3235
+ *
3236
+ * @experimental Internal: used by Corbado autocapture bundles. Not part of the documented API.
3237
+ * @internal
3238
+ */
3239
+ declare function probe(tracker: CorbadoTrackerCore, input: ProbeInput): void;
3240
+
2822
3241
  interface TransportMakeRequestResponse {
2823
3242
  deliveryAccepted?: boolean;
2824
3243
  statusCode?: number;
@@ -2837,21 +3256,11 @@ interface TransportOptions {
2837
3256
  headers?: Record<string, string>;
2838
3257
  }
2839
3258
 
2840
- /** In-memory probe queue caps (oldest items are dropped beyond them). */
2841
- declare const PROBE_QUEUE_MAX_ITEMS = 500;
2842
- declare const PROBE_QUEUE_MAX_BYTES: number;
2843
- /** Per-request probe caps (the server keeps at most 200 probe items per batch). */
2844
- declare const PROBE_BATCH_MAX_ITEMS = 200;
2845
- declare const PROBE_BATCH_MAX_BYTES: number;
2846
- /** Serialized payload cap per probe item (server rule). */
2847
- declare const PROBE_PAYLOAD_MAX_BYTES: number;
2848
3259
  /**
2849
3260
  * Unload request budget shared by the event beacon and the probe beacon that follows it: unload
2850
3261
  * transports share a ~64 KB in-flight budget per page (same limit as the fetch keepalive cap).
2851
3262
  */
2852
3263
  declare const UNLOAD_BUDGET_BYTES = 60000;
2853
- /** Absolute cap of the probe request at pagehide / destroy. */
2854
- declare const UNLOAD_PROBE_MAX_BYTES = 32000;
2855
3264
  /** UTF-8 byte length of a string (no TextEncoder dependency). */
2856
3265
  declare function utf8Length(text: string): number;
2857
3266
  interface QueueOptions {
@@ -2949,15 +3358,10 @@ declare class RequestQueue {
2949
3358
  */
2950
3359
  private telemetryQueue;
2951
3360
  /**
2952
- * Probe items (`tracker.probe()`): in memory only — never the durable outbox — capped by
2953
- * {@link PROBE_QUEUE_MAX_ITEMS} / {@link PROBE_QUEUE_MAX_BYTES}. They arm the flush timer, ride
2954
- * the regular batches (probe-only batches allowed), retry under `config.retry`, and are the lowest
2955
- * priority at unload (a separate request after the event request, within the remaining budget).
3361
+ * Optional probe lane (`probes()` plugin, see {@link ProbeLane}); without one, probe items are dropped
3362
+ * and the flush paths below never see any.
2956
3363
  */
2957
- private probeQueue;
2958
- private probeBytes;
2959
- /** Probe items dropped on this load (caps, permanent rejection, exhausted retries, unload budget). */
2960
- private probesDropped;
3364
+ private lane?;
2961
3365
  private timer;
2962
3366
  private isFlushing;
2963
3367
  private flushingDone?;
@@ -3034,29 +3438,18 @@ declare class RequestQueue {
3034
3438
  */
3035
3439
  enqueueTelemetry(entry: TelemetryEntry): void;
3036
3440
  /**
3037
- * Queue a probe item (in memory only). The payload is snapshotted (serialized once) so later host
3038
- * mutations cannot change it; items over {@link PROBE_PAYLOAD_MAX_BYTES} are dropped, and the
3039
- * oldest items are dropped beyond the queue caps. Arms the normal flush timer.
3441
+ * Queue a probe item (in memory only) on the probe lane (see {@link ProbeLane} for snapshotting and
3442
+ * caps). Arms the normal flush timer. Installed with the lane by the `probes()` plugin
3443
+ * ({@link installProbeLane}; always on the full `CorbadoTracker`): a queue without a lane has neither
3444
+ * this nor {@link droppedProbeCount} at runtime (the type keeps the 1.10 shape), so core-only bundles
3445
+ * carry no probe code. Check for the lane (`probe(tracker, input)` does) before calling.
3040
3446
  *
3041
3447
  * Error situations:
3042
3448
  * - Any error while enqueueing or scheduling the flush timer: log "Failed to enqueue probe"
3043
3449
  */
3044
- enqueueProbe(entry: ProbeEntry, capturedSessionId?: string): void;
3045
- /** Number of probe items dropped on this load (diagnostics / tests). */
3046
- droppedProbeCount(): number;
3047
- private dueProbes;
3048
- /** Oldest-first selection for one session, within an item and byte cap (at least one item when any fits the item cap). */
3049
- private selectProbes;
3050
- private removeProbes;
3051
- private dropProbes;
3052
- /** Same policy as events: 2xx delivered, non-retryable dropped, retryable backed off up to `config.retry.maxAttempts`. */
3053
- private handleProbeSendResult;
3054
- /**
3055
- * Unload / final teardown: one probe-only request for the current session within `budget` bytes,
3056
- * sent after the event request so the events' delivery is unaffected. Leftovers are dropped when
3057
- * `dropRest` (pagehide, destroy); otherwise they stay queued.
3058
- */
3059
- private sendUnloadProbes;
3450
+ enqueueProbe: (entry: ProbeEntry, capturedSessionId?: string) => void;
3451
+ /** Number of probe items dropped on this load (diagnostics / tests); installed with the lane. */
3452
+ droppedProbeCount: () => number;
3060
3453
  private scheduleAfterEnqueue;
3061
3454
  /**
3062
3455
  * Whether this event completes one of the configured priority flow types. Only the two flow
@@ -3159,6 +3552,85 @@ declare class RequestQueue {
3159
3552
  destroy(): void;
3160
3553
  }
3161
3554
 
3555
+ /** In-memory probe queue caps (oldest items are dropped beyond them). */
3556
+ declare const PROBE_QUEUE_MAX_ITEMS = 500;
3557
+ declare const PROBE_QUEUE_MAX_BYTES: number;
3558
+ /** Per-request probe caps (the server keeps at most 200 probe items per batch). */
3559
+ declare const PROBE_BATCH_MAX_ITEMS = 200;
3560
+ declare const PROBE_BATCH_MAX_BYTES: number;
3561
+ /** Serialized payload cap per probe item (server rule). */
3562
+ declare const PROBE_PAYLOAD_MAX_BYTES: number;
3563
+ /** Absolute cap of the probe request at pagehide / destroy. */
3564
+ declare const UNLOAD_PROBE_MAX_BYTES = 32000;
3565
+ /**
3566
+ * Install a probe lane on `queue` together with the queue's probe entry points (`enqueueProbe`,
3567
+ * `droppedProbeCount`): what the `probes()` plugin does. Idempotent: returns the installed lane.
3568
+ * @internal
3569
+ */
3570
+ declare function installProbeLane(queue: RequestQueue): ProbeLane;
3571
+ /**
3572
+ * A queued probe item: in memory only, keeps the session it was captured in, retried like events.
3573
+ * @internal
3574
+ */
3575
+ interface ProbePending {
3576
+ sessionId: string;
3577
+ entry: ProbeEntry;
3578
+ bytes: number;
3579
+ attempts: number;
3580
+ flushAfter: number;
3581
+ }
3582
+ /**
3583
+ * The probe lane of a {@link RequestQueue}: probe items (`probe(tracker, input)`), in memory only —
3584
+ * never the durable outbox — capped by {@link PROBE_QUEUE_MAX_ITEMS} / {@link PROBE_QUEUE_MAX_BYTES}.
3585
+ * They arm the flush timer, ride the regular batches (probe-only batches allowed), retry under
3586
+ * `config.retry`, and are the lowest priority at unload (a separate request after the event request,
3587
+ * within the remaining budget).
3588
+ *
3589
+ * @remarks
3590
+ * Optional: installed by the `probes()` tracker plugin (always on the full `CorbadoTracker`). A queue
3591
+ * without a lane drops probe items, and a bundle that never imports `probes()` contains none of this.
3592
+ * The lane is a package-internal friend of the queue: it reads the queue's delivery state directly.
3593
+ *
3594
+ * @internal
3595
+ */
3596
+ declare class ProbeLane {
3597
+ private readonly queue;
3598
+ /** Queued items, oldest first; read by the queue's flush paths. */
3599
+ items: ProbePending[];
3600
+ private bytes;
3601
+ /** Probe items dropped on this load (caps, permanent rejection, exhausted retries, unload budget). */
3602
+ dropped: number;
3603
+ /** Default probe page id (one per tracker instance) and the probe seq counter per page id. */
3604
+ private pageId?;
3605
+ private readonly seqs;
3606
+ constructor(queue: RequestQueue);
3607
+ /**
3608
+ * Queue a probe item. The payload is snapshotted (serialized once) so later host mutations cannot
3609
+ * change it; items over {@link PROBE_PAYLOAD_MAX_BYTES} are dropped, and the oldest items are dropped
3610
+ * beyond the queue caps. Arms the normal flush timer. Throws on unexpected errors (the queue logs).
3611
+ */
3612
+ enqueue(entry: ProbeEntry, capturedSessionId: string): void;
3613
+ /** The probe part of one regular batch of `sessionId`. */
3614
+ selectBatch(candidates: ProbePending[], sessionId: string): ProbePending[];
3615
+ /** Oldest-first selection for one session, within an item and byte cap (at least one item when any fits the item cap). */
3616
+ private select;
3617
+ private remove;
3618
+ /** Drop `items` (all of them: `drop(lane.items.slice())`), counting them as dropped. */
3619
+ drop(items: ProbePending[]): void;
3620
+ /** Same policy as events: 2xx delivered, non-retryable dropped, retryable backed off up to `config.retry.maxAttempts`. */
3621
+ handleResult(response: TransportMakeRequestResponse, items: ProbePending[], now: number): void;
3622
+ /**
3623
+ * Unload / final teardown: one probe-only request for the current session within `budget` bytes,
3624
+ * sent after the event request so the events' delivery is unaffected. Leftovers are dropped when
3625
+ * `dropRest` (pagehide, destroy); otherwise they stay queued.
3626
+ */
3627
+ sendUnload(budget: number, reason: FlushReason, dropRest: boolean, useBeacon: boolean): void;
3628
+ /** Default page id of probe items without one: one random id per lane (= per tracker instance). */
3629
+ defaultPageId(): string;
3630
+ /** Next probe seq of `pageId` (per-page counters, the oldest forgotten beyond {@link PROBE_PAGE_IDS_MAX}). */
3631
+ nextSeq(pageId: string): number;
3632
+ }
3633
+
3162
3634
  /** Config cache of older SDKs: read as a stale fallback until the first {@link CONFIG_CACHE_STORAGE_KEY} write. */
3163
3635
  declare const CONFIG_STORAGE_KEY = "cbo_sdk_config";
3164
3636
  /** Last-known server config with its source endpoint and freshness, written as one record. */
@@ -3410,33 +3882,44 @@ declare function sanitizeAssertionResponse(value: unknown, projectors?: WebAuthn
3410
3882
  * their methods, or construct {@link CorbadoTracker} instances directly without changing the default.
3411
3883
  */
3412
3884
  declare function init(options: TrackerOptions): CorbadoTracker;
3413
- /** Return the default tracker from the most recent {@link init} call. */
3414
- declare function getTracker(): CorbadoTracker | undefined;
3415
- declare function resetSession(): string | undefined;
3416
3885
  /**
3417
- * Session id of the global tracker, or `undefined` when no tracker was initialized or no session
3418
- * could be established. See {@link CorbadoTracker.getSessionId}.
3886
+ * Create a {@link CorbadoTrackerCore} and make it the default for all package-level helpers — the
3887
+ * tree-shakeable counterpart of {@link init} for integrations that care about bundle size.
3888
+ *
3889
+ * @remarks
3890
+ * The core sends exactly what {@link init} sends for the same calls. Optional features are imported:
3891
+ * typed operations and the other tracker features as standalone functions that take the tracker
3892
+ * (`passkeyLoginFullOperation(tracker, config)`, `setUser(tracker, user)`, `resetSession(tracker)`, ...),
3893
+ * option-driven features as plugins (`cookieStorage()`, `crossOriginSession()`, `rawErrors()`,
3894
+ * `probes()`), see {@link TrackerCoreOptions}. Code that is not imported is not in the bundle.
3895
+ *
3896
+ * @example
3897
+ * ```ts
3898
+ * import { initCore, passkeyLoginFullOperation, rawErrors, setUser } from "@corbado/observe";
3899
+ *
3900
+ * const tracker = initCore({ projectId, apiBaseUrl, plugins: [rawErrors()] });
3901
+ * tracker.flowStarted({ flowName: "login" });
3902
+ * const passkey = passkeyLoginFullOperation(tracker, { explicitSpecType: "pre-identifier" });
3903
+ * setUser(tracker, { userId });
3904
+ * ```
3419
3905
  */
3420
- declare function getSessionId(): string | undefined;
3906
+ declare function initCore(options: TrackerCoreOptions): CorbadoTrackerCore;
3421
3907
  /**
3422
- * Record a user reference for the global tracker's current active flow.
3423
- * Call after the flow starts and before it finishes; matching has no grace period.
3424
- * See {@link CorbadoTracker.setUser}.
3908
+ * Return the default tracker from the most recent {@link init} call; `undefined` when there is none
3909
+ * or when the default was created by {@link initCore} (use {@link getTrackerCore} for that).
3425
3910
  */
3426
- declare function setUser(user: UserReference): void;
3911
+ declare function getTracker(): CorbadoTracker | undefined;
3912
+ /** Return the default tracker from the most recent {@link init} or {@link initCore} call. */
3913
+ declare function getTrackerCore(): CorbadoTrackerCore | undefined;
3427
3914
  /**
3428
- * Attach tags to the global tracker's innermost open flow.
3429
- * See {@link CorbadoTracker.setFlowTags}.
3915
+ * Session id of the global tracker, or `undefined` when no tracker was initialized or no session
3916
+ * could be established. See {@link CorbadoTrackerCore.getSessionId}.
3430
3917
  */
3431
- declare function setFlowTags(tags: Record<string, string>, options?: SetFlowTagsOptions): void;
3432
- declare function setExperiment(key: string, variant: string): void;
3918
+ declare function getSessionId(): string | undefined;
3433
3919
  declare function setExperiments(assignments: Record<string, string>): void;
3434
- declare function clearExperiment(key: string): void;
3435
- declare function clearExperiments(): void;
3436
3920
  declare function getExperiments(): Record<string, string>;
3437
3921
  declare function telemetry(level: TelemetryLevel, message: string): void;
3438
- declare function logInfo(message: string): void;
3439
- declare function logError(message: string): void;
3922
+ /** Destroy the default tracker (see {@link CorbadoTrackerCore.destroy}) and clear the default. */
3440
3923
  declare function destroy(): Promise<void>;
3441
3924
 
3442
- 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_CACHE_STORAGE_KEY, CONFIG_REQUEST_HEADER, CONFIG_STORAGE_KEY, type CaptchaOperationConfig, CaptchaOperationFull, type CaptchaOperationSpecType, type ClientCapabilities, type ClientEnvHandleMeta, type ClientEnvHandleMetaSource, type ConfigCacheRecord, type Conversion, CookieStorage, CorbadoTracker, type CreateLoggerOptions, type CrossOriginSessionConfig, 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 EmailLinkContinuationConfig, EmailLinkContinuationOperation, type EmailLinkOperationConfig, EmailLinkOperationFull, type EmailLinkOperationPostResponseStart, type EmailLinkOperationSendStart, type EmailLinkOperationSpecType, type EmailOTPOperationConfig, type EmailOTPOperationPostResponseStart, type EmailOTPOperationSendOTPStart, type EmailOTPOperationSpecType, EmailOtpOperationFull, type ErrorStepOptions, type Event, type EventBatch, type EventBatchMeta, type EventMeta, EventStore, type EventType, type FixedDataConfig, type FlowAutoFinished, type FlowDecided, type FlowFinished, type FlowHandle, type FlowReset, type FlowStarted, type FlowType, type FlushReason, type FormOperationConfig, FormOperationFull, type HandoffStepHelper, type JavaScriptHighEntropy, type KeyOperationConfig, KeyRegistrationOperationFull, KeySigningOperationFull, 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, PROBE_BATCH_MAX_BYTES, PROBE_BATCH_MAX_ITEMS, PROBE_PAYLOAD_MAX_BYTES, PROBE_QUEUE_MAX_BYTES, PROBE_QUEUE_MAX_ITEMS, type PasskeyDeletionDeletionTypedError, type PasskeyDeletionOperationConfig, PasskeyDeletionOperationFull, type PasskeyDeletionUserConfirmationTypedError, 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 PasswordManagerExtension, type PasswordManagerExtensionName, type PredefinedEvent, type ProbeContext, type ProbeEntry, type ProbeInput, type ProvideDataOperationConfig, ProvideDataOperationFull, type ProvideDataOperationPostResponseStart, type ProvideDataOperationSpecType, type ProvideDataOperationStart, type ProvideIdentifierError, type ProvideIdentifierFinish, type ProvideIdentifierPostResponseStart, type ProvideIdentifierSpecType, type ProvideIdentifierStart, type QueueOptions, RAW_ERROR_BOUNDS, READER_EXPOSURES, type RawErrorEnvelope, type ReaderDataConfigKey, type ReaderExposure, type ReaderField, type ReaderMeta, type ReaderOrigin, type ReaderTransform, RequestQueue, type ResolvedFixedDataConfig, SDK_NAME, SDK_VERSION, type SdkInfo, type SdkInputHandoff, type SdkReliabilityConfig, type SdkReliabilityConfigOverrides, type SdkRetryConfig, type SdkWebAuthnError, type SdkWebAuthnPayload, type SerializeRawErrorOptions, SessionStorage, type SetFlowTagsOptions, type SmsOTPOperationConfig, type SmsOTPOperationPostResponseStart, type SmsOTPOperationSpecType, SmsOtpOperationFull, type SocialLoginEntry, type SocialLoginExchangeCodeFinished, type SocialLoginExchangeCodeStart, type SocialLoginGetRedirectUrlFinished, type SocialLoginGetRedirectUrlStart, type SocialLoginOperationConfig, SocialLoginOperationFull, type SocialLoginProviderType, type SocialLoginSpecType, type SourcePathQueryMode, type SsoLoginExchangeCodeFinished, type SsoLoginExchangeCodeStart, type SsoLoginGetRedirectUrlFinished, type SsoLoginGetRedirectUrlStart, type SsoLoginOperationConfig, SsoLoginOperationFull, type SsoLoginSpecType, type StandaloneDeviceInfoSource, type StepHelper, type StepIdentifier, type StepOptions, type StorageEngine, type SubflowTrigger, type SubflowType, type TelemetryEntry, type TelemetryLevel, type TelemetrySink, type TotpOperationConfig, TotpOperationFull, type TotpOperationPostResponseStart, type TotpOperationSpecType, type TrackerOptions, type Transport, type TransportMakeRequestResponse, type TransportOptions, type TrustedDeviceBindingMetadata, type TrustedDeviceCheckConfig, TrustedDeviceCheckOperationFull, type TrustedDeviceCheckResult, type TrustedDeviceCheckStepResult, type TrustedDeviceCheckTypedError, TrustedDeviceEnrollmentOperationFull, type TrustedDeviceEnrollmentResult, type TrustedDeviceOperationConfig, type TrustedDevicePurpose, type TrustedDeviceStorage, UNLOAD_BUDGET_BYTES, UNLOAD_PROBE_MAX_BYTES, type UserReference, type WebAuthnIdentifierProjector, type WebAuthnIdentifierProjectors, type WithHandoffs, cacheConfigRecord, clearExperiment, clearExperiments, createLogger, destroy, detectPasswordManagerExtensions, getExperiments, getSessionId, getTracker, init, loadCachedConfig, loadConfigRecord, logError, logInfo, namespacedKey, parseReliabilityConfig, resetSession, resolveFixedDataConfig, resolveRawErrorLimits, resolveReliabilityConfig, sanitizeAssertionResponse, sanitizeCreationOptions, sanitizeCreationResponse, sanitizeRequestOptions, serializeRawError, setExperiment, setExperiments, setFlowTags, setUser, telemetry, utf8Length };
3925
+ 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_CACHE_STORAGE_KEY, CONFIG_REQUEST_HEADER, CONFIG_STORAGE_KEY, type CaptchaOperationConfig, CaptchaOperationFull, type CaptchaOperationSpecType, type ClientCapabilities, type ClientEnvHandleMeta, type ClientEnvHandleMetaSource, type ConfigCacheRecord, type Conversion, CookieStorage, type CookieStorageOptions, CorbadoTracker, CorbadoTrackerCore, type CreateLoggerOptions, type CrossOriginSessionConfig, 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 EmailLinkContinuationConfig, EmailLinkContinuationOperation, type EmailLinkOperationConfig, EmailLinkOperationFull, type EmailLinkOperationPostResponseStart, type EmailLinkOperationSendStart, type EmailLinkOperationSpecType, type EmailOTPOperationConfig, type EmailOTPOperationPostResponseStart, type EmailOTPOperationSendOTPStart, type EmailOTPOperationSpecType, EmailOtpOperationFull, type ErrorStepOptions, type Event, type EventBatch, type EventBatchMeta, type EventMeta, EventStore, type EventType, type FixedDataConfig, type FlowAutoFinished, type FlowDecided, type FlowFinished, type FlowHandle, type FlowReset, type FlowStarted, type FlowType, type FlushReason, type FormOperationConfig, FormOperationFull, type HandoffStepHelper, type JavaScriptHighEntropy, type KeyOperationConfig, KeyRegistrationOperationFull, KeySigningOperationFull, 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, PROBE_BATCH_MAX_BYTES, PROBE_BATCH_MAX_ITEMS, PROBE_PAYLOAD_MAX_BYTES, PROBE_QUEUE_MAX_BYTES, PROBE_QUEUE_MAX_ITEMS, type PasskeyDeletionDeletionTypedError, type PasskeyDeletionOperationConfig, PasskeyDeletionOperationFull, type PasskeyDeletionUserConfirmationTypedError, 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 PasswordManagerExtension, type PasswordManagerExtensionName, type PredefinedEvent, type ProbeContext, type ProbeEntry, type ProbeInput, ProbeLane, type ProbePending, type ProvideDataOperationConfig, ProvideDataOperationFull, type ProvideDataOperationPostResponseStart, type ProvideDataOperationSpecType, type ProvideDataOperationStart, type ProvideIdentifierError, type ProvideIdentifierFinish, type ProvideIdentifierPostResponseStart, type ProvideIdentifierSpecType, type ProvideIdentifierStart, type QueueOptions, RAW_ERROR_BOUNDS, READER_EXPOSURES, type RawErrorEnvelope, type RawErrorSerializer, type ReaderDataConfigKey, type ReaderExposure, type ReaderField, type ReaderMeta, type ReaderOrigin, type ReaderTransform, RequestQueue, type ResolvedFixedDataConfig, SDK_NAME, SDK_VERSION, type SdkInfo, type SdkInputHandoff, type SdkReliabilityConfig, type SdkReliabilityConfigOverrides, type SdkRetryConfig, type SdkWebAuthnError, type SdkWebAuthnPayload, type SerializeRawErrorOptions, type SessionBridge, SessionStorage, type SetFlowTagsOptions, type SmsOTPOperationConfig, type SmsOTPOperationPostResponseStart, type SmsOTPOperationSpecType, SmsOtpOperationFull, type SocialLoginEntry, type SocialLoginExchangeCodeFinished, type SocialLoginExchangeCodeStart, type SocialLoginGetRedirectUrlFinished, type SocialLoginGetRedirectUrlStart, type SocialLoginOperationConfig, SocialLoginOperationFull, type SocialLoginProviderType, type SocialLoginSpecType, type SourcePathQueryMode, type SsoLoginExchangeCodeFinished, type SsoLoginExchangeCodeStart, type SsoLoginGetRedirectUrlFinished, type SsoLoginGetRedirectUrlStart, type SsoLoginOperationConfig, SsoLoginOperationFull, type SsoLoginSpecType, type StandaloneDeviceInfoSource, type StepHelper, type StepIdentifier, type StepOptions, type StorageEngine, type SubflowTrigger, type SubflowType, type TelemetryEntry, type TelemetryLevel, type TelemetrySink, type TotpOperationConfig, TotpOperationFull, type TotpOperationPostResponseStart, type TotpOperationSpecType, type TrackerCoreOptions, type TrackerOptions, type TrackerPlugin, type TrackerStorageEngine, type Transport, type TransportMakeRequestResponse, type TransportOptions, type TrustedDeviceBindingMetadata, type TrustedDeviceCheckConfig, TrustedDeviceCheckOperationFull, type TrustedDeviceCheckResult, type TrustedDeviceCheckStepResult, type TrustedDeviceCheckTypedError, TrustedDeviceEnrollmentOperationFull, type TrustedDeviceEnrollmentResult, type TrustedDeviceOperationConfig, type TrustedDevicePurpose, type TrustedDeviceStorage, UNLOAD_BUDGET_BYTES, UNLOAD_PROBE_MAX_BYTES, type UserReference, type WebAuthnIdentifierProjector, type WebAuthnIdentifierProjectors, type WithHandoffs, appConfirmationOperationFull, authDecisionFinished, authDecisionStarted, cacheConfigRecord, captchaOperationFull, clearExperiment, clearExperiments, continueEmailLinkOperation, conversion, cookieStorage, createLogger, crossOriginSession, destroy, detectPasswordManagerExtensions, emailLinkOperationFull, emailOtpOperationFull, formOperationFull, getCrossOriginContext, getExperiments, getSessionId, getTracker, getTrackerCore, init, initCore, installProbeLane, keyRegistrationOperationFull, keySigningOperationFull, loadCachedConfig, loadConfigRecord, logError, logInfo, namespacedKey, parseReliabilityConfig, passkeyDeletionOperationFull, passkeyEnrollmentFullOperation, passkeyLoginFullOperation, passwordEnrollmentFullOperation, passwordLoginFullOperation, probe, probes, provideDataOperationFull, provideIdentifierOperationFull, rawErrors, resetSession, resolveFixedDataConfig, resolveRawErrorLimits, resolveReliabilityConfig, sanitizeAssertionResponse, sanitizeCreationOptions, sanitizeCreationResponse, sanitizeRequestOptions, serializeRawError, setCrossOriginContext, setExperiment, setExperiments, setFlowTags, setUser, smsOtpOperationFull, socialLoginOperationFull, ssoLoginOperationFull, telemetry, totpOperationFull, trackSubflowError, trustedDeviceCheckOperationFull, trustedDeviceEnrollmentOperationFull, utf8Length };