@revturbine/sdk 0.11.5 → 0.11.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -3581,6 +3581,138 @@ declare const AnalyticsCatalogConceptSchema: z.ZodObject<{
3581
3581
  }>>;
3582
3582
  }, z.core.$strip>>;
3583
3583
  livemode_qualified: z.ZodOptional<z.ZodBoolean>;
3584
+ record_contract: z.ZodOptional<z.ZodObject<{
3585
+ record_id: z.ZodArray<z.ZodString>;
3586
+ source_namespace: z.ZodString;
3587
+ occurred_time_field: z.ZodString;
3588
+ received_time_field: z.ZodOptional<z.ZodString>;
3589
+ dedup: z.ZodEnum<{
3590
+ unknown: "unknown";
3591
+ deduplicated_on_record_id: "deduplicated_on_record_id";
3592
+ summed_on_sorting_key: "summed_on_sorting_key";
3593
+ append_only: "append_only";
3594
+ upsert_on_primary_key: "upsert_on_primary_key";
3595
+ recomputed_at_query: "recomputed_at_query";
3596
+ }>;
3597
+ revision: z.ZodEnum<{
3598
+ unknown: "unknown";
3599
+ immutable: "immutable";
3600
+ re_emit_higher_version: "re_emit_higher_version";
3601
+ in_place_update: "in_place_update";
3602
+ recomputed_from_source: "recomputed_from_source";
3603
+ }>;
3604
+ late_arrival: z.ZodEnum<{
3605
+ unknown: "unknown";
3606
+ accepted: "accepted";
3607
+ accepted_within_retention: "accepted_within_retention";
3608
+ rejected: "rejected";
3609
+ }>;
3610
+ correlation_keys: z.ZodOptional<z.ZodArray<z.ZodString>>;
3611
+ livemode_field: z.ZodOptional<z.ZodString>;
3612
+ policy_version_fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
3613
+ note: z.ZodOptional<z.ZodString>;
3614
+ }, z.core.$strip>>;
3615
+ keys: z.ZodOptional<z.ZodArray<z.ZodObject<{
3616
+ key: z.ZodString;
3617
+ path: z.ZodString;
3618
+ resolution: z.ZodEnum<{
3619
+ source: "source";
3620
+ enriched: "enriched";
3621
+ absent: "absent";
3622
+ }>;
3623
+ note: z.ZodOptional<z.ZodString>;
3624
+ }, z.core.$strip>>>;
3625
+ measures: z.ZodOptional<z.ZodArray<z.ZodObject<{
3626
+ name: z.ZodString;
3627
+ source: z.ZodString;
3628
+ unit: z.ZodEnum<{
3629
+ count: "count";
3630
+ ratio: "ratio";
3631
+ seconds: "seconds";
3632
+ currency_minor: "currency_minor";
3633
+ timestamp: "timestamp";
3634
+ usage_unit: "usage_unit";
3635
+ polymorphic: "polymorphic";
3636
+ }>;
3637
+ temporal: z.ZodEnum<{
3638
+ stock: "stock";
3639
+ flow: "flow";
3640
+ gauge: "gauge";
3641
+ }>;
3642
+ sign: z.ZodEnum<{
3643
+ signed: "signed";
3644
+ positive_magnitude: "positive_magnitude";
3645
+ unsigned: "unsigned";
3646
+ }>;
3647
+ aggregation_semantics: z.ZodEnum<{
3648
+ additive: "additive";
3649
+ semi_additive: "semi_additive";
3650
+ non_additive: "non_additive";
3651
+ }>;
3652
+ note: z.ZodOptional<z.ZodString>;
3653
+ }, z.core.$strip>>>;
3654
+ event_attributes: z.ZodOptional<z.ZodArray<z.ZodObject<{
3655
+ name: z.ZodString;
3656
+ path: z.ZodString;
3657
+ note: z.ZodOptional<z.ZodString>;
3658
+ }, z.core.$strip>>>;
3659
+ sources: z.ZodOptional<z.ZodArray<z.ZodObject<{
3660
+ kind: z.ZodEnum<{
3661
+ unavailable: "unavailable";
3662
+ ingested_event: "ingested_event";
3663
+ datasource: "datasource";
3664
+ control_plane_table: "control_plane_table";
3665
+ build: "build";
3666
+ }>;
3667
+ ref: z.ZodString;
3668
+ blocker: z.ZodOptional<z.ZodString>;
3669
+ note: z.ZodOptional<z.ZodString>;
3670
+ }, z.core.$strip>>>;
3671
+ build: z.ZodOptional<z.ZodObject<{
3672
+ kind: z.ZodEnum<{
3673
+ pipe: "pipe";
3674
+ unavailable: "unavailable";
3675
+ materialized_view: "materialized_view";
3676
+ worker: "worker";
3677
+ query_time: "query_time";
3678
+ }>;
3679
+ ref: z.ZodString;
3680
+ inputs: z.ZodArray<z.ZodString>;
3681
+ blocker: z.ZodOptional<z.ZodString>;
3682
+ }, z.core.$strip>>;
3683
+ maturity: z.ZodOptional<z.ZodObject<{
3684
+ status: z.ZodEnum<{
3685
+ unavailable: "unavailable";
3686
+ declared: "declared";
3687
+ }>;
3688
+ horizon_field: z.ZodOptional<z.ZodString>;
3689
+ observed_through_field: z.ZodOptional<z.ZodString>;
3690
+ blocker: z.ZodOptional<z.ZodString>;
3691
+ }, z.core.$strip>>;
3692
+ oracle_family: z.ZodOptional<z.ZodObject<{
3693
+ family: z.ZodEnum<{
3694
+ none: "none";
3695
+ funnel: "funnel";
3696
+ revenue: "revenue";
3697
+ gate: "gate";
3698
+ presentation: "presentation";
3699
+ attribution: "attribution";
3700
+ event_count: "event_count";
3701
+ cohort: "cohort";
3702
+ read_through: "read_through";
3703
+ }>;
3704
+ blocker: z.ZodOptional<z.ZodString>;
3705
+ }, z.core.$strip>>;
3706
+ policy_dependencies: z.ZodOptional<z.ZodArray<z.ZodObject<{
3707
+ kind: z.ZodEnum<{
3708
+ attribution: "attribution";
3709
+ mrr: "mrr";
3710
+ lifecycle: "lifecycle";
3711
+ engagement: "engagement";
3712
+ }>;
3713
+ stamped: z.ZodBoolean;
3714
+ blocker: z.ZodOptional<z.ZodString>;
3715
+ }, z.core.$strip>>>;
3584
3716
  deprecation: z.ZodOptional<z.ZodObject<{
3585
3717
  deprecated: z.ZodBoolean;
3586
3718
  replaced_by: z.ZodOptional<z.ZodString>;
@@ -5770,6 +5902,138 @@ declare const AnalyticsCatalogSchema: z.ZodObject<{
5770
5902
  }>>;
5771
5903
  }, z.core.$strip>>;
5772
5904
  livemode_qualified: z.ZodOptional<z.ZodBoolean>;
5905
+ record_contract: z.ZodOptional<z.ZodObject<{
5906
+ record_id: z.ZodArray<z.ZodString>;
5907
+ source_namespace: z.ZodString;
5908
+ occurred_time_field: z.ZodString;
5909
+ received_time_field: z.ZodOptional<z.ZodString>;
5910
+ dedup: z.ZodEnum<{
5911
+ unknown: "unknown";
5912
+ deduplicated_on_record_id: "deduplicated_on_record_id";
5913
+ summed_on_sorting_key: "summed_on_sorting_key";
5914
+ append_only: "append_only";
5915
+ upsert_on_primary_key: "upsert_on_primary_key";
5916
+ recomputed_at_query: "recomputed_at_query";
5917
+ }>;
5918
+ revision: z.ZodEnum<{
5919
+ unknown: "unknown";
5920
+ immutable: "immutable";
5921
+ re_emit_higher_version: "re_emit_higher_version";
5922
+ in_place_update: "in_place_update";
5923
+ recomputed_from_source: "recomputed_from_source";
5924
+ }>;
5925
+ late_arrival: z.ZodEnum<{
5926
+ unknown: "unknown";
5927
+ accepted: "accepted";
5928
+ accepted_within_retention: "accepted_within_retention";
5929
+ rejected: "rejected";
5930
+ }>;
5931
+ correlation_keys: z.ZodOptional<z.ZodArray<z.ZodString>>;
5932
+ livemode_field: z.ZodOptional<z.ZodString>;
5933
+ policy_version_fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
5934
+ note: z.ZodOptional<z.ZodString>;
5935
+ }, z.core.$strip>>;
5936
+ keys: z.ZodOptional<z.ZodArray<z.ZodObject<{
5937
+ key: z.ZodString;
5938
+ path: z.ZodString;
5939
+ resolution: z.ZodEnum<{
5940
+ source: "source";
5941
+ enriched: "enriched";
5942
+ absent: "absent";
5943
+ }>;
5944
+ note: z.ZodOptional<z.ZodString>;
5945
+ }, z.core.$strip>>>;
5946
+ measures: z.ZodOptional<z.ZodArray<z.ZodObject<{
5947
+ name: z.ZodString;
5948
+ source: z.ZodString;
5949
+ unit: z.ZodEnum<{
5950
+ count: "count";
5951
+ ratio: "ratio";
5952
+ seconds: "seconds";
5953
+ currency_minor: "currency_minor";
5954
+ timestamp: "timestamp";
5955
+ usage_unit: "usage_unit";
5956
+ polymorphic: "polymorphic";
5957
+ }>;
5958
+ temporal: z.ZodEnum<{
5959
+ stock: "stock";
5960
+ flow: "flow";
5961
+ gauge: "gauge";
5962
+ }>;
5963
+ sign: z.ZodEnum<{
5964
+ signed: "signed";
5965
+ positive_magnitude: "positive_magnitude";
5966
+ unsigned: "unsigned";
5967
+ }>;
5968
+ aggregation_semantics: z.ZodEnum<{
5969
+ additive: "additive";
5970
+ semi_additive: "semi_additive";
5971
+ non_additive: "non_additive";
5972
+ }>;
5973
+ note: z.ZodOptional<z.ZodString>;
5974
+ }, z.core.$strip>>>;
5975
+ event_attributes: z.ZodOptional<z.ZodArray<z.ZodObject<{
5976
+ name: z.ZodString;
5977
+ path: z.ZodString;
5978
+ note: z.ZodOptional<z.ZodString>;
5979
+ }, z.core.$strip>>>;
5980
+ sources: z.ZodOptional<z.ZodArray<z.ZodObject<{
5981
+ kind: z.ZodEnum<{
5982
+ unavailable: "unavailable";
5983
+ ingested_event: "ingested_event";
5984
+ datasource: "datasource";
5985
+ control_plane_table: "control_plane_table";
5986
+ build: "build";
5987
+ }>;
5988
+ ref: z.ZodString;
5989
+ blocker: z.ZodOptional<z.ZodString>;
5990
+ note: z.ZodOptional<z.ZodString>;
5991
+ }, z.core.$strip>>>;
5992
+ build: z.ZodOptional<z.ZodObject<{
5993
+ kind: z.ZodEnum<{
5994
+ pipe: "pipe";
5995
+ unavailable: "unavailable";
5996
+ materialized_view: "materialized_view";
5997
+ worker: "worker";
5998
+ query_time: "query_time";
5999
+ }>;
6000
+ ref: z.ZodString;
6001
+ inputs: z.ZodArray<z.ZodString>;
6002
+ blocker: z.ZodOptional<z.ZodString>;
6003
+ }, z.core.$strip>>;
6004
+ maturity: z.ZodOptional<z.ZodObject<{
6005
+ status: z.ZodEnum<{
6006
+ unavailable: "unavailable";
6007
+ declared: "declared";
6008
+ }>;
6009
+ horizon_field: z.ZodOptional<z.ZodString>;
6010
+ observed_through_field: z.ZodOptional<z.ZodString>;
6011
+ blocker: z.ZodOptional<z.ZodString>;
6012
+ }, z.core.$strip>>;
6013
+ oracle_family: z.ZodOptional<z.ZodObject<{
6014
+ family: z.ZodEnum<{
6015
+ none: "none";
6016
+ funnel: "funnel";
6017
+ revenue: "revenue";
6018
+ gate: "gate";
6019
+ presentation: "presentation";
6020
+ attribution: "attribution";
6021
+ event_count: "event_count";
6022
+ cohort: "cohort";
6023
+ read_through: "read_through";
6024
+ }>;
6025
+ blocker: z.ZodOptional<z.ZodString>;
6026
+ }, z.core.$strip>>;
6027
+ policy_dependencies: z.ZodOptional<z.ZodArray<z.ZodObject<{
6028
+ kind: z.ZodEnum<{
6029
+ attribution: "attribution";
6030
+ mrr: "mrr";
6031
+ lifecycle: "lifecycle";
6032
+ engagement: "engagement";
6033
+ }>;
6034
+ stamped: z.ZodBoolean;
6035
+ blocker: z.ZodOptional<z.ZodString>;
6036
+ }, z.core.$strip>>>;
5773
6037
  deprecation: z.ZodOptional<z.ZodObject<{
5774
6038
  deprecated: z.ZodBoolean;
5775
6039
  replaced_by: z.ZodOptional<z.ZodString>;
@@ -7959,9 +8223,9 @@ declare const WebhookProcessingStatusSchema: z.ZodEnum<{
7959
8223
  */
7960
8224
  declare const WebhookDispatchStatusSchema: z.ZodEnum<{
7961
8225
  unknown: "unknown";
8226
+ accepted: "accepted";
7962
8227
  failed: "failed";
7963
8228
  pending: "pending";
7964
- accepted: "accepted";
7965
8229
  terminal: "terminal";
7966
8230
  not_required: "not_required";
7967
8231
  dispatching: "dispatching";
@@ -8017,9 +8281,9 @@ declare const WebhookDeliverySchema: z.ZodObject<{
8017
8281
  }>>;
8018
8282
  dispatch_status: z.ZodDefault<z.ZodEnum<{
8019
8283
  unknown: "unknown";
8284
+ accepted: "accepted";
8020
8285
  failed: "failed";
8021
8286
  pending: "pending";
8022
- accepted: "accepted";
8023
8287
  terminal: "terminal";
8024
8288
  not_required: "not_required";
8025
8289
  dispatching: "dispatching";
@@ -9172,6 +9436,9 @@ declare const TrialInstanceSchema: z.ZodObject<{
9172
9436
  usage_limit_value: z.ZodOptional<z.ZodNumber>;
9173
9437
  converted_at: z.ZodDefault<z.ZodNullable<z.ZodString>>;
9174
9438
  cancelled_at: z.ZodDefault<z.ZodNullable<z.ZodString>>;
9439
+ trial_episode_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
9440
+ stripe_subscription_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
9441
+ actual_end_at: z.ZodDefault<z.ZodNullable<z.ZodString>>;
9175
9442
  metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
9176
9443
  }, z.core.$strip>;
9177
9444
  declare const trialPaths: ZodOpenApiPathsObject;
@@ -15738,12 +16005,12 @@ declare const ServerEvaluationPayloadSchema: z.ZodObject<{
15738
16005
 
15739
16006
  declare const PlaybookVersionStatusSchema: z.ZodEnum<{
15740
16007
  draft: "draft";
16008
+ rejected: "rejected";
15741
16009
  archived: "archived";
15742
16010
  awaiting_approval: "awaiting_approval";
15743
16011
  approved: "approved";
15744
16012
  deploying: "deploying";
15745
16013
  deployed: "deployed";
15746
- rejected: "rejected";
15747
16014
  }>;
15748
16015
  declare const PlaybookVersionSchema: z.ZodObject<{
15749
16016
  id: z.ZodString;
@@ -15755,12 +16022,12 @@ declare const PlaybookVersionSchema: z.ZodObject<{
15755
16022
  description: z.ZodOptional<z.ZodString>;
15756
16023
  status: z.ZodDefault<z.ZodEnum<{
15757
16024
  draft: "draft";
16025
+ rejected: "rejected";
15758
16026
  archived: "archived";
15759
16027
  awaiting_approval: "awaiting_approval";
15760
16028
  approved: "approved";
15761
16029
  deploying: "deploying";
15762
16030
  deployed: "deployed";
15763
- rejected: "rejected";
15764
16031
  }>>;
15765
16032
  labels: z.ZodDefault<z.ZodArray<z.ZodString>>;
15766
16033
  created_by: z.ZodString;
@@ -16271,9 +16538,9 @@ declare const AuthMemberSchema: z.ZodObject<{
16271
16538
  declare const InvitationStatusSchema: z.ZodEnum<{
16272
16539
  canceled: "canceled";
16273
16540
  expired: "expired";
16274
- pending: "pending";
16275
16541
  accepted: "accepted";
16276
16542
  rejected: "rejected";
16543
+ pending: "pending";
16277
16544
  }>;
16278
16545
  declare const AuthInvitationSchema: z.ZodObject<{
16279
16546
  id: z.ZodString;
@@ -16288,9 +16555,9 @@ declare const AuthInvitationSchema: z.ZodObject<{
16288
16555
  status: z.ZodDefault<z.ZodEnum<{
16289
16556
  canceled: "canceled";
16290
16557
  expired: "expired";
16291
- pending: "pending";
16292
16558
  accepted: "accepted";
16293
16559
  rejected: "rejected";
16560
+ pending: "pending";
16294
16561
  }>>;
16295
16562
  expires_at: z.ZodString;
16296
16563
  created_at: z.ZodString;
@@ -17171,11 +17438,14 @@ interface RevTurbineTreatmentInteractionInput {
17171
17438
  * `PlacementOutput.rule_id` — projected onto the `placement_interaction`
17172
17439
  * clickstream payload as `rule_handle` (BL-0182).
17173
17440
  *
17174
- * Unlike its neighbours this does NOT reach the wire
17175
- * `TreatmentInteractionInputSchema` / `placement_presentations`: that path is
17176
- * column-shaped and would need a datasource migration. The clickstream
17177
- * carries payload fields inside a JSON column, so the rule slice for
17178
- * interactions is readable the moment producers send it.
17441
+ * It reaches the wire `TreatmentInteractionInputSchema` too, as of BL-0200.
17442
+ * It deliberately did not under BL-0182: that path is column-shaped and the
17443
+ * rule would have needed a datasource migration, while the clickstream
17444
+ * carries payload fields inside a JSON column and was readable at once.
17445
+ * `placement_exposure_attribution.rule_handle` exists now (web ledger 015),
17446
+ * so the base exposure row records the rule the exposure was DECIDED by
17447
+ * rather than waiting for attribution to reconstruct one when a conversion
17448
+ * lands — which is what makes presentation-grain rule cuts servable.
17179
17449
  *
17180
17450
  * Omitted, never sent empty, when no decision is in scope — a bare
17181
17451
  * `trackTreatmentInteraction` caller supplies no rule, and absence is what
@@ -21339,6 +21609,12 @@ declare class RevTurbineCustomerSdk {
21339
21609
  * redundant segment re-evaluation.
21340
21610
  */
21341
21611
  private lastServerContextHash?;
21612
+ /**
21613
+ * The plan move an optimistic `convert()` made ahead of the server (BL-0004),
21614
+ * held only until a `client-context` read stops reporting the old plan. See
21615
+ * {@link dropStalePostConversionPlan}.
21616
+ */
21617
+ private pendingConversionPlan?;
21342
21618
  private usageBalances;
21343
21619
  private localDecisionsByPlacementId;
21344
21620
  private localPlacementsByLookupKey;
@@ -22483,12 +22759,16 @@ declare class RevTurbineCustomerSdk {
22483
22759
  /** Map the client-safe context response into a UserContext patch (plan 157). */
22484
22760
  private mapClientSafeContext;
22485
22761
  /**
22486
- * Apply a server-derived UserContext patch (plan 157) — mirrors setUserContext
22487
- * but accepts a partial. The patch's RevTurbine-authoritative fields (trial,
22488
- * billing signals) overlay the held context; undefined fields are skipped by
22489
- * the merge, so app-set values are never nulled.
22762
+ * Apply a UserContext patch — mirrors setUserContext but accepts a partial.
22763
+ * RevTurbine-authoritative fields (trial, billing signals, server plan)
22764
+ * overlay the held context; undefined fields are skipped by the merge, so
22765
+ * app-set values are never nulled.
22766
+ *
22767
+ * Two callers: the server client-context fetch (plan 157) and the optimistic
22768
+ * post-conversion plan move (BL-0004). Both notify subscribers, which is what
22769
+ * makes mounted slots and gates re-resolve.
22490
22770
  */
22491
- private applyServerContextPatch;
22771
+ private applyUserContextPatch;
22492
22772
  /**
22493
22773
  * Record that a placement was rendered to the user. Plan 43 TASK-9.
22494
22774
  *
@@ -22665,13 +22945,73 @@ declare class RevTurbineCustomerSdk {
22665
22945
  */
22666
22946
  snooze(outputId: string, seconds?: number): Promise<void>;
22667
22947
  /**
22668
- * Record a confirmed CTA completion and retire the decision's placement
22669
- * permanently — future calls to `getPlacementDecision` for it will not
22670
- * return it again.
22948
+ * Record a confirmed CTA completion, then reload the UserContext so every
22949
+ * mounted surface re-decides against the plan the user just converted to.
22950
+ *
22951
+ * Conversion is **not** a suppression: it writes no cooldown and no permanent
22952
+ * retirement (spec §"interaction" table; Kent's plan 254 D-9 ruling). What
22953
+ * makes a converted upgrade banner leave the screen is the user no longer
22954
+ * matching it — so a conversion that did not refresh the context left the
22955
+ * placement mounted until something else happened to re-resolve it. Kent,
22956
+ * 2026-09-25 (BL-0004): *"Converting should trigger a reloading of UserContext
22957
+ * with the new plan/billing state the user has converted to."*
22958
+ *
22959
+ * Ordering, and why it is this way round:
22960
+ *
22961
+ * 1. The interaction is recorded (analytics + attribution), as before.
22962
+ * 2. **Optimistically**, locally: when the converted output's CTA names a
22963
+ * target plan (`cta_path.plan_handle`), the held context moves to that plan
22964
+ * immediately. Billing truth arrives by Stripe webhook, so
22965
+ * `GET /api/sdk/client-context` can still report the OLD plan for seconds
22966
+ * after a successful checkout — waiting for it would leave the upgrade
22967
+ * prompt on screen exactly when the user has just paid.
22968
+ * 3. Subscribers are notified either way — a conversion whose CTA names no
22969
+ * plan still re-decides mounted slots and re-checks mounted gates, which is
22970
+ * what turns a plan change the host applied itself into a re-render.
22971
+ * 4. **Then** the server refresh (`fetchClientContext()`), which overlays the
22972
+ * RevTurbine-authoritative trial / billing-health / plan fields and
22973
+ * notifies again if it changed anything. It is best-effort and never
22974
+ * throws, so awaiting it cannot fail a conversion; with no client-session
22975
+ * minter configured it is a no-op and the optimistic state stands.
22976
+ *
22977
+ * Mounted `PlacementController`s re-decide and mounted `EntitlementGate`s
22978
+ * re-check through their `watchUserContext()` subscriptions — which the React
22979
+ * bindings attach for you. Re-resolution emits the normal lifecycle events
22980
+ * once per final decision; the transient states emit nothing.
22981
+ * `PlacementController.ctaComplete()` is unchanged and remains the
22982
+ * component-level path.
22671
22983
  *
22672
22984
  * @public
22673
22985
  */
22674
22986
  convert(outputId: string): Promise<void>;
22987
+ /**
22988
+ * The BL-0004 post-conversion context reload: optimistic local plan move,
22989
+ * then the server refresh. See {@link convert} for the ordering rationale.
22990
+ */
22991
+ private reloadUserContextAfterConversion;
22992
+ /**
22993
+ * Keep a stale server plan from undoing an optimistic conversion (BL-0004).
22994
+ *
22995
+ * Billing truth arrives by Stripe webhook, so a `client-context` read that
22996
+ * races the webhook reports the PRE-conversion plan — and the server plan
22997
+ * deliberately overlays the app-supplied one (plan 179 TASK-1), so applying
22998
+ * that read verbatim would put the upgrade prompt straight back on screen
22999
+ * seconds after the user paid.
23000
+ *
23001
+ * So while a conversion is pending, a server plan equal to the plan converted
23002
+ * AWAY from is dropped — only the plan fields, never the trial or billing-health
23003
+ * signals, which are authoritative regardless. Any other value (the new plan,
23004
+ * or a third one the user was moved to out-of-band) clears the pending state
23005
+ * and applies, so this can suppress at most the one value it was created for
23006
+ * and cannot outlive the lag it exists to cover.
23007
+ */
23008
+ private dropStalePostConversionPlan;
23009
+ /**
23010
+ * The display name the loaded Playbook gives a plan handle, else the handle.
23011
+ * Keeps an optimistic plan move from putting a raw handle in front of a user
23012
+ * when the Playbook already knows the plan's name.
23013
+ */
23014
+ private planNameForHandle;
22675
23015
  /**
22676
23016
  * Emit a canonical trigger event. There is no in-SDK consumer that matches
22677
23017
  * on trigger names — the shipped behavior is ingest to `events_clickstream`
@@ -23135,12 +23475,41 @@ declare class PlacementController {
23135
23475
  private _awaitingConfig;
23136
23476
  private _configRetries;
23137
23477
  private _playbookUnsubscribe;
23478
+ private _userContextUnsubscribe;
23138
23479
  constructor(sdk: RevTurbineCustomerSdk, options: PlacementControllerOptions);
23139
23480
  /**
23140
- * Stop listening for Playbook loads. Idempotent; call it when the owning
23141
- * component unmounts (`usePlacement` does).
23481
+ * Stop listening for Playbook loads and user-context changes. Idempotent; call
23482
+ * it when the owning component unmounts (`usePlacement` does).
23142
23483
  */
23143
23484
  dispose(): void;
23485
+ /**
23486
+ * Drop only the Playbook-load subscription — the within-load-cycle teardown
23487
+ * (BL-0177). A mounted controller keeps watching the user context (BL-0004).
23488
+ */
23489
+ private unsubscribePlaybook;
23490
+ /**
23491
+ * Re-decide whenever the user context changes (BL-0004).
23492
+ *
23493
+ * The counterpart to {@link EntitlementGate.watchUserContext}, and the reason
23494
+ * `sdk.convert()` now removes a converted placement in place: conversion writes
23495
+ * no suppression — eligibility is a function of the user's CURRENT plan and
23496
+ * targeting — so the only thing that can take a converted upgrade banner off
23497
+ * screen is a re-decide against the reloaded context. Without this the
23498
+ * placement stayed mounted until something else happened to re-resolve it, and
23499
+ * the host had to call `refresh()` itself or use the component's
23500
+ * `ctaComplete()` (the limitation plan 236 TASK-13 recorded).
23501
+ *
23502
+ * Only re-decides a controller that has already resolved something: before the
23503
+ * first `load()` there is nothing on screen to be stale, and firing then would
23504
+ * turn every startup `identify()` into a duplicate decision.
23505
+ *
23506
+ * Calls `load()` rather than `refresh()` on purpose — `refresh()` clears
23507
+ * impression/exposure tracking, so a context change would re-credit a
23508
+ * presentation the user never saw again.
23509
+ *
23510
+ * Returns an unsubscribe function; {@link dispose} also drops it.
23511
+ */
23512
+ watchUserContext(): () => void;
23144
23513
  /**
23145
23514
  * Is this decision a race against a Playbook load rather than a verdict?
23146
23515
  *
@@ -23358,12 +23727,18 @@ declare class EntitlementGate {
23358
23727
  private _awaitedResult;
23359
23728
  private _configRetries;
23360
23729
  private _playbookUnsubscribe;
23730
+ private _userContextUnsubscribe;
23361
23731
  constructor(sdk: RevTurbineCustomerSdk, options: EntitlementGateOptions);
23362
23732
  /**
23363
- * Stop listening for Playbook loads. Idempotent; call it when the owning
23364
- * component unmounts (`useEntitlement` does).
23733
+ * Stop listening for Playbook loads and user-context changes. Idempotent; call
23734
+ * it when the owning component unmounts (`useEntitlement` does).
23365
23735
  */
23366
23736
  dispose(): void;
23737
+ /**
23738
+ * Drop only the Playbook-load subscription — the within-check-cycle teardown
23739
+ * (BL-0179). A mounted gate keeps watching the user context (BL-0004).
23740
+ */
23741
+ private unsubscribePlaybook;
23367
23742
  /** Current state snapshot. */
23368
23743
  get state(): EntitlementGateState;
23369
23744
  /** Convenience: `true` when the entitlement is allowed. */
@@ -23463,8 +23838,13 @@ declare class EntitlementGate {
23463
23838
  * `check()` there is nothing on screen to be stale, and firing then would
23464
23839
  * turn every `identify()` at startup into a redundant evaluation.
23465
23840
  *
23841
+ * `sdk.convert()` reloads the UserContext (BL-0004), so this is also what
23842
+ * flips a mounted `useCan` gate to allowed after a conversion.
23843
+ *
23466
23844
  * Returns an unsubscribe function. Call it when the gate is discarded —
23467
23845
  * without that, a gate outlives its consumer and keeps re-checking.
23846
+ * Idempotent: a second call returns the first subscription rather than
23847
+ * orphaning it, and {@link dispose} drops it too.
23468
23848
  */
23469
23849
  watchUserContext(): () => void;
23470
23850
  private notify;