@wireai/activation 0.13.6 → 0.14.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 (41) hide show
  1. package/AGENTS.md +21 -9
  2. package/CHANGELOG.md +172 -1
  3. package/INTEGRATION_PROMPT.md +7 -4
  4. package/README.md +10 -2
  5. package/dist/analytics/index.d.mts +9 -2
  6. package/dist/analytics/index.d.ts +9 -2
  7. package/dist/analytics/index.js +56 -12
  8. package/dist/analytics/index.js.map +1 -1
  9. package/dist/analytics/index.mjs +56 -12
  10. package/dist/analytics/index.mjs.map +1 -1
  11. package/dist/{currentSession-DngW-QoD.d.mts → currentSession-CUvTOchb.d.mts} +35 -6
  12. package/dist/{currentSession-C5976akx.d.ts → currentSession-CW_5Mq4O.d.ts} +35 -6
  13. package/dist/index.d.mts +24 -6
  14. package/dist/index.d.ts +24 -6
  15. package/dist/index.js +631 -548
  16. package/dist/index.js.map +1 -1
  17. package/dist/index.mjs +631 -548
  18. package/dist/index.mjs.map +1 -1
  19. package/dist/questionnaire/index.js.map +1 -1
  20. package/dist/questionnaire/index.mjs.map +1 -1
  21. package/dist/reviews/index.js.map +1 -1
  22. package/dist/reviews/index.mjs.map +1 -1
  23. package/llms.txt +2 -2
  24. package/package.json +1 -1
  25. package/src/OnboardingFlow.tsx +4 -3
  26. package/src/WireOnboarding.tsx +4 -3
  27. package/src/activation/useWireActivation.ts +14 -1
  28. package/src/activation/wireActivation.ts +68 -2
  29. package/src/analytics/analyticsFacade.ts +24 -0
  30. package/src/analytics/eventQueue.ts +106 -11
  31. package/src/analytics/reportClientEvent.ts +31 -7
  32. package/src/analytics/useAnalytics.ts +17 -0
  33. package/src/context/deviceId.ts +10 -3
  34. package/src/permissions/permissionMemory.ts +12 -1
  35. package/src/session/persistedSession.ts +32 -8
  36. package/src/session-analytics/lifecycle.ts +26 -5
  37. package/src/session-analytics/reportSessionStart.ts +14 -10
  38. package/src/session-analytics/useLifecycleEvents.ts +70 -32
  39. package/src/session-analytics/useSessionStart.ts +57 -15
  40. package/src/types.ts +16 -6
  41. package/src/utils/readPlan.ts +8 -5
@@ -472,10 +472,11 @@ type OnboardingResult = {
472
472
  /** The raw message thread, for custom downstream parsing. */
473
473
  raw: Message[];
474
474
  /**
475
- * The backend's onboarding plan, when it sent one. Present ONLY on the AI path: a tenant running
476
- * the static flow, or any run the server finished without a plan, leaves this `undefined` AND
477
- * leaves the key off the result object entirely so a host written before plans existed sees
478
- * byte-identically what it always saw.
475
+ * The backend's onboarding plan, present when the backend sent one the kit never infers it
476
+ * from which flow ran. Whether a plan arrives is the backend's configuration, not the kit's. Any
477
+ * run the server finished without a plan leaves this `undefined` AND leaves the key off the
478
+ * result object entirely — so a host written before plans existed sees byte-identically what it
479
+ * always saw.
479
480
  *
480
481
  * ⚠️ The kit does NOT interpret this and does NOT validate it. It checks one structural fact (a
481
482
  * plan is an object) and hands the payload straight through, unread, unlogged, and never attached
@@ -669,10 +670,19 @@ type WireOnboardingProps = {
669
670
  *
670
671
  * ```tsx
671
672
  * <WireOnboarding userContext={activationJoinContext(deviceKey)} ... />
672
- * // no device id of your own? read the kit's:
673
- * <WireOnboarding userContext={activationJoinContext(resolveAutoDeviceKey({ appId, storage }))} ... />
673
+ * // no device id of your own? pass `storage` and leave this prop alone — the kit injects its
674
+ * // own key, and only after it has confirmed the key actually persists (see `autoJoinKey`).
675
+ * <WireOnboarding config={{ ...config, storage }} ... />
674
676
  * ```
675
677
  *
678
+ * ⛔ Do NOT hand-build the auto key with `activationJoinContext(resolveAutoDeviceKey({...}))`.
679
+ * `resolveAutoDeviceKey` is SYNCHRONOUS by contract: it hands back a freshly minted id and adopts
680
+ * the persisted one a storage read later, and it cannot tell you whether the id survives the
681
+ * launch at all. A key that differs on every launch corrupts `min_sessions` rather than merely
682
+ * leaving the join empty. The auto-join path does the awaited, durability-checked read for you;
683
+ * a host that genuinely wants the value in hand should await `hydrateDeviceIdentity` and refuse a
684
+ * `durable: false` record, which is exactly what the kit does internally.
685
+ *
676
686
  * SINCE 0.12.2, leaving it out no longer silently empties the funnel: when you pass `storage` and
677
687
  * this prop carries no `device_key`, the kit injects its OWN per-install key — the same one the
678
688
  * analytics surfaces mint and persist — so the default wiring joins. Anything you DO pass wins
@@ -984,6 +994,19 @@ type EventQueue = {
984
994
  notifyOnline(): void;
985
995
  /** Current pending (in-memory) count. */
986
996
  size(): number;
997
+ /**
998
+ * Tear this queue down when its owner goes away (a hook's effect cleanup, a host disposing its
999
+ * own instance). Idempotent, never throws, and REQUIRED for any queue that can be re-created:
1000
+ * a remount builds a second queue while the first is still holding the storage claim and a live
1001
+ * backoff timer, and the two then fight over one persisted slot.
1002
+ *
1003
+ * It clears the retry timer, releases the claimed storage key so a replacement gets the SAME slot
1004
+ * instead of a rotated `…#2` nobody reads next launch, and makes the queue inert — `enqueue`,
1005
+ * `flush` and every write become no-ops, so a timer that already fired cannot `removeItem` the
1006
+ * slot the live queue owns. Anything still buffered in memory at that point stays on disk under
1007
+ * the released key, which is exactly where the replacement queue looks for it.
1008
+ */
1009
+ dispose(): void;
987
1010
  };
988
1011
  /** Test-only: forget every claimed queue key. A real RELAUNCH is a new process, so a test that
989
1012
  * simulates one in-process must call this or its second queue reads as a concurrent sibling.
@@ -1375,6 +1398,12 @@ declare const resolveAutoDeviceKey: (opts?: ResolveAutoDeviceKeyOptions) => stri
1375
1398
  *
1376
1399
  * Never throws or rejects: a missing, hung, or rejecting adapter resolves to the in-memory id, and
1377
1400
  * with no `storage` it resolves immediately (there is nothing to hydrate from).
1401
+ *
1402
+ * ⚠️ IT RETURNS A BARE STRING, so it CANNOT say whether the id survives the launch — a degraded
1403
+ * adapter resolves to the in-memory mint and reads identically to a persisted one. No kit surface
1404
+ * uses it any more (0.14.0 moved the two lifecycle hooks off it): a caller writing a cross-launch
1405
+ * join key wants {@link hydrateDeviceIdentity} and its `durable` flag. Kept as public API for a host
1406
+ * that only wants "the id", never as the way to decide whether to stamp one.
1378
1407
  */
1379
1408
  declare const hydrateAutoDeviceKey: (opts?: ResolveAutoDeviceKeyOptions) => Promise<string>;
1380
1409
  /**
@@ -472,10 +472,11 @@ type OnboardingResult = {
472
472
  /** The raw message thread, for custom downstream parsing. */
473
473
  raw: Message[];
474
474
  /**
475
- * The backend's onboarding plan, when it sent one. Present ONLY on the AI path: a tenant running
476
- * the static flow, or any run the server finished without a plan, leaves this `undefined` AND
477
- * leaves the key off the result object entirely so a host written before plans existed sees
478
- * byte-identically what it always saw.
475
+ * The backend's onboarding plan, present when the backend sent one the kit never infers it
476
+ * from which flow ran. Whether a plan arrives is the backend's configuration, not the kit's. Any
477
+ * run the server finished without a plan leaves this `undefined` AND leaves the key off the
478
+ * result object entirely — so a host written before plans existed sees byte-identically what it
479
+ * always saw.
479
480
  *
480
481
  * ⚠️ The kit does NOT interpret this and does NOT validate it. It checks one structural fact (a
481
482
  * plan is an object) and hands the payload straight through, unread, unlogged, and never attached
@@ -669,10 +670,19 @@ type WireOnboardingProps = {
669
670
  *
670
671
  * ```tsx
671
672
  * <WireOnboarding userContext={activationJoinContext(deviceKey)} ... />
672
- * // no device id of your own? read the kit's:
673
- * <WireOnboarding userContext={activationJoinContext(resolveAutoDeviceKey({ appId, storage }))} ... />
673
+ * // no device id of your own? pass `storage` and leave this prop alone — the kit injects its
674
+ * // own key, and only after it has confirmed the key actually persists (see `autoJoinKey`).
675
+ * <WireOnboarding config={{ ...config, storage }} ... />
674
676
  * ```
675
677
  *
678
+ * ⛔ Do NOT hand-build the auto key with `activationJoinContext(resolveAutoDeviceKey({...}))`.
679
+ * `resolveAutoDeviceKey` is SYNCHRONOUS by contract: it hands back a freshly minted id and adopts
680
+ * the persisted one a storage read later, and it cannot tell you whether the id survives the
681
+ * launch at all. A key that differs on every launch corrupts `min_sessions` rather than merely
682
+ * leaving the join empty. The auto-join path does the awaited, durability-checked read for you;
683
+ * a host that genuinely wants the value in hand should await `hydrateDeviceIdentity` and refuse a
684
+ * `durable: false` record, which is exactly what the kit does internally.
685
+ *
676
686
  * SINCE 0.12.2, leaving it out no longer silently empties the funnel: when you pass `storage` and
677
687
  * this prop carries no `device_key`, the kit injects its OWN per-install key — the same one the
678
688
  * analytics surfaces mint and persist — so the default wiring joins. Anything you DO pass wins
@@ -984,6 +994,19 @@ type EventQueue = {
984
994
  notifyOnline(): void;
985
995
  /** Current pending (in-memory) count. */
986
996
  size(): number;
997
+ /**
998
+ * Tear this queue down when its owner goes away (a hook's effect cleanup, a host disposing its
999
+ * own instance). Idempotent, never throws, and REQUIRED for any queue that can be re-created:
1000
+ * a remount builds a second queue while the first is still holding the storage claim and a live
1001
+ * backoff timer, and the two then fight over one persisted slot.
1002
+ *
1003
+ * It clears the retry timer, releases the claimed storage key so a replacement gets the SAME slot
1004
+ * instead of a rotated `…#2` nobody reads next launch, and makes the queue inert — `enqueue`,
1005
+ * `flush` and every write become no-ops, so a timer that already fired cannot `removeItem` the
1006
+ * slot the live queue owns. Anything still buffered in memory at that point stays on disk under
1007
+ * the released key, which is exactly where the replacement queue looks for it.
1008
+ */
1009
+ dispose(): void;
987
1010
  };
988
1011
  /** Test-only: forget every claimed queue key. A real RELAUNCH is a new process, so a test that
989
1012
  * simulates one in-process must call this or its second queue reads as a concurrent sibling.
@@ -1375,6 +1398,12 @@ declare const resolveAutoDeviceKey: (opts?: ResolveAutoDeviceKeyOptions) => stri
1375
1398
  *
1376
1399
  * Never throws or rejects: a missing, hung, or rejecting adapter resolves to the in-memory id, and
1377
1400
  * with no `storage` it resolves immediately (there is nothing to hydrate from).
1401
+ *
1402
+ * ⚠️ IT RETURNS A BARE STRING, so it CANNOT say whether the id survives the launch — a degraded
1403
+ * adapter resolves to the in-memory mint and reads identically to a persisted one. No kit surface
1404
+ * uses it any more (0.14.0 moved the two lifecycle hooks off it): a caller writing a cross-launch
1405
+ * join key wants {@link hydrateDeviceIdentity} and its `durable` flag. Kept as public API for a host
1406
+ * that only wants "the id", never as the way to decide whether to stamp one.
1378
1407
  */
1379
1408
  declare const hydrateAutoDeviceKey: (opts?: ResolveAutoDeviceKeyOptions) => Promise<string>;
1380
1409
  /**
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 { I as WireOnboardingProps, J as WireOnboardingConfig, O as OnboardingResult, K as WirePermissionStatus, P as PermissionStage, L as WirePermissionOutcome, S as StepValidator, M as OnboardingEvent, N as OnboardingCopy, C as ClientEventTarget, Q as DeviceContext, T as PermissionScreenConfig, W as WireUserContext, U as PermissionPlacement, c as ClientEvent, g as EnvelopeSource } from './currentSession-DngW-QoD.mjs';
4
- export { A as AUTO_DEVICE_ID_PREFIX, a as AnalyticsEvent, b as ClearUserContextOptions, d as ClientEventType, V as DEFAULT_PERMISSION_COPY, X as DeviceFormFactor, D as DeviceKeyStorage, Y as EXTRA_KEY_PREFIX, Z as GENERIC_PERMISSION_COPY, _ as IdentifyOnboardingBinding, $ as IdentifyOnboardingOptions, a0 as IdentityRecord, a1 as IdentitySource, a2 as IdentitySpace, a3 as NOTIFICATIONS_PERMISSION_COPY, a4 as OnboardingProgress, a5 as PermissionScreenCopy, R as ResolveAutoDeviceKeyOptions, a6 as ResolveUserContextOptions, a7 as ResolvedUserContext, a8 as USER_ID_MAX_LENGTH, i as WIRE_ONBOARDING_EVENTS, a9 as WIRE_PERMISSION_EVENTS, j as WireOnboardingEventName, aa as WirePermissionEventName, ab as WirePermissionKind, ac as activationJoinContext, k as analyticsUserIdStorageKey, m as clearPiiFromContext, n as clearUserContext, ad as collectDeviceContext, p as deviceIdStorageKey, q as ensureCurrentSessionId, r as getCurrentSessionId, ae as hashEmailFnv1a, af as hostIdentity, ag as hydrateAutoDeviceKey, ah as hydrateDeviceIdentity, ai as identifyOnboarding, aj as isWireScalar, s as looksLikeEmail, t as makeSessionId, ak as mintDeviceId, al as namespaceExtra, am as normalizePermissionStatus, an as permissionEventName, ao as permissionEventProps, u as reportClientEvent, v as reportClientEventAwait, w as reportClientEvents, x as reportClientEventsAwait, y as resetAutoDeviceKeys, z as resetCurrentSessionId, ap as resetIdentityProvenance, F as resolveAutoDeviceKey, aq as resolveIdentity, ar as resolvePermissionCopy, as as resolveUserContext, at as sanitizeUserId, G as setCurrentSessionId, H as toAnalyticsEvent } from './currentSession-DngW-QoD.mjs';
3
+ import { I as WireOnboardingProps, J as WireOnboardingConfig, O as OnboardingResult, K as WirePermissionStatus, P as PermissionStage, L as WirePermissionOutcome, S as StepValidator, M as OnboardingEvent, N as OnboardingCopy, C as ClientEventTarget, Q as DeviceContext, T as PermissionScreenConfig, W as WireUserContext, c as ClientEvent, U as PermissionPlacement, g as EnvelopeSource } from './currentSession-CUvTOchb.mjs';
4
+ export { A as AUTO_DEVICE_ID_PREFIX, a as AnalyticsEvent, b as ClearUserContextOptions, d as ClientEventType, V as DEFAULT_PERMISSION_COPY, X as DeviceFormFactor, D as DeviceKeyStorage, Y as EXTRA_KEY_PREFIX, Z as GENERIC_PERMISSION_COPY, _ as IdentifyOnboardingBinding, $ as IdentifyOnboardingOptions, a0 as IdentityRecord, a1 as IdentitySource, a2 as IdentitySpace, a3 as NOTIFICATIONS_PERMISSION_COPY, a4 as OnboardingProgress, a5 as PermissionScreenCopy, R as ResolveAutoDeviceKeyOptions, a6 as ResolveUserContextOptions, a7 as ResolvedUserContext, a8 as USER_ID_MAX_LENGTH, i as WIRE_ONBOARDING_EVENTS, a9 as WIRE_PERMISSION_EVENTS, j as WireOnboardingEventName, aa as WirePermissionEventName, ab as WirePermissionKind, ac as activationJoinContext, k as analyticsUserIdStorageKey, m as clearPiiFromContext, n as clearUserContext, ad as collectDeviceContext, p as deviceIdStorageKey, q as ensureCurrentSessionId, r as getCurrentSessionId, ae as hashEmailFnv1a, af as hostIdentity, ag as hydrateAutoDeviceKey, ah as hydrateDeviceIdentity, ai as identifyOnboarding, aj as isWireScalar, s as looksLikeEmail, t as makeSessionId, ak as mintDeviceId, al as namespaceExtra, am as normalizePermissionStatus, an as permissionEventName, ao as permissionEventProps, u as reportClientEvent, v as reportClientEventAwait, w as reportClientEvents, x as reportClientEventsAwait, y as resetAutoDeviceKeys, z as resetCurrentSessionId, ap as resetIdentityProvenance, F as resolveAutoDeviceKey, aq as resolveIdentity, ar as resolvePermissionCopy, as as resolveUserContext, at as sanitizeUserId, G as setCurrentSessionId, H as toAnalyticsEvent } from './currentSession-CUvTOchb.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';
@@ -1572,6 +1572,15 @@ type WireActivationConfig = {
1572
1572
  appVersion?: string;
1573
1573
  /** Host persistence (AsyncStorage-compatible subset) so the auto-minted device key survives launches. */
1574
1574
  storage?: WireOnboardingStorage;
1575
+ /**
1576
+ * Where a FAILED `track()` goes instead of being dropped: your existing offline queue's `enqueue`
1577
+ * (the same wiring `useLifecycleEvents` takes). Pass it when you already run one queue for the app
1578
+ * and you want one backlog, one retry schedule, one storage slot.
1579
+ *
1580
+ * Omit it and the instance opens its OWN queue the first time a POST fails — never before, so an
1581
+ * app that is online the whole time allocates nothing. A successful `track()` never touches either.
1582
+ */
1583
+ sink?: (event: ClientEvent) => void;
1575
1584
  };
1576
1585
  /** The kit-owned activation surface. `sessionId` is a live getter (reads `getCurrentSessionId()`). */
1577
1586
  type WireActivation = {
@@ -1594,6 +1603,12 @@ type WireActivation = {
1594
1603
  subscribeRevalidation(listener: () => void): () => void;
1595
1604
  /** The current revalidation version — include in a decision-fetch effect's deps to re-fetch on bump. */
1596
1605
  getRevalidationVersion(): number;
1606
+ /**
1607
+ * Tear down the durability queue a failed `track()` may have opened (see
1608
+ * {@link EventQueue.dispose}). Idempotent, never throws, and a no-op on an instance that never had
1609
+ * a failure. Call it when you build an instance per mount; `useWireActivation` does it for you.
1610
+ */
1611
+ dispose(): void;
1597
1612
  };
1598
1613
  /**
1599
1614
  * Create a bound activation instance for a tenant transport. Resolves the device key once (explicit >
@@ -2033,8 +2048,9 @@ interface SessionStartConfig {
2033
2048
  appVersion?: string;
2034
2049
  /** Tenant/app id — namespaces the auto `device_key` fallback below. */
2035
2050
  appId?: string;
2036
- /** Host storage (AsyncStorage subset). Present → `app.session_started` falls back to the kit's
2037
- * persisted auto `device_key` when the host passes none. Absent no fallback (see below). */
2051
+ /** Host storage (AsyncStorage subset). Present AND actually persisting → `app.session_started`
2052
+ * falls back to the kit's persisted auto `device_key` when the host passes none. Absent, or an
2053
+ * adapter that throws / rejects → no fallback (a per-launch key is worse than none, see below). */
2038
2054
  storage?: WireOnboardingStorage;
2039
2055
  }
2040
2056
  /** Per-open identity the host supplies. All optional: a pre-auth open is device-only. */
@@ -2167,8 +2183,10 @@ interface LifecycleConfig {
2167
2183
  appVersion?: string;
2168
2184
  /** Tenant/app id — namespaces the first-open flag AND the hook's internal queue storage key. */
2169
2185
  appId?: string;
2170
- /** Host storage (AsyncStorage subset). Enables the persisted once-ever first-open flag AND the
2171
- * offline durability of the hook's internal queue. Omit it and both degrade to in-memory. */
2186
+ /** Host storage (AsyncStorage subset). Enables the persisted once-ever first-open flag, the
2187
+ * offline durability of the hook's internal queue, AND the auto `device_key` fallback the last
2188
+ * one only when the adapter actually persists (one that throws or rejects gets no fallback, the
2189
+ * same verdict as no storage at all). Omit it and all three degrade to in-memory. */
2172
2190
  storage?: WireOnboardingStorage;
2173
2191
  }
2174
2192
  /** Per-open identity + wiring the host supplies. All optional: a pre-auth open is device-only. */
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 { I as WireOnboardingProps, J as WireOnboardingConfig, O as OnboardingResult, K as WirePermissionStatus, P as PermissionStage, L as WirePermissionOutcome, S as StepValidator, M as OnboardingEvent, N as OnboardingCopy, C as ClientEventTarget, Q as DeviceContext, T as PermissionScreenConfig, W as WireUserContext, U as PermissionPlacement, c as ClientEvent, g as EnvelopeSource } from './currentSession-C5976akx.js';
4
- export { A as AUTO_DEVICE_ID_PREFIX, a as AnalyticsEvent, b as ClearUserContextOptions, d as ClientEventType, V as DEFAULT_PERMISSION_COPY, X as DeviceFormFactor, D as DeviceKeyStorage, Y as EXTRA_KEY_PREFIX, Z as GENERIC_PERMISSION_COPY, _ as IdentifyOnboardingBinding, $ as IdentifyOnboardingOptions, a0 as IdentityRecord, a1 as IdentitySource, a2 as IdentitySpace, a3 as NOTIFICATIONS_PERMISSION_COPY, a4 as OnboardingProgress, a5 as PermissionScreenCopy, R as ResolveAutoDeviceKeyOptions, a6 as ResolveUserContextOptions, a7 as ResolvedUserContext, a8 as USER_ID_MAX_LENGTH, i as WIRE_ONBOARDING_EVENTS, a9 as WIRE_PERMISSION_EVENTS, j as WireOnboardingEventName, aa as WirePermissionEventName, ab as WirePermissionKind, ac as activationJoinContext, k as analyticsUserIdStorageKey, m as clearPiiFromContext, n as clearUserContext, ad as collectDeviceContext, p as deviceIdStorageKey, q as ensureCurrentSessionId, r as getCurrentSessionId, ae as hashEmailFnv1a, af as hostIdentity, ag as hydrateAutoDeviceKey, ah as hydrateDeviceIdentity, ai as identifyOnboarding, aj as isWireScalar, s as looksLikeEmail, t as makeSessionId, ak as mintDeviceId, al as namespaceExtra, am as normalizePermissionStatus, an as permissionEventName, ao as permissionEventProps, u as reportClientEvent, v as reportClientEventAwait, w as reportClientEvents, x as reportClientEventsAwait, y as resetAutoDeviceKeys, z as resetCurrentSessionId, ap as resetIdentityProvenance, F as resolveAutoDeviceKey, aq as resolveIdentity, ar as resolvePermissionCopy, as as resolveUserContext, at as sanitizeUserId, G as setCurrentSessionId, H as toAnalyticsEvent } from './currentSession-C5976akx.js';
3
+ import { I as WireOnboardingProps, J as WireOnboardingConfig, O as OnboardingResult, K as WirePermissionStatus, P as PermissionStage, L as WirePermissionOutcome, S as StepValidator, M as OnboardingEvent, N as OnboardingCopy, C as ClientEventTarget, Q as DeviceContext, T as PermissionScreenConfig, W as WireUserContext, c as ClientEvent, U as PermissionPlacement, g as EnvelopeSource } from './currentSession-CW_5Mq4O.js';
4
+ export { A as AUTO_DEVICE_ID_PREFIX, a as AnalyticsEvent, b as ClearUserContextOptions, d as ClientEventType, V as DEFAULT_PERMISSION_COPY, X as DeviceFormFactor, D as DeviceKeyStorage, Y as EXTRA_KEY_PREFIX, Z as GENERIC_PERMISSION_COPY, _ as IdentifyOnboardingBinding, $ as IdentifyOnboardingOptions, a0 as IdentityRecord, a1 as IdentitySource, a2 as IdentitySpace, a3 as NOTIFICATIONS_PERMISSION_COPY, a4 as OnboardingProgress, a5 as PermissionScreenCopy, R as ResolveAutoDeviceKeyOptions, a6 as ResolveUserContextOptions, a7 as ResolvedUserContext, a8 as USER_ID_MAX_LENGTH, i as WIRE_ONBOARDING_EVENTS, a9 as WIRE_PERMISSION_EVENTS, j as WireOnboardingEventName, aa as WirePermissionEventName, ab as WirePermissionKind, ac as activationJoinContext, k as analyticsUserIdStorageKey, m as clearPiiFromContext, n as clearUserContext, ad as collectDeviceContext, p as deviceIdStorageKey, q as ensureCurrentSessionId, r as getCurrentSessionId, ae as hashEmailFnv1a, af as hostIdentity, ag as hydrateAutoDeviceKey, ah as hydrateDeviceIdentity, ai as identifyOnboarding, aj as isWireScalar, s as looksLikeEmail, t as makeSessionId, ak as mintDeviceId, al as namespaceExtra, am as normalizePermissionStatus, an as permissionEventName, ao as permissionEventProps, u as reportClientEvent, v as reportClientEventAwait, w as reportClientEvents, x as reportClientEventsAwait, y as resetAutoDeviceKeys, z as resetCurrentSessionId, ap as resetIdentityProvenance, F as resolveAutoDeviceKey, aq as resolveIdentity, ar as resolvePermissionCopy, as as resolveUserContext, at as sanitizeUserId, G as setCurrentSessionId, H as toAnalyticsEvent } from './currentSession-CW_5Mq4O.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';
@@ -1572,6 +1572,15 @@ type WireActivationConfig = {
1572
1572
  appVersion?: string;
1573
1573
  /** Host persistence (AsyncStorage-compatible subset) so the auto-minted device key survives launches. */
1574
1574
  storage?: WireOnboardingStorage;
1575
+ /**
1576
+ * Where a FAILED `track()` goes instead of being dropped: your existing offline queue's `enqueue`
1577
+ * (the same wiring `useLifecycleEvents` takes). Pass it when you already run one queue for the app
1578
+ * and you want one backlog, one retry schedule, one storage slot.
1579
+ *
1580
+ * Omit it and the instance opens its OWN queue the first time a POST fails — never before, so an
1581
+ * app that is online the whole time allocates nothing. A successful `track()` never touches either.
1582
+ */
1583
+ sink?: (event: ClientEvent) => void;
1575
1584
  };
1576
1585
  /** The kit-owned activation surface. `sessionId` is a live getter (reads `getCurrentSessionId()`). */
1577
1586
  type WireActivation = {
@@ -1594,6 +1603,12 @@ type WireActivation = {
1594
1603
  subscribeRevalidation(listener: () => void): () => void;
1595
1604
  /** The current revalidation version — include in a decision-fetch effect's deps to re-fetch on bump. */
1596
1605
  getRevalidationVersion(): number;
1606
+ /**
1607
+ * Tear down the durability queue a failed `track()` may have opened (see
1608
+ * {@link EventQueue.dispose}). Idempotent, never throws, and a no-op on an instance that never had
1609
+ * a failure. Call it when you build an instance per mount; `useWireActivation` does it for you.
1610
+ */
1611
+ dispose(): void;
1597
1612
  };
1598
1613
  /**
1599
1614
  * Create a bound activation instance for a tenant transport. Resolves the device key once (explicit >
@@ -2033,8 +2048,9 @@ interface SessionStartConfig {
2033
2048
  appVersion?: string;
2034
2049
  /** Tenant/app id — namespaces the auto `device_key` fallback below. */
2035
2050
  appId?: string;
2036
- /** Host storage (AsyncStorage subset). Present → `app.session_started` falls back to the kit's
2037
- * persisted auto `device_key` when the host passes none. Absent no fallback (see below). */
2051
+ /** Host storage (AsyncStorage subset). Present AND actually persisting → `app.session_started`
2052
+ * falls back to the kit's persisted auto `device_key` when the host passes none. Absent, or an
2053
+ * adapter that throws / rejects → no fallback (a per-launch key is worse than none, see below). */
2038
2054
  storage?: WireOnboardingStorage;
2039
2055
  }
2040
2056
  /** Per-open identity the host supplies. All optional: a pre-auth open is device-only. */
@@ -2167,8 +2183,10 @@ interface LifecycleConfig {
2167
2183
  appVersion?: string;
2168
2184
  /** Tenant/app id — namespaces the first-open flag AND the hook's internal queue storage key. */
2169
2185
  appId?: string;
2170
- /** Host storage (AsyncStorage subset). Enables the persisted once-ever first-open flag AND the
2171
- * offline durability of the hook's internal queue. Omit it and both degrade to in-memory. */
2186
+ /** Host storage (AsyncStorage subset). Enables the persisted once-ever first-open flag, the
2187
+ * offline durability of the hook's internal queue, AND the auto `device_key` fallback the last
2188
+ * one only when the adapter actually persists (one that throws or rejects gets no fallback, the
2189
+ * same verdict as no storage at all). Omit it and all three degrade to in-memory. */
2172
2190
  storage?: WireOnboardingStorage;
2173
2191
  }
2174
2192
  /** Per-open identity + wiring the host supplies. All optional: a pre-auth open is device-only. */