@wireai/activation 0.12.1 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +146 -1
  2. package/README.md +5 -3
  3. package/dist/analytics/index.d.mts +2 -2
  4. package/dist/analytics/index.d.ts +2 -2
  5. package/dist/analytics/index.js +114 -35
  6. package/dist/analytics/index.js.map +1 -1
  7. package/dist/analytics/index.mjs +114 -36
  8. package/dist/analytics/index.mjs.map +1 -1
  9. package/dist/{currentSession-BxEB37xt.d.ts → currentSession-D7zabMXK.d.ts} +161 -9
  10. package/dist/{currentSession-BlCeDP0f.d.mts → currentSession-_GynvhzT.d.mts} +161 -9
  11. package/dist/index.d.mts +5 -15
  12. package/dist/index.d.ts +5 -15
  13. package/dist/index.js +232 -135
  14. package/dist/index.js.map +1 -1
  15. package/dist/index.mjs +229 -134
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/questionnaire/index.js.map +1 -1
  18. package/dist/questionnaire/index.mjs.map +1 -1
  19. package/dist/reviews/index.js +8 -6
  20. package/dist/reviews/index.js.map +1 -1
  21. package/dist/reviews/index.mjs +8 -6
  22. package/dist/reviews/index.mjs.map +1 -1
  23. package/package.json +1 -1
  24. package/src/OnboardingFlow.tsx +10 -3
  25. package/src/WireOnboarding.tsx +115 -32
  26. package/src/activation/wireActivation.ts +13 -7
  27. package/src/analytics/analyticsFacade.ts +11 -10
  28. package/src/analytics/currentSession.ts +6 -20
  29. package/src/analytics/eventQueue.ts +69 -1
  30. package/src/analytics/index.ts +1 -1
  31. package/src/analytics/reportClientEvent.ts +92 -29
  32. package/src/config/wireConfigFromEnv.ts +1 -10
  33. package/src/context/deviceId.ts +77 -16
  34. package/src/context/userContext.ts +4 -15
  35. package/src/identity/identityRecord.ts +123 -0
  36. package/src/identity/userIdentity.ts +45 -9
  37. package/src/index.ts +6 -4
  38. package/src/session-analytics/useLifecycleEvents.ts +10 -1
  39. package/src/types.ts +14 -0
  40. package/src/utils/deriveAnswers.ts +6 -2
  41. package/src/utils/readProgress.ts +4 -0
  42. package/src/utils/warnInDev.ts +33 -0
  43. package/src/components/DoneBlock.tsx +0 -37
@@ -190,8 +190,17 @@ declare const reportClientEvent: (target: ClientEventTarget | undefined, event:
190
190
  * `/v1/events` path, but resolve only once the server has RESPONDED — so a decision re-fetch fired
191
191
  * immediately after is guaranteed to see the event in the session stream (this is the guarantee
192
192
  * `wire.track` needs before it triggers decision revalidation). Never throws: a missing/invalid
193
- * target, a missing `fetch`, a network error, or a non-2xx status all resolve to `false`. Resolves
194
- * `true` only on a 2xx response.
193
+ * target, a missing `fetch`, a network error, or a non-2xx status all resolve to `false`.
194
+ *
195
+ * ⚠️ 0.13.0: a 2xx is NO LONGER SUFFICIENT. The endpoint answers HTTP 200 with `{ ok, written,
196
+ * skipped }` and counts an event it refuses in `skipped`, so this used to resolve `true` for an event
197
+ * the server had thrown away — and `wire.track` then bumped decision revalidation, making every
198
+ * subscribed gate re-fetch against a stream the action never entered. It now reads the ack and
199
+ * resolves `false` when the server reports a positive `skipped`.
200
+ *
201
+ * BACKWARD COMPATIBLE BY CONSTRUCTION: only an explicit positive `skipped` demotes a 200. An old
202
+ * server that sends no such field, a body that cannot be parsed, or a response with no `.json` at all
203
+ * resolves `true` exactly as before — the change can produce no false negatives.
195
204
  */
196
205
  declare const reportClientEventsAwait: (target: ClientEventTarget | undefined, events: ClientEvent[]) => Promise<boolean>;
197
206
  /** Convenience single-event wrapper around {@link reportClientEventsAwait}. */
@@ -472,6 +481,20 @@ type OnboardingProgress = {
472
481
  total: number;
473
482
  /** Base-question key for the CURRENT screen, when known (used to pick a validator). */
474
483
  key?: string;
484
+ /**
485
+ * STABLE per-slot identity for the CURRENT screen, when the backend sends one. Preferred over
486
+ * {@link key} for both the answer key and the validator lookup.
487
+ *
488
+ * WHY IT EXISTS: `key` is authored from the question's prompt text (the tenant flows slugify it and
489
+ * cut at 32 chars), so re-wording a question mints a NEW key — the answer a host reads as
490
+ * `answers.interests` silently becomes `answers.what_are_you_into_v2`, with no error anywhere. A
491
+ * slot is the question's identity independent of its wording.
492
+ *
493
+ * FULLY ADDITIVE AND CURRENTLY INERT: no server emits it yet. Every fallback is PER-CARD, so a
494
+ * thread that mixes slotted and unslotted cards (the real shape during a rollout) keys each one
495
+ * correctly, and a backend that never sends it produces byte-identical behaviour to 0.12.2.
496
+ */
497
+ slot_id?: string;
475
498
  /** Whether the CURRENT screen may be skipped (backend-marked; default false → no Skip shown). */
476
499
  skippable?: boolean;
477
500
  };
@@ -638,6 +661,10 @@ type EventQueue = {
638
661
  /** Current pending (in-memory) count. */
639
662
  size(): number;
640
663
  };
664
+ /** Test-only: forget every claimed queue key. A real RELAUNCH is a new process, so a test that
665
+ * simulates one in-process must call this or its second queue reads as a concurrent sibling.
666
+ * Exported from `@wireai/activation/analytics`, matching `resetAutoDeviceKeys` / `resetCurrentSessionId`. */
667
+ declare const resetEventQueueKeys: () => void;
641
668
  /**
642
669
  * Create an offline-first event queue. Loads any persisted backlog on creation so a
643
670
  * killed-and-relaunched app resumes where it left off. Returns the {@link EventQueue} surface.
@@ -705,8 +732,6 @@ interface ResolvedUserContext {
705
732
  /** The `user_context` bucket (device_key, app_version, user_email[+ _hashed], custom.*). */
706
733
  userContext?: Record<string, string | number | boolean>;
707
734
  }
708
- /** Reserved `user_context` keys the kit itself writes; host `extra` is namespaced away from these. */
709
- declare const RESERVED_USER_CONTEXT_KEYS: readonly ["device_key", "app_version", "app_build", "network_type", "session_count", "returning", "platform", "user_email", "user_email_hashed"];
710
735
  /** The prefix applied to every host `extra` key so it can never collide with a reserved key. */
711
736
  declare const EXTRA_KEY_PREFIX: "custom.";
712
737
  /** A finite scalar the wire accepts. Non-finite numbers (NaN/Infinity) are NOT scalars here. */
@@ -831,17 +856,127 @@ type IdentifyOnboardingOptions = {
831
856
  appId?: string;
832
857
  /** Storage key override — pass the same `persistKey` you gave `<WireOnboarding>`, if any. */
833
858
  persistKey?: string;
859
+ /**
860
+ * OPT-IN LAST RESORT, default `false`. When no ONBOARDING session can be resolved (no `contextId`,
861
+ * nothing in `storage`), bind the user to the LIVE PER-OPEN app session instead and return
862
+ * `"app_session"`.
863
+ *
864
+ * ⚠️ These are two different id spaces sharing one wire field. An onboarding session id is the A2A
865
+ * `contextId`; a per-open id is what `app.session_started` registers. The server's onboarding funnel
866
+ * groups by `session_id`, so a per-open id posted here does not attach the user to their onboarding
867
+ * — it writes a row nothing in that funnel can join. Until 0.13.0 this happened SILENTLY and
868
+ * returned `true`, in exactly the documented post-completion case (completion clears the persisted
869
+ * session), so the funnel stayed unattributed while the host was told it had worked.
870
+ *
871
+ * Turn it on only if binding the id to *some* session the server saw is genuinely worth more to you
872
+ * than knowing the onboarding bind failed — and read the return value, which now says which it was.
873
+ */
874
+ allowAppSessionFallback?: boolean;
834
875
  };
876
+ /**
877
+ * What {@link identifyOnboarding} bound, and to WHICH id space — because `true` could not say.
878
+ *
879
+ * • `"onboarding"` — bound to the A2A `contextId`. This is the one that attributes the funnel.
880
+ * • `"app_session"` — bound to the live per-open app session, via `allowAppSessionFallback`. The
881
+ * server saw that session, but it is not this user's onboarding.
882
+ * • `false` — nothing was dispatched (no user id, no server url, no resolvable session).
883
+ *
884
+ * ⚠️ 0.13.0 widened this from `boolean`. `"onboarding"` is truthy, so an `if (await identify…)` still
885
+ * behaves identically; only an explicit `: boolean` annotation needs updating.
886
+ */
887
+ type IdentifyOnboardingBinding = "onboarding" | "app_session" | false;
835
888
  /**
836
889
  * Attach a host user id to an onboarding session AFTER the fact (post-registration), by sending
837
890
  * an `identify` client event to `/v1/events`. Resolves the contextId from an explicit
838
891
  * `contextId` or, failing that, from the persisted session in the host `storage`.
839
892
  *
840
- * Fire-and-forget under the hood (never throws, never blocks onboarding). Resolves to `true`
841
- * when an identify event was dispatched, `false` when it couldn't (no user id, no server url,
842
- * or no resolvable contextId).
893
+ * Fire-and-forget under the hood (never throws, never blocks onboarding). Resolves to the
894
+ * {@link IdentifyOnboardingBinding} that says WHICH id space was bound, or `false` when nothing could
895
+ * be (no user id, no server url, or no resolvable session).
843
896
  */
844
- declare const identifyOnboarding: (opts: IdentifyOnboardingOptions) => Promise<boolean>;
897
+ declare const identifyOnboarding: (opts: IdentifyOnboardingOptions) => Promise<IdentifyOnboardingBinding>;
898
+
899
+ /**
900
+ * identityRecord — the ONE provenance-carrying shape for an id the kit puts on the wire.
901
+ *
902
+ * WHY IT EXISTS. `session_id` and `device_key` are bare `string`s minted independently by four
903
+ * subsystems, and nothing anywhere recorded WHERE a given id came from. Every id-layer defect this
904
+ * release fixes is a direct consequence of that one omission:
905
+ *
906
+ * • a rejecting storage adapter's in-memory id was indistinguishable from a persisted one, so the
907
+ * kit injected a fresh per-launch join key on every launch — nothing carried `durable`.
908
+ * • an app-OPEN session id could be posted into a field that means the ONBOARDING session, and the
909
+ * caller was told `true` — nothing carried `space`.
910
+ * • an auto-minted `wdev_*` could be injected beside a device id the host demonstrably owns on
911
+ * another surface, silently — nothing carried `source`.
912
+ *
913
+ * WHAT THIS IS, AND WHAT IT DELIBERATELY IS NOT. It is a small record plus a process-wide registry of
914
+ * the ids a HOST supplied. It is NOT a branded-type refactor (`OnboardingSessionId` / `AppSessionId` /
915
+ * `DeviceKey` across every signature) — that is real value and it is deferred, because it touches
916
+ * every file and is not what makes a number correct this week. Nothing here changes the wire.
917
+ *
918
+ * WHY A `Symbol.for` REGISTRY. Same reason as `analytics/currentSession` and `context/deviceId`: tsup
919
+ * inlines a separate copy of a module into each bundle (`.` and `./analytics`), so a plain module
920
+ * `let` would give every bundle its own registry and the cross-surface question this exists to answer
921
+ * ("did ANY surface in this process get a host-supplied device key?") would read `no` from the wrong
922
+ * copy. `Symbol.for` resolves to one slot on `globalThis` no matter how many copies exist.
923
+ */
924
+ /**
925
+ * Which id space a value belongs to. These are NOT interchangeable, and the whole point of naming
926
+ * them is that a value from one space must never be posted into a field that means another:
927
+ * • `onboarding-session` — the A2A `contextId` for ONE onboarding run.
928
+ * • `app-session` — the per-app-open session id (`app.session_started`).
929
+ * • `device` — the per-install `device_key`; the only cross-family join key.
930
+ */
931
+ type IdentitySpace = "onboarding-session" | "app-session" | "device";
932
+ /** Where the value came from: the host handed it over, or the kit minted it. */
933
+ type IdentitySource = "host" | "auto";
934
+ /** An id plus everything a consumer needs to decide whether it may use it. */
935
+ type IdentityRecord = {
936
+ /** The id itself, trimmed. Never empty (a blank input yields no record at all). */
937
+ value: string;
938
+ /** Which id space {@link value} belongs to. */
939
+ space: IdentitySpace;
940
+ /** `host` = the integrator supplied it; `auto` = the kit minted it. */
941
+ source: IdentitySource;
942
+ /**
943
+ * Whether the value was actually PERSISTED (or adopted from persistence), as opposed to living
944
+ * only in this process's memory. A non-durable auto id is a DIFFERENT id on the next launch, which
945
+ * for a `device` value is worse than no value at all: the server counts `min_sessions` by distinct
946
+ * opens grouped on `device_key`, so a per-launch key corrupts the counter rather than leaving it
947
+ * empty. A host-supplied value is durable by definition — the host owns its lifetime.
948
+ */
949
+ durable: boolean;
950
+ };
951
+ /** Input to {@link resolveIdentity}. `value` is `unknown` so callers can pass a raw prop through. */
952
+ type ResolveIdentityInput = {
953
+ value: unknown;
954
+ space: IdentitySpace;
955
+ source: IdentitySource;
956
+ /** Defaults to `true` for a host value (the host owns its lifetime) and `false` otherwise. */
957
+ durable?: boolean;
958
+ /** Tenant/app id — two tenants in one process never share a provenance entry. */
959
+ scope?: string;
960
+ };
961
+ /**
962
+ * Build an {@link IdentityRecord} from a candidate value, or `undefined` when there is nothing usable
963
+ * (a non-string, or blank after trimming) — so a caller can `if (record)`-gate instead of guessing
964
+ * whether an empty string means "none" or "not yet".
965
+ *
966
+ * SIDE EFFECT, deliberate and the reason this is a function and not an object literal: a `host`-sourced
967
+ * record is RECORDED on the process registry, so a later surface can ask {@link hostIdentity} whether
968
+ * this process demonstrably owns a host id in that space. That is what turns "the kit injected its own
969
+ * key" from a silent third id space into a warnable condition. Never throws.
970
+ */
971
+ declare const resolveIdentity: (input: ResolveIdentityInput) => IdentityRecord | undefined;
972
+ /**
973
+ * The HOST-supplied id this process has seen for a space, or `undefined` when every surface so far
974
+ * let the kit mint its own. Answers the cross-surface question no single mount can answer alone:
975
+ * "does this app own a device id that this particular mount was not given?"
976
+ */
977
+ declare const hostIdentity: (space: IdentitySpace, scope?: string) => string | undefined;
978
+ /** Test-only: forget every recorded host identity so a unit test starts from a clean registry. */
979
+ declare const resetIdentityProvenance: () => void;
845
980
 
846
981
  /**
847
982
  * deviceId — mint a stable, NON-PII, per-install device id the kit owns when the host supplies
@@ -862,6 +997,7 @@ declare const identifyOnboarding: (opts: IdentifyOnboardingOptions) => Promise<b
862
997
  * A host that wants its OWN device id still wins: pass `WireUserContext.deviceKey` and the kit uses
863
998
  * that verbatim and never mints/persists an auto id.
864
999
  */
1000
+
865
1001
  /** Prefix so an auto-minted id is visibly the kit's (distinguishable from a host-supplied `deviceKey`). */
866
1002
  declare const AUTO_DEVICE_ID_PREFIX = "wdev_";
867
1003
  /** The storage key the façade persists the auto-minted id under (namespaced per `appId`). */
@@ -917,6 +1053,22 @@ declare const resolveAutoDeviceKey: (opts?: ResolveAutoDeviceKeyOptions) => stri
917
1053
  * with no `storage` it resolves immediately (there is nothing to hydrate from).
918
1054
  */
919
1055
  declare const hydrateAutoDeviceKey: (opts?: ResolveAutoDeviceKeyOptions) => Promise<string>;
1056
+ /**
1057
+ * The PROVENANCE-CARRYING sibling of {@link hydrateAutoDeviceKey}: the same awaited read, but it
1058
+ * answers "is this id one this install will KEEP?" instead of only "what is the id?".
1059
+ *
1060
+ * WHY IT EXISTS (K1). `<WireOnboarding>` gated auto-injection on `Boolean(storage)` — the presence of
1061
+ * the prop — because a string carries no provenance and there was nothing better to gate on. A
1062
+ * REJECTING adapter therefore injected a fresh `wdev_*` on every launch: strictly worse than
1063
+ * injecting nothing, since the server counts `min_sessions` by distinct opens grouped on `device_key`,
1064
+ * so a per-launch key corrupts that counter AND inflates distinct-device counts. Callers that write a
1065
+ * key onto the wire as a cross-launch join must read `durable` and refuse a `false`.
1066
+ *
1067
+ * Resolves `undefined` only when there is no usable id at all. With no `storage` it resolves
1068
+ * immediately with `durable: false` — a process-scoped id is exactly what "no persistence" means.
1069
+ * Never throws or rejects.
1070
+ */
1071
+ declare const hydrateDeviceIdentity: (opts?: ResolveAutoDeviceKeyOptions) => Promise<IdentityRecord | undefined>;
920
1072
  /** Test-only: forget every auto id + hydration flag so a unit test starts from a clean registry. */
921
1073
  declare const resetAutoDeviceKeys: () => void;
922
1074
 
@@ -948,4 +1100,4 @@ declare const resetCurrentSessionId: () => void;
948
1100
  */
949
1101
  declare const ensureCurrentSessionId: () => string;
950
1102
 
951
- export { hydrateAutoDeviceKey as $, AUTO_DEVICE_ID_PREFIX as A, resolveAutoDeviceKey as B, type ClearUserContextOptions as C, type DeviceKeyStorage as D, type EventQueueOptions as E, setCurrentSessionId as F, toAnalyticsEvent as G, type WireOnboardingProps as H, type WireOnboardingConfig as I, type OnboardingEvent as J, type OnboardingCopy as K, type DeviceContext as L, type DeviceFormFactor as M, EXTRA_KEY_PREFIX as N, type OnboardingResult as O, type IdentifyOnboardingOptions as P, type OnboardingProgress as Q, type ResolveAutoDeviceKeyOptions as R, type StepValidator as S, RESERVED_USER_CONTEXT_KEYS as T, type ResolveUserContextOptions as U, type ResolvedUserContext as V, type WireUserContext as W, USER_ID_MAX_LENGTH as X, activationJoinContext as Y, collectDeviceContext as Z, hashEmailFnv1a as _, type AnalyticsEvent as a, identifyOnboarding as a0, isWireScalar as a1, mintDeviceId as a2, namespaceExtra as a3, resolveUserContext as a4, sanitizeUserId as a5, type ClientEvent as b, type ClientEventTarget as c, type ClientEventType as d, type ContextEnvelope as e, type ContextEnvelopeInput as f, type EnvelopeSource as g, type EventQueue as h, WIRE_ONBOARDING_EVENTS as i, type WireOnboardingEventName as j, analyticsUserIdStorageKey as k, buildContextEnvelope as l, clearPiiFromContext as m, clearUserContext as n, createEventQueue as o, deviceIdStorageKey as p, ensureCurrentSessionId as q, getCurrentSessionId as r, looksLikeEmail as s, makeSessionId as t, reportClientEvent as u, reportClientEventAwait as v, reportClientEvents as w, reportClientEventsAwait as x, resetAutoDeviceKeys as y, resetCurrentSessionId as z };
1103
+ export { USER_ID_MAX_LENGTH as $, AUTO_DEVICE_ID_PREFIX as A, resetEventQueueKeys as B, type ClearUserContextOptions as C, type DeviceKeyStorage as D, type EventQueueOptions as E, resolveAutoDeviceKey as F, setCurrentSessionId as G, toAnalyticsEvent as H, type WireOnboardingProps as I, type WireOnboardingConfig as J, type OnboardingEvent as K, type OnboardingCopy as L, type DeviceContext as M, type DeviceFormFactor as N, type OnboardingResult as O, EXTRA_KEY_PREFIX as P, type IdentifyOnboardingBinding as Q, type ResolveAutoDeviceKeyOptions as R, type StepValidator as S, type IdentifyOnboardingOptions as T, type IdentityRecord as U, type IdentitySource as V, type WireUserContext as W, type IdentitySpace as X, type OnboardingProgress as Y, type ResolveUserContextOptions as Z, type ResolvedUserContext as _, type AnalyticsEvent as a, activationJoinContext as a0, collectDeviceContext as a1, hashEmailFnv1a as a2, hostIdentity as a3, hydrateAutoDeviceKey as a4, hydrateDeviceIdentity as a5, identifyOnboarding as a6, isWireScalar as a7, mintDeviceId as a8, namespaceExtra as a9, resetIdentityProvenance as aa, resolveIdentity as ab, resolveUserContext as ac, sanitizeUserId as ad, type ClientEvent as b, type ClientEventTarget as c, type ClientEventType as d, type ContextEnvelope as e, type ContextEnvelopeInput as f, type EnvelopeSource as g, type EventQueue as h, WIRE_ONBOARDING_EVENTS as i, type WireOnboardingEventName as j, analyticsUserIdStorageKey as k, buildContextEnvelope as l, clearPiiFromContext as m, clearUserContext as n, createEventQueue as o, deviceIdStorageKey as p, ensureCurrentSessionId as q, getCurrentSessionId as r, looksLikeEmail as s, makeSessionId as t, reportClientEvent as u, reportClientEventAwait as v, reportClientEvents as w, reportClientEventsAwait as x, resetAutoDeviceKeys as y, resetCurrentSessionId as z };
@@ -190,8 +190,17 @@ declare const reportClientEvent: (target: ClientEventTarget | undefined, event:
190
190
  * `/v1/events` path, but resolve only once the server has RESPONDED — so a decision re-fetch fired
191
191
  * immediately after is guaranteed to see the event in the session stream (this is the guarantee
192
192
  * `wire.track` needs before it triggers decision revalidation). Never throws: a missing/invalid
193
- * target, a missing `fetch`, a network error, or a non-2xx status all resolve to `false`. Resolves
194
- * `true` only on a 2xx response.
193
+ * target, a missing `fetch`, a network error, or a non-2xx status all resolve to `false`.
194
+ *
195
+ * ⚠️ 0.13.0: a 2xx is NO LONGER SUFFICIENT. The endpoint answers HTTP 200 with `{ ok, written,
196
+ * skipped }` and counts an event it refuses in `skipped`, so this used to resolve `true` for an event
197
+ * the server had thrown away — and `wire.track` then bumped decision revalidation, making every
198
+ * subscribed gate re-fetch against a stream the action never entered. It now reads the ack and
199
+ * resolves `false` when the server reports a positive `skipped`.
200
+ *
201
+ * BACKWARD COMPATIBLE BY CONSTRUCTION: only an explicit positive `skipped` demotes a 200. An old
202
+ * server that sends no such field, a body that cannot be parsed, or a response with no `.json` at all
203
+ * resolves `true` exactly as before — the change can produce no false negatives.
195
204
  */
196
205
  declare const reportClientEventsAwait: (target: ClientEventTarget | undefined, events: ClientEvent[]) => Promise<boolean>;
197
206
  /** Convenience single-event wrapper around {@link reportClientEventsAwait}. */
@@ -472,6 +481,20 @@ type OnboardingProgress = {
472
481
  total: number;
473
482
  /** Base-question key for the CURRENT screen, when known (used to pick a validator). */
474
483
  key?: string;
484
+ /**
485
+ * STABLE per-slot identity for the CURRENT screen, when the backend sends one. Preferred over
486
+ * {@link key} for both the answer key and the validator lookup.
487
+ *
488
+ * WHY IT EXISTS: `key` is authored from the question's prompt text (the tenant flows slugify it and
489
+ * cut at 32 chars), so re-wording a question mints a NEW key — the answer a host reads as
490
+ * `answers.interests` silently becomes `answers.what_are_you_into_v2`, with no error anywhere. A
491
+ * slot is the question's identity independent of its wording.
492
+ *
493
+ * FULLY ADDITIVE AND CURRENTLY INERT: no server emits it yet. Every fallback is PER-CARD, so a
494
+ * thread that mixes slotted and unslotted cards (the real shape during a rollout) keys each one
495
+ * correctly, and a backend that never sends it produces byte-identical behaviour to 0.12.2.
496
+ */
497
+ slot_id?: string;
475
498
  /** Whether the CURRENT screen may be skipped (backend-marked; default false → no Skip shown). */
476
499
  skippable?: boolean;
477
500
  };
@@ -638,6 +661,10 @@ type EventQueue = {
638
661
  /** Current pending (in-memory) count. */
639
662
  size(): number;
640
663
  };
664
+ /** Test-only: forget every claimed queue key. A real RELAUNCH is a new process, so a test that
665
+ * simulates one in-process must call this or its second queue reads as a concurrent sibling.
666
+ * Exported from `@wireai/activation/analytics`, matching `resetAutoDeviceKeys` / `resetCurrentSessionId`. */
667
+ declare const resetEventQueueKeys: () => void;
641
668
  /**
642
669
  * Create an offline-first event queue. Loads any persisted backlog on creation so a
643
670
  * killed-and-relaunched app resumes where it left off. Returns the {@link EventQueue} surface.
@@ -705,8 +732,6 @@ interface ResolvedUserContext {
705
732
  /** The `user_context` bucket (device_key, app_version, user_email[+ _hashed], custom.*). */
706
733
  userContext?: Record<string, string | number | boolean>;
707
734
  }
708
- /** Reserved `user_context` keys the kit itself writes; host `extra` is namespaced away from these. */
709
- declare const RESERVED_USER_CONTEXT_KEYS: readonly ["device_key", "app_version", "app_build", "network_type", "session_count", "returning", "platform", "user_email", "user_email_hashed"];
710
735
  /** The prefix applied to every host `extra` key so it can never collide with a reserved key. */
711
736
  declare const EXTRA_KEY_PREFIX: "custom.";
712
737
  /** A finite scalar the wire accepts. Non-finite numbers (NaN/Infinity) are NOT scalars here. */
@@ -831,17 +856,127 @@ type IdentifyOnboardingOptions = {
831
856
  appId?: string;
832
857
  /** Storage key override — pass the same `persistKey` you gave `<WireOnboarding>`, if any. */
833
858
  persistKey?: string;
859
+ /**
860
+ * OPT-IN LAST RESORT, default `false`. When no ONBOARDING session can be resolved (no `contextId`,
861
+ * nothing in `storage`), bind the user to the LIVE PER-OPEN app session instead and return
862
+ * `"app_session"`.
863
+ *
864
+ * ⚠️ These are two different id spaces sharing one wire field. An onboarding session id is the A2A
865
+ * `contextId`; a per-open id is what `app.session_started` registers. The server's onboarding funnel
866
+ * groups by `session_id`, so a per-open id posted here does not attach the user to their onboarding
867
+ * — it writes a row nothing in that funnel can join. Until 0.13.0 this happened SILENTLY and
868
+ * returned `true`, in exactly the documented post-completion case (completion clears the persisted
869
+ * session), so the funnel stayed unattributed while the host was told it had worked.
870
+ *
871
+ * Turn it on only if binding the id to *some* session the server saw is genuinely worth more to you
872
+ * than knowing the onboarding bind failed — and read the return value, which now says which it was.
873
+ */
874
+ allowAppSessionFallback?: boolean;
834
875
  };
876
+ /**
877
+ * What {@link identifyOnboarding} bound, and to WHICH id space — because `true` could not say.
878
+ *
879
+ * • `"onboarding"` — bound to the A2A `contextId`. This is the one that attributes the funnel.
880
+ * • `"app_session"` — bound to the live per-open app session, via `allowAppSessionFallback`. The
881
+ * server saw that session, but it is not this user's onboarding.
882
+ * • `false` — nothing was dispatched (no user id, no server url, no resolvable session).
883
+ *
884
+ * ⚠️ 0.13.0 widened this from `boolean`. `"onboarding"` is truthy, so an `if (await identify…)` still
885
+ * behaves identically; only an explicit `: boolean` annotation needs updating.
886
+ */
887
+ type IdentifyOnboardingBinding = "onboarding" | "app_session" | false;
835
888
  /**
836
889
  * Attach a host user id to an onboarding session AFTER the fact (post-registration), by sending
837
890
  * an `identify` client event to `/v1/events`. Resolves the contextId from an explicit
838
891
  * `contextId` or, failing that, from the persisted session in the host `storage`.
839
892
  *
840
- * Fire-and-forget under the hood (never throws, never blocks onboarding). Resolves to `true`
841
- * when an identify event was dispatched, `false` when it couldn't (no user id, no server url,
842
- * or no resolvable contextId).
893
+ * Fire-and-forget under the hood (never throws, never blocks onboarding). Resolves to the
894
+ * {@link IdentifyOnboardingBinding} that says WHICH id space was bound, or `false` when nothing could
895
+ * be (no user id, no server url, or no resolvable session).
843
896
  */
844
- declare const identifyOnboarding: (opts: IdentifyOnboardingOptions) => Promise<boolean>;
897
+ declare const identifyOnboarding: (opts: IdentifyOnboardingOptions) => Promise<IdentifyOnboardingBinding>;
898
+
899
+ /**
900
+ * identityRecord — the ONE provenance-carrying shape for an id the kit puts on the wire.
901
+ *
902
+ * WHY IT EXISTS. `session_id` and `device_key` are bare `string`s minted independently by four
903
+ * subsystems, and nothing anywhere recorded WHERE a given id came from. Every id-layer defect this
904
+ * release fixes is a direct consequence of that one omission:
905
+ *
906
+ * • a rejecting storage adapter's in-memory id was indistinguishable from a persisted one, so the
907
+ * kit injected a fresh per-launch join key on every launch — nothing carried `durable`.
908
+ * • an app-OPEN session id could be posted into a field that means the ONBOARDING session, and the
909
+ * caller was told `true` — nothing carried `space`.
910
+ * • an auto-minted `wdev_*` could be injected beside a device id the host demonstrably owns on
911
+ * another surface, silently — nothing carried `source`.
912
+ *
913
+ * WHAT THIS IS, AND WHAT IT DELIBERATELY IS NOT. It is a small record plus a process-wide registry of
914
+ * the ids a HOST supplied. It is NOT a branded-type refactor (`OnboardingSessionId` / `AppSessionId` /
915
+ * `DeviceKey` across every signature) — that is real value and it is deferred, because it touches
916
+ * every file and is not what makes a number correct this week. Nothing here changes the wire.
917
+ *
918
+ * WHY A `Symbol.for` REGISTRY. Same reason as `analytics/currentSession` and `context/deviceId`: tsup
919
+ * inlines a separate copy of a module into each bundle (`.` and `./analytics`), so a plain module
920
+ * `let` would give every bundle its own registry and the cross-surface question this exists to answer
921
+ * ("did ANY surface in this process get a host-supplied device key?") would read `no` from the wrong
922
+ * copy. `Symbol.for` resolves to one slot on `globalThis` no matter how many copies exist.
923
+ */
924
+ /**
925
+ * Which id space a value belongs to. These are NOT interchangeable, and the whole point of naming
926
+ * them is that a value from one space must never be posted into a field that means another:
927
+ * • `onboarding-session` — the A2A `contextId` for ONE onboarding run.
928
+ * • `app-session` — the per-app-open session id (`app.session_started`).
929
+ * • `device` — the per-install `device_key`; the only cross-family join key.
930
+ */
931
+ type IdentitySpace = "onboarding-session" | "app-session" | "device";
932
+ /** Where the value came from: the host handed it over, or the kit minted it. */
933
+ type IdentitySource = "host" | "auto";
934
+ /** An id plus everything a consumer needs to decide whether it may use it. */
935
+ type IdentityRecord = {
936
+ /** The id itself, trimmed. Never empty (a blank input yields no record at all). */
937
+ value: string;
938
+ /** Which id space {@link value} belongs to. */
939
+ space: IdentitySpace;
940
+ /** `host` = the integrator supplied it; `auto` = the kit minted it. */
941
+ source: IdentitySource;
942
+ /**
943
+ * Whether the value was actually PERSISTED (or adopted from persistence), as opposed to living
944
+ * only in this process's memory. A non-durable auto id is a DIFFERENT id on the next launch, which
945
+ * for a `device` value is worse than no value at all: the server counts `min_sessions` by distinct
946
+ * opens grouped on `device_key`, so a per-launch key corrupts the counter rather than leaving it
947
+ * empty. A host-supplied value is durable by definition — the host owns its lifetime.
948
+ */
949
+ durable: boolean;
950
+ };
951
+ /** Input to {@link resolveIdentity}. `value` is `unknown` so callers can pass a raw prop through. */
952
+ type ResolveIdentityInput = {
953
+ value: unknown;
954
+ space: IdentitySpace;
955
+ source: IdentitySource;
956
+ /** Defaults to `true` for a host value (the host owns its lifetime) and `false` otherwise. */
957
+ durable?: boolean;
958
+ /** Tenant/app id — two tenants in one process never share a provenance entry. */
959
+ scope?: string;
960
+ };
961
+ /**
962
+ * Build an {@link IdentityRecord} from a candidate value, or `undefined` when there is nothing usable
963
+ * (a non-string, or blank after trimming) — so a caller can `if (record)`-gate instead of guessing
964
+ * whether an empty string means "none" or "not yet".
965
+ *
966
+ * SIDE EFFECT, deliberate and the reason this is a function and not an object literal: a `host`-sourced
967
+ * record is RECORDED on the process registry, so a later surface can ask {@link hostIdentity} whether
968
+ * this process demonstrably owns a host id in that space. That is what turns "the kit injected its own
969
+ * key" from a silent third id space into a warnable condition. Never throws.
970
+ */
971
+ declare const resolveIdentity: (input: ResolveIdentityInput) => IdentityRecord | undefined;
972
+ /**
973
+ * The HOST-supplied id this process has seen for a space, or `undefined` when every surface so far
974
+ * let the kit mint its own. Answers the cross-surface question no single mount can answer alone:
975
+ * "does this app own a device id that this particular mount was not given?"
976
+ */
977
+ declare const hostIdentity: (space: IdentitySpace, scope?: string) => string | undefined;
978
+ /** Test-only: forget every recorded host identity so a unit test starts from a clean registry. */
979
+ declare const resetIdentityProvenance: () => void;
845
980
 
846
981
  /**
847
982
  * deviceId — mint a stable, NON-PII, per-install device id the kit owns when the host supplies
@@ -862,6 +997,7 @@ declare const identifyOnboarding: (opts: IdentifyOnboardingOptions) => Promise<b
862
997
  * A host that wants its OWN device id still wins: pass `WireUserContext.deviceKey` and the kit uses
863
998
  * that verbatim and never mints/persists an auto id.
864
999
  */
1000
+
865
1001
  /** Prefix so an auto-minted id is visibly the kit's (distinguishable from a host-supplied `deviceKey`). */
866
1002
  declare const AUTO_DEVICE_ID_PREFIX = "wdev_";
867
1003
  /** The storage key the façade persists the auto-minted id under (namespaced per `appId`). */
@@ -917,6 +1053,22 @@ declare const resolveAutoDeviceKey: (opts?: ResolveAutoDeviceKeyOptions) => stri
917
1053
  * with no `storage` it resolves immediately (there is nothing to hydrate from).
918
1054
  */
919
1055
  declare const hydrateAutoDeviceKey: (opts?: ResolveAutoDeviceKeyOptions) => Promise<string>;
1056
+ /**
1057
+ * The PROVENANCE-CARRYING sibling of {@link hydrateAutoDeviceKey}: the same awaited read, but it
1058
+ * answers "is this id one this install will KEEP?" instead of only "what is the id?".
1059
+ *
1060
+ * WHY IT EXISTS (K1). `<WireOnboarding>` gated auto-injection on `Boolean(storage)` — the presence of
1061
+ * the prop — because a string carries no provenance and there was nothing better to gate on. A
1062
+ * REJECTING adapter therefore injected a fresh `wdev_*` on every launch: strictly worse than
1063
+ * injecting nothing, since the server counts `min_sessions` by distinct opens grouped on `device_key`,
1064
+ * so a per-launch key corrupts that counter AND inflates distinct-device counts. Callers that write a
1065
+ * key onto the wire as a cross-launch join must read `durable` and refuse a `false`.
1066
+ *
1067
+ * Resolves `undefined` only when there is no usable id at all. With no `storage` it resolves
1068
+ * immediately with `durable: false` — a process-scoped id is exactly what "no persistence" means.
1069
+ * Never throws or rejects.
1070
+ */
1071
+ declare const hydrateDeviceIdentity: (opts?: ResolveAutoDeviceKeyOptions) => Promise<IdentityRecord | undefined>;
920
1072
  /** Test-only: forget every auto id + hydration flag so a unit test starts from a clean registry. */
921
1073
  declare const resetAutoDeviceKeys: () => void;
922
1074
 
@@ -948,4 +1100,4 @@ declare const resetCurrentSessionId: () => void;
948
1100
  */
949
1101
  declare const ensureCurrentSessionId: () => string;
950
1102
 
951
- export { hydrateAutoDeviceKey as $, AUTO_DEVICE_ID_PREFIX as A, resolveAutoDeviceKey as B, type ClearUserContextOptions as C, type DeviceKeyStorage as D, type EventQueueOptions as E, setCurrentSessionId as F, toAnalyticsEvent as G, type WireOnboardingProps as H, type WireOnboardingConfig as I, type OnboardingEvent as J, type OnboardingCopy as K, type DeviceContext as L, type DeviceFormFactor as M, EXTRA_KEY_PREFIX as N, type OnboardingResult as O, type IdentifyOnboardingOptions as P, type OnboardingProgress as Q, type ResolveAutoDeviceKeyOptions as R, type StepValidator as S, RESERVED_USER_CONTEXT_KEYS as T, type ResolveUserContextOptions as U, type ResolvedUserContext as V, type WireUserContext as W, USER_ID_MAX_LENGTH as X, activationJoinContext as Y, collectDeviceContext as Z, hashEmailFnv1a as _, type AnalyticsEvent as a, identifyOnboarding as a0, isWireScalar as a1, mintDeviceId as a2, namespaceExtra as a3, resolveUserContext as a4, sanitizeUserId as a5, type ClientEvent as b, type ClientEventTarget as c, type ClientEventType as d, type ContextEnvelope as e, type ContextEnvelopeInput as f, type EnvelopeSource as g, type EventQueue as h, WIRE_ONBOARDING_EVENTS as i, type WireOnboardingEventName as j, analyticsUserIdStorageKey as k, buildContextEnvelope as l, clearPiiFromContext as m, clearUserContext as n, createEventQueue as o, deviceIdStorageKey as p, ensureCurrentSessionId as q, getCurrentSessionId as r, looksLikeEmail as s, makeSessionId as t, reportClientEvent as u, reportClientEventAwait as v, reportClientEvents as w, reportClientEventsAwait as x, resetAutoDeviceKeys as y, resetCurrentSessionId as z };
1103
+ export { USER_ID_MAX_LENGTH as $, AUTO_DEVICE_ID_PREFIX as A, resetEventQueueKeys as B, type ClearUserContextOptions as C, type DeviceKeyStorage as D, type EventQueueOptions as E, resolveAutoDeviceKey as F, setCurrentSessionId as G, toAnalyticsEvent as H, type WireOnboardingProps as I, type WireOnboardingConfig as J, type OnboardingEvent as K, type OnboardingCopy as L, type DeviceContext as M, type DeviceFormFactor as N, type OnboardingResult as O, EXTRA_KEY_PREFIX as P, type IdentifyOnboardingBinding as Q, type ResolveAutoDeviceKeyOptions as R, type StepValidator as S, type IdentifyOnboardingOptions as T, type IdentityRecord as U, type IdentitySource as V, type WireUserContext as W, type IdentitySpace as X, type OnboardingProgress as Y, type ResolveUserContextOptions as Z, type ResolvedUserContext as _, type AnalyticsEvent as a, activationJoinContext as a0, collectDeviceContext as a1, hashEmailFnv1a as a2, hostIdentity as a3, hydrateAutoDeviceKey as a4, hydrateDeviceIdentity as a5, identifyOnboarding as a6, isWireScalar as a7, mintDeviceId as a8, namespaceExtra as a9, resetIdentityProvenance as aa, resolveIdentity as ab, resolveUserContext as ac, sanitizeUserId as ad, type ClientEvent as b, type ClientEventTarget as c, type ClientEventType as d, type ContextEnvelope as e, type ContextEnvelopeInput as f, type EnvelopeSource as g, type EventQueue as h, WIRE_ONBOARDING_EVENTS as i, type WireOnboardingEventName as j, analyticsUserIdStorageKey as k, buildContextEnvelope as l, clearPiiFromContext as m, clearUserContext as n, createEventQueue as o, deviceIdStorageKey as p, ensureCurrentSessionId as q, getCurrentSessionId as r, looksLikeEmail as s, makeSessionId as t, reportClientEvent as u, reportClientEventAwait as v, reportClientEvents as w, reportClientEventsAwait as x, resetAutoDeviceKeys as y, resetCurrentSessionId as z };
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import React__default, { ReactNode } from 'react';
3
- import { H as WireOnboardingProps, I as WireOnboardingConfig, O as OnboardingResult, S as StepValidator, J as OnboardingEvent, K as OnboardingCopy, c as ClientEventTarget, L as DeviceContext, W as WireUserContext, b as ClientEvent, g as EnvelopeSource } from './currentSession-BlCeDP0f.mjs';
4
- export { A as AUTO_DEVICE_ID_PREFIX, a as AnalyticsEvent, C as ClearUserContextOptions, d as ClientEventType, M as DeviceFormFactor, D as DeviceKeyStorage, N as EXTRA_KEY_PREFIX, P as IdentifyOnboardingOptions, Q as OnboardingProgress, T as RESERVED_USER_CONTEXT_KEYS, R as ResolveAutoDeviceKeyOptions, U as ResolveUserContextOptions, V as ResolvedUserContext, X as USER_ID_MAX_LENGTH, i as WIRE_ONBOARDING_EVENTS, j as WireOnboardingEventName, Y as activationJoinContext, k as analyticsUserIdStorageKey, m as clearPiiFromContext, n as clearUserContext, Z as collectDeviceContext, p as deviceIdStorageKey, q as ensureCurrentSessionId, r as getCurrentSessionId, _ as hashEmailFnv1a, $ as hydrateAutoDeviceKey, a0 as identifyOnboarding, a1 as isWireScalar, s as looksLikeEmail, t as makeSessionId, a2 as mintDeviceId, a3 as namespaceExtra, u as reportClientEvent, v as reportClientEventAwait, w as reportClientEvents, x as reportClientEventsAwait, y as resetAutoDeviceKeys, z as resetCurrentSessionId, B as resolveAutoDeviceKey, a4 as resolveUserContext, a5 as sanitizeUserId, F as setCurrentSessionId, G as toAnalyticsEvent } from './currentSession-BlCeDP0f.mjs';
3
+ import { I as WireOnboardingProps, J as WireOnboardingConfig, O as OnboardingResult, S as StepValidator, K as OnboardingEvent, L as OnboardingCopy, c as ClientEventTarget, M as DeviceContext, W as WireUserContext, b as ClientEvent, g as EnvelopeSource } from './currentSession-_GynvhzT.mjs';
4
+ export { A as AUTO_DEVICE_ID_PREFIX, a as AnalyticsEvent, C as ClearUserContextOptions, d as ClientEventType, N as DeviceFormFactor, D as DeviceKeyStorage, P as EXTRA_KEY_PREFIX, Q as IdentifyOnboardingBinding, T as IdentifyOnboardingOptions, U as IdentityRecord, V as IdentitySource, X as IdentitySpace, Y as OnboardingProgress, R as ResolveAutoDeviceKeyOptions, Z as ResolveUserContextOptions, _ as ResolvedUserContext, $ as USER_ID_MAX_LENGTH, i as WIRE_ONBOARDING_EVENTS, j as WireOnboardingEventName, a0 as activationJoinContext, k as analyticsUserIdStorageKey, m as clearPiiFromContext, n as clearUserContext, a1 as collectDeviceContext, p as deviceIdStorageKey, q as ensureCurrentSessionId, r as getCurrentSessionId, a2 as hashEmailFnv1a, a3 as hostIdentity, a4 as hydrateAutoDeviceKey, a5 as hydrateDeviceIdentity, a6 as identifyOnboarding, a7 as isWireScalar, s as looksLikeEmail, t as makeSessionId, a8 as mintDeviceId, a9 as namespaceExtra, u as reportClientEvent, v as reportClientEventAwait, w as reportClientEvents, x as reportClientEventsAwait, y as resetAutoDeviceKeys, z as resetCurrentSessionId, aa as resetIdentityProvenance, F as resolveAutoDeviceKey, ab as resolveIdentity, ac as resolveUserContext, ad as sanitizeUserId, G as setCurrentSessionId, H as toAnalyticsEvent } from './currentSession-_GynvhzT.mjs';
5
5
  import { O as OnboardingTheme } from './types-BKfpdZzX.mjs';
6
6
  export { a as OnboardingButtonStyle, b as OnboardingColors, c as OnboardingFonts, d as OnboardingRadius, e as OnboardingSpacing } from './types-BKfpdZzX.mjs';
7
7
  export { C as CenteredModal, a as CenteredModalHandle, b as CenteredModalProps } from './CenteredModal-C3qQBHsA.mjs';
@@ -231,18 +231,6 @@ type ErrorBlockProps = {
231
231
  };
232
232
  declare const ErrorBlock: React__default.NamedExoticComponent<ErrorBlockProps>;
233
233
 
234
- /**
235
- * DoneBlock — a brief themed "all set" state shown when the flow completes, while
236
- * the host persists results and navigates away. Purely cosmetic; the real
237
- * terminal signal is the SDK's StatusCard (handled in OnboardingFlow).
238
- */
239
-
240
- type DoneBlockProps = {
241
- title?: string;
242
- message?: string;
243
- };
244
- declare const DoneBlock: React__default.NamedExoticComponent<DoneBlockProps>;
245
-
246
234
  /**
247
235
  * CompletionView — the terminal "you're all set" screen, shown when the flow
248
236
  * reaches its final StatusCard. It surfaces the backend's recap (what the app
@@ -1163,6 +1151,8 @@ type PartialProgress = {
1163
1151
  step?: number;
1164
1152
  total?: number;
1165
1153
  key?: string;
1154
+ /** The stable per-slot identity, when the backend sends one. See `OnboardingProgress.slot_id`. */
1155
+ slot_id?: string;
1166
1156
  skippable?: boolean;
1167
1157
  };
1168
1158
  declare const readProgress: (response?: WireAIResponse) => PartialProgress;
@@ -1996,4 +1986,4 @@ interface UseLifecycleEventsOptions {
1996
1986
  */
1997
1987
  declare const useLifecycleEvents: (config: LifecycleConfig | undefined, options?: UseLifecycleEventsOptions) => void;
1998
1988
 
1999
- export { AnimatedSparkle, BACKGROUND_SESSION_MS, type CachedFeatures, CardGridSelectCard, CardHandoff, type CardHandoffProps, type CardHandoffVariant, type CardOption, ChipSelectCard, ClientEvent, ClientEventTarget, CompletionView, DEFAULT_FEATURES_TTL_MS, DemoOnboarding, type DemoOnboardingProps, DeviceContext, DoneBlock, ErrorBlock, FIRST_OPEN_EVENT, IconRegistryProvider, IllustrationProvider, type IllustrationRegistry, InterstitialCard, type LifecycleConfig, type LifecycleEventInput, LoadingBlock, LoadingScreen, NumberStepperCard, type OnboardingAttribution, Button as OnboardingButton, OnboardingCopy, OnboardingEvent, type OnboardingFlagOptions, OnboardingFlow, OnboardingResult, OnboardingScaffold, OnboardingTheme, OnboardingThemeProvider, PLAN_TIER_CONTEXT_KEY, type PlanTier, type PurchaseProps, type ReportFirstOpenOptions, type ReportSessionStartOptions, type ResolveFeaturesOptions, type RevenueCatBridge, type RevenueCatBridgeConfig, type RevenueCatCustomerInfoLike, type RevenueCatEntitlementLike, type RevenueCatErrorLike, type RevenueCatOfferingLike, type RevenueCatPackageLike, type RevenueCatProductLike, type RevenueCatSink, SESSION_STARTED_EVENT, SelectionCard, type SessionStartConfig, StatusCard, StepProgress, StepValidator, TextInputCard, type ThemeFromBrandInput, type UseLifecycleEventsOptions, type UseSessionStartOptions, type UseWireActivation, WIRE_ENV_VARS, WIRE_ICON_GLYPHS, WIRE_ICON_NAMES, WIRE_PURCHASE_EVENTS, type WireActivation, type WireActivationConfig, type WireConfigOverrides, WireFeatures, WireFeaturesConfig, WireFeaturesProvider, type WireFeaturesProviderProps, WireIcon, type WireIconFamily, type WireIconGlyph, type WireIconName, type WireIconProps, type WireIconRegistry, type WireLifecycleOptions, WireOnboarding, WireOnboardingConfig, WireOnboardingProps, WireOnboardingStorage, type WirePurchaseEventName, WireUserContext, activeEntitlement, attributionMetadata, bumpActivationRevalidation, createRevenueCatBridge, createWireActivation, defaultIllustrations, defaultOnboardingTheme, defaultWireFeatures, deriveAnswers, describeEntitlement, describeFailure, describePackage, detectAppVersion, detectNativeModel, featuresCacheKey, featuresEqual, fetchWireFeatures, firstOpenStorageKey, getActivationRevalidationVersion, isFeaturesFresh, isOnboardingEnabled, isUserCancelled, lookupIconGlyph, mergeTheme, motionSpec, onboardingComponents, parseWireFeatures, readCachedFeatures, readProgress, reportFirstOpen, reportSessionStart, resetActivationRevalidation, resetFirstOpenLatch, resetSessionStartGuard, resolvePlanTier, subscribeActivationRevalidation, themeFromBrand, useActivationRevalidation, useHostIcon, useIllustration, useLifecycleEvents, useOnboardingTheme, useReducedMotion, useResolvedFeatures, useSessionStart, useWireActivation, useWireFeatures, useWireFeaturesContext, wireConfigFromEnv, wireLifecycleEvents, writeCachedFeatures };
1989
+ export { AnimatedSparkle, BACKGROUND_SESSION_MS, type CachedFeatures, CardGridSelectCard, CardHandoff, type CardHandoffProps, type CardHandoffVariant, type CardOption, ChipSelectCard, ClientEvent, ClientEventTarget, CompletionView, DEFAULT_FEATURES_TTL_MS, DemoOnboarding, type DemoOnboardingProps, DeviceContext, ErrorBlock, FIRST_OPEN_EVENT, IconRegistryProvider, IllustrationProvider, type IllustrationRegistry, InterstitialCard, type LifecycleConfig, type LifecycleEventInput, LoadingBlock, LoadingScreen, NumberStepperCard, type OnboardingAttribution, Button as OnboardingButton, OnboardingCopy, OnboardingEvent, type OnboardingFlagOptions, OnboardingFlow, OnboardingResult, OnboardingScaffold, OnboardingTheme, OnboardingThemeProvider, PLAN_TIER_CONTEXT_KEY, type PlanTier, type PurchaseProps, type ReportFirstOpenOptions, type ReportSessionStartOptions, type ResolveFeaturesOptions, type RevenueCatBridge, type RevenueCatBridgeConfig, type RevenueCatCustomerInfoLike, type RevenueCatEntitlementLike, type RevenueCatErrorLike, type RevenueCatOfferingLike, type RevenueCatPackageLike, type RevenueCatProductLike, type RevenueCatSink, SESSION_STARTED_EVENT, SelectionCard, type SessionStartConfig, StatusCard, StepProgress, StepValidator, TextInputCard, type ThemeFromBrandInput, type UseLifecycleEventsOptions, type UseSessionStartOptions, type UseWireActivation, WIRE_ENV_VARS, WIRE_ICON_GLYPHS, WIRE_ICON_NAMES, WIRE_PURCHASE_EVENTS, type WireActivation, type WireActivationConfig, type WireConfigOverrides, WireFeatures, WireFeaturesConfig, WireFeaturesProvider, type WireFeaturesProviderProps, WireIcon, type WireIconFamily, type WireIconGlyph, type WireIconName, type WireIconProps, type WireIconRegistry, type WireLifecycleOptions, WireOnboarding, WireOnboardingConfig, WireOnboardingProps, WireOnboardingStorage, type WirePurchaseEventName, WireUserContext, activeEntitlement, attributionMetadata, bumpActivationRevalidation, createRevenueCatBridge, createWireActivation, defaultIllustrations, defaultOnboardingTheme, defaultWireFeatures, deriveAnswers, describeEntitlement, describeFailure, describePackage, detectAppVersion, detectNativeModel, featuresCacheKey, featuresEqual, fetchWireFeatures, firstOpenStorageKey, getActivationRevalidationVersion, isFeaturesFresh, isOnboardingEnabled, isUserCancelled, lookupIconGlyph, mergeTheme, motionSpec, onboardingComponents, parseWireFeatures, readCachedFeatures, readProgress, reportFirstOpen, reportSessionStart, resetActivationRevalidation, resetFirstOpenLatch, resetSessionStartGuard, resolvePlanTier, subscribeActivationRevalidation, themeFromBrand, useActivationRevalidation, useHostIcon, useIllustration, useLifecycleEvents, useOnboardingTheme, useReducedMotion, useResolvedFeatures, useSessionStart, useWireActivation, useWireFeatures, useWireFeaturesContext, wireConfigFromEnv, wireLifecycleEvents, writeCachedFeatures };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import React__default, { ReactNode } from 'react';
3
- import { H as WireOnboardingProps, I as WireOnboardingConfig, O as OnboardingResult, S as StepValidator, J as OnboardingEvent, K as OnboardingCopy, c as ClientEventTarget, L as DeviceContext, W as WireUserContext, b as ClientEvent, g as EnvelopeSource } from './currentSession-BxEB37xt.js';
4
- export { A as AUTO_DEVICE_ID_PREFIX, a as AnalyticsEvent, C as ClearUserContextOptions, d as ClientEventType, M as DeviceFormFactor, D as DeviceKeyStorage, N as EXTRA_KEY_PREFIX, P as IdentifyOnboardingOptions, Q as OnboardingProgress, T as RESERVED_USER_CONTEXT_KEYS, R as ResolveAutoDeviceKeyOptions, U as ResolveUserContextOptions, V as ResolvedUserContext, X as USER_ID_MAX_LENGTH, i as WIRE_ONBOARDING_EVENTS, j as WireOnboardingEventName, Y as activationJoinContext, k as analyticsUserIdStorageKey, m as clearPiiFromContext, n as clearUserContext, Z as collectDeviceContext, p as deviceIdStorageKey, q as ensureCurrentSessionId, r as getCurrentSessionId, _ as hashEmailFnv1a, $ as hydrateAutoDeviceKey, a0 as identifyOnboarding, a1 as isWireScalar, s as looksLikeEmail, t as makeSessionId, a2 as mintDeviceId, a3 as namespaceExtra, u as reportClientEvent, v as reportClientEventAwait, w as reportClientEvents, x as reportClientEventsAwait, y as resetAutoDeviceKeys, z as resetCurrentSessionId, B as resolveAutoDeviceKey, a4 as resolveUserContext, a5 as sanitizeUserId, F as setCurrentSessionId, G as toAnalyticsEvent } from './currentSession-BxEB37xt.js';
3
+ import { I as WireOnboardingProps, J as WireOnboardingConfig, O as OnboardingResult, S as StepValidator, K as OnboardingEvent, L as OnboardingCopy, c as ClientEventTarget, M as DeviceContext, W as WireUserContext, b as ClientEvent, g as EnvelopeSource } from './currentSession-D7zabMXK.js';
4
+ export { A as AUTO_DEVICE_ID_PREFIX, a as AnalyticsEvent, C as ClearUserContextOptions, d as ClientEventType, N as DeviceFormFactor, D as DeviceKeyStorage, P as EXTRA_KEY_PREFIX, Q as IdentifyOnboardingBinding, T as IdentifyOnboardingOptions, U as IdentityRecord, V as IdentitySource, X as IdentitySpace, Y as OnboardingProgress, R as ResolveAutoDeviceKeyOptions, Z as ResolveUserContextOptions, _ as ResolvedUserContext, $ as USER_ID_MAX_LENGTH, i as WIRE_ONBOARDING_EVENTS, j as WireOnboardingEventName, a0 as activationJoinContext, k as analyticsUserIdStorageKey, m as clearPiiFromContext, n as clearUserContext, a1 as collectDeviceContext, p as deviceIdStorageKey, q as ensureCurrentSessionId, r as getCurrentSessionId, a2 as hashEmailFnv1a, a3 as hostIdentity, a4 as hydrateAutoDeviceKey, a5 as hydrateDeviceIdentity, a6 as identifyOnboarding, a7 as isWireScalar, s as looksLikeEmail, t as makeSessionId, a8 as mintDeviceId, a9 as namespaceExtra, u as reportClientEvent, v as reportClientEventAwait, w as reportClientEvents, x as reportClientEventsAwait, y as resetAutoDeviceKeys, z as resetCurrentSessionId, aa as resetIdentityProvenance, F as resolveAutoDeviceKey, ab as resolveIdentity, ac as resolveUserContext, ad as sanitizeUserId, G as setCurrentSessionId, H as toAnalyticsEvent } from './currentSession-D7zabMXK.js';
5
5
  import { O as OnboardingTheme } from './types-BKfpdZzX.js';
6
6
  export { a as OnboardingButtonStyle, b as OnboardingColors, c as OnboardingFonts, d as OnboardingRadius, e as OnboardingSpacing } from './types-BKfpdZzX.js';
7
7
  export { C as CenteredModal, a as CenteredModalHandle, b as CenteredModalProps } from './CenteredModal-Cdgns6--.js';
@@ -231,18 +231,6 @@ type ErrorBlockProps = {
231
231
  };
232
232
  declare const ErrorBlock: React__default.NamedExoticComponent<ErrorBlockProps>;
233
233
 
234
- /**
235
- * DoneBlock — a brief themed "all set" state shown when the flow completes, while
236
- * the host persists results and navigates away. Purely cosmetic; the real
237
- * terminal signal is the SDK's StatusCard (handled in OnboardingFlow).
238
- */
239
-
240
- type DoneBlockProps = {
241
- title?: string;
242
- message?: string;
243
- };
244
- declare const DoneBlock: React__default.NamedExoticComponent<DoneBlockProps>;
245
-
246
234
  /**
247
235
  * CompletionView — the terminal "you're all set" screen, shown when the flow
248
236
  * reaches its final StatusCard. It surfaces the backend's recap (what the app
@@ -1163,6 +1151,8 @@ type PartialProgress = {
1163
1151
  step?: number;
1164
1152
  total?: number;
1165
1153
  key?: string;
1154
+ /** The stable per-slot identity, when the backend sends one. See `OnboardingProgress.slot_id`. */
1155
+ slot_id?: string;
1166
1156
  skippable?: boolean;
1167
1157
  };
1168
1158
  declare const readProgress: (response?: WireAIResponse) => PartialProgress;
@@ -1996,4 +1986,4 @@ interface UseLifecycleEventsOptions {
1996
1986
  */
1997
1987
  declare const useLifecycleEvents: (config: LifecycleConfig | undefined, options?: UseLifecycleEventsOptions) => void;
1998
1988
 
1999
- export { AnimatedSparkle, BACKGROUND_SESSION_MS, type CachedFeatures, CardGridSelectCard, CardHandoff, type CardHandoffProps, type CardHandoffVariant, type CardOption, ChipSelectCard, ClientEvent, ClientEventTarget, CompletionView, DEFAULT_FEATURES_TTL_MS, DemoOnboarding, type DemoOnboardingProps, DeviceContext, DoneBlock, ErrorBlock, FIRST_OPEN_EVENT, IconRegistryProvider, IllustrationProvider, type IllustrationRegistry, InterstitialCard, type LifecycleConfig, type LifecycleEventInput, LoadingBlock, LoadingScreen, NumberStepperCard, type OnboardingAttribution, Button as OnboardingButton, OnboardingCopy, OnboardingEvent, type OnboardingFlagOptions, OnboardingFlow, OnboardingResult, OnboardingScaffold, OnboardingTheme, OnboardingThemeProvider, PLAN_TIER_CONTEXT_KEY, type PlanTier, type PurchaseProps, type ReportFirstOpenOptions, type ReportSessionStartOptions, type ResolveFeaturesOptions, type RevenueCatBridge, type RevenueCatBridgeConfig, type RevenueCatCustomerInfoLike, type RevenueCatEntitlementLike, type RevenueCatErrorLike, type RevenueCatOfferingLike, type RevenueCatPackageLike, type RevenueCatProductLike, type RevenueCatSink, SESSION_STARTED_EVENT, SelectionCard, type SessionStartConfig, StatusCard, StepProgress, StepValidator, TextInputCard, type ThemeFromBrandInput, type UseLifecycleEventsOptions, type UseSessionStartOptions, type UseWireActivation, WIRE_ENV_VARS, WIRE_ICON_GLYPHS, WIRE_ICON_NAMES, WIRE_PURCHASE_EVENTS, type WireActivation, type WireActivationConfig, type WireConfigOverrides, WireFeatures, WireFeaturesConfig, WireFeaturesProvider, type WireFeaturesProviderProps, WireIcon, type WireIconFamily, type WireIconGlyph, type WireIconName, type WireIconProps, type WireIconRegistry, type WireLifecycleOptions, WireOnboarding, WireOnboardingConfig, WireOnboardingProps, WireOnboardingStorage, type WirePurchaseEventName, WireUserContext, activeEntitlement, attributionMetadata, bumpActivationRevalidation, createRevenueCatBridge, createWireActivation, defaultIllustrations, defaultOnboardingTheme, defaultWireFeatures, deriveAnswers, describeEntitlement, describeFailure, describePackage, detectAppVersion, detectNativeModel, featuresCacheKey, featuresEqual, fetchWireFeatures, firstOpenStorageKey, getActivationRevalidationVersion, isFeaturesFresh, isOnboardingEnabled, isUserCancelled, lookupIconGlyph, mergeTheme, motionSpec, onboardingComponents, parseWireFeatures, readCachedFeatures, readProgress, reportFirstOpen, reportSessionStart, resetActivationRevalidation, resetFirstOpenLatch, resetSessionStartGuard, resolvePlanTier, subscribeActivationRevalidation, themeFromBrand, useActivationRevalidation, useHostIcon, useIllustration, useLifecycleEvents, useOnboardingTheme, useReducedMotion, useResolvedFeatures, useSessionStart, useWireActivation, useWireFeatures, useWireFeaturesContext, wireConfigFromEnv, wireLifecycleEvents, writeCachedFeatures };
1989
+ export { AnimatedSparkle, BACKGROUND_SESSION_MS, type CachedFeatures, CardGridSelectCard, CardHandoff, type CardHandoffProps, type CardHandoffVariant, type CardOption, ChipSelectCard, ClientEvent, ClientEventTarget, CompletionView, DEFAULT_FEATURES_TTL_MS, DemoOnboarding, type DemoOnboardingProps, DeviceContext, ErrorBlock, FIRST_OPEN_EVENT, IconRegistryProvider, IllustrationProvider, type IllustrationRegistry, InterstitialCard, type LifecycleConfig, type LifecycleEventInput, LoadingBlock, LoadingScreen, NumberStepperCard, type OnboardingAttribution, Button as OnboardingButton, OnboardingCopy, OnboardingEvent, type OnboardingFlagOptions, OnboardingFlow, OnboardingResult, OnboardingScaffold, OnboardingTheme, OnboardingThemeProvider, PLAN_TIER_CONTEXT_KEY, type PlanTier, type PurchaseProps, type ReportFirstOpenOptions, type ReportSessionStartOptions, type ResolveFeaturesOptions, type RevenueCatBridge, type RevenueCatBridgeConfig, type RevenueCatCustomerInfoLike, type RevenueCatEntitlementLike, type RevenueCatErrorLike, type RevenueCatOfferingLike, type RevenueCatPackageLike, type RevenueCatProductLike, type RevenueCatSink, SESSION_STARTED_EVENT, SelectionCard, type SessionStartConfig, StatusCard, StepProgress, StepValidator, TextInputCard, type ThemeFromBrandInput, type UseLifecycleEventsOptions, type UseSessionStartOptions, type UseWireActivation, WIRE_ENV_VARS, WIRE_ICON_GLYPHS, WIRE_ICON_NAMES, WIRE_PURCHASE_EVENTS, type WireActivation, type WireActivationConfig, type WireConfigOverrides, WireFeatures, WireFeaturesConfig, WireFeaturesProvider, type WireFeaturesProviderProps, WireIcon, type WireIconFamily, type WireIconGlyph, type WireIconName, type WireIconProps, type WireIconRegistry, type WireLifecycleOptions, WireOnboarding, WireOnboardingConfig, WireOnboardingProps, WireOnboardingStorage, type WirePurchaseEventName, WireUserContext, activeEntitlement, attributionMetadata, bumpActivationRevalidation, createRevenueCatBridge, createWireActivation, defaultIllustrations, defaultOnboardingTheme, defaultWireFeatures, deriveAnswers, describeEntitlement, describeFailure, describePackage, detectAppVersion, detectNativeModel, featuresCacheKey, featuresEqual, fetchWireFeatures, firstOpenStorageKey, getActivationRevalidationVersion, isFeaturesFresh, isOnboardingEnabled, isUserCancelled, lookupIconGlyph, mergeTheme, motionSpec, onboardingComponents, parseWireFeatures, readCachedFeatures, readProgress, reportFirstOpen, reportSessionStart, resetActivationRevalidation, resetFirstOpenLatch, resetSessionStartGuard, resolvePlanTier, subscribeActivationRevalidation, themeFromBrand, useActivationRevalidation, useHostIcon, useIllustration, useLifecycleEvents, useOnboardingTheme, useReducedMotion, useResolvedFeatures, useSessionStart, useWireActivation, useWireFeatures, useWireFeaturesContext, wireConfigFromEnv, wireLifecycleEvents, writeCachedFeatures };