@revturbine/sdk 0.10.4 → 0.10.6
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/CHANGELOG.md +101 -0
- package/dist/headless.js +1 -1
- package/dist/headless.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types/web-sdk/customer-side.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -47,6 +47,103 @@ also require a changelog entry.
|
|
|
47
47
|
|
|
48
48
|
---
|
|
49
49
|
|
|
50
|
+
## 0.10.6
|
|
51
|
+
|
|
52
|
+
### The trial-status PlanProvider overlay ships in the Rust crate (BL-0153)
|
|
53
|
+
|
|
54
|
+
**What changed.** `revturbine::overlay_trial_status_on_plan_provider` is a new
|
|
55
|
+
public function on the Rust crate: it maps a runtime `UserTrialStatus` onto the
|
|
56
|
+
`trial_*` fields of a resolved PlanProviderState, the fields the placement
|
|
57
|
+
resolver's `trial_progress` / `trial_ending` / `trial_ended` /
|
|
58
|
+
`trial_converted` gates and milestone supersession read. Python has always done
|
|
59
|
+
this inside its shipped package
|
|
60
|
+
(`revturbine.sdk._overlay_trial_status_on_plan_provider`); on Rust the mapping
|
|
61
|
+
existed only as a private helper the facade used, so a host that assembles its
|
|
62
|
+
own provider context — including this repo's own parity runner — had to
|
|
63
|
+
re-implement it. Additive: no existing signature changed.
|
|
64
|
+
|
|
65
|
+
Porting Python's mapping faithfully corrected two Rust-only divergences in the
|
|
66
|
+
overlay the facade applies:
|
|
67
|
+
|
|
68
|
+
| `UserTrialStatus` field | Rust before | Rust now (= TS/Python) |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| `day_number` + `days_remaining` | not derived | `trial_days_total = day_number + days_remaining`, only when both are present |
|
|
71
|
+
| `day_number` | written to `trial_day_number` | not written — no provider-state field reads it |
|
|
72
|
+
| `usage_entitlement_handle` | dropped | `trial_usage_entitlement_handle` |
|
|
73
|
+
|
|
74
|
+
`trial_days_total` is the input to the time-mode progress fallback in
|
|
75
|
+
`placements::trial_gating`, so before this the fallback could never fire on the
|
|
76
|
+
Rust port.
|
|
77
|
+
|
|
78
|
+
**Landed in.** `0.10.6`.
|
|
79
|
+
|
|
80
|
+
**Fail-closed in.** `0.10.6` — the parity facade-presence gate
|
|
81
|
+
(`tests/parity/facade-surface.json`) no longer allow-lists a runner-local
|
|
82
|
+
overlay, so a future re-implementation harness-side fails the gate.
|
|
83
|
+
|
|
84
|
+
**Proving test.** `server-rust/src/sdk.rs` `overlay_maps_every_canonical_trial_field`,
|
|
85
|
+
`trial_days_total_requires_both_halves`, `overlay_does_not_clobber_base_state_with_null`
|
|
86
|
+
(mirroring `server-python/tests/test_trial_overlay_upsert.py`), plus the
|
|
87
|
+
`trial_ending_days_before_end`, `trial_ended_post_expiry` and
|
|
88
|
+
`trial_progress_milestone_supersession` parity fixtures.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 0.10.5
|
|
93
|
+
|
|
94
|
+
### Trial-only local integrations get provider context (BL-0120)
|
|
95
|
+
|
|
96
|
+
**What changed.** `synthesizeProviderContext()` — the fallback that builds
|
|
97
|
+
`DomainProvider` state from `userContext` when no explicit domain provider is
|
|
98
|
+
registered — dropped an integration's trial data whenever no commercial
|
|
99
|
+
`plan` / `plan_handle` was also present. An app supplying **only**
|
|
100
|
+
`initialData.trialStatus` (or `setTrialInstances()` / `setTrialStatus()` with
|
|
101
|
+
no plan) got no provider context at all: `providers.plan` came back
|
|
102
|
+
`undefined`, so `{{trial_days_remaining}}` (and every other `trial*` token
|
|
103
|
+
`derivePlacementPersonalizationTokens` derives from `providers.plan`) stayed
|
|
104
|
+
raw, unresolved, in placement copy. Reported against the CybeDefend demo
|
|
105
|
+
(SDK 0.7.13): a `trial_ending` placement with `in_trial: true,
|
|
106
|
+
days_remaining: 3` left `{{trial_days_remaining}}` literal in the rendered
|
|
107
|
+
body.
|
|
108
|
+
|
|
109
|
+
Two omissions, same root cause — trial was never checked alongside
|
|
110
|
+
`plan` / `plan_handle` / `usage` / `tiers` / `experiments`:
|
|
111
|
+
|
|
112
|
+
- the early-return guard (`if (!plan && !planHandle && !usage && !hasTiers
|
|
113
|
+
&& !hasExperiments) return undefined;`) treated a trial-only integration as
|
|
114
|
+
having no signal whatsoever;
|
|
115
|
+
- even past that guard, the returned `plan` key itself was gated on
|
|
116
|
+
`plan || planHandle` — so the trial fields (`trialActive`,
|
|
117
|
+
`trialDaysRemaining`, etc.) it computed were still discarded for a
|
|
118
|
+
plan-less trial.
|
|
119
|
+
|
|
120
|
+
Both gates now also check `hasTrial` (an explicit trial signal — the default
|
|
121
|
+
untouched `{ in_trial: false }` sentinel does not count, so the omitted-signal
|
|
122
|
+
short-circuit is otherwise unchanged for integrations that supply nothing at
|
|
123
|
+
all). `usage`-only, `tiers`-only, and `experiments`-only integrations already
|
|
124
|
+
threaded through correctly before this change; trial was the only signal
|
|
125
|
+
missing from both checks.
|
|
126
|
+
|
|
127
|
+
No public API change — `synthesizeProviderContext` is private, and the fix is
|
|
128
|
+
additive: a plan-less trial integration now gets a `providers.plan` it never
|
|
129
|
+
got before, with an empty `currentPlanHandle: ''` (no plan name/handle was
|
|
130
|
+
ever supplied to derive one from).
|
|
131
|
+
|
|
132
|
+
**Landed in** `0.10.5`. **Fail-closed in** n/a — a previously-dropped signal
|
|
133
|
+
is now included; nothing that resolved before stops resolving.
|
|
134
|
+
|
|
135
|
+
**Proving test:** `web-sdk/customer-side-trial-token-signal.test.ts` — a
|
|
136
|
+
trial-only local integration now gets a non-empty provider context with
|
|
137
|
+
`trialActive`/`trialDaysRemaining` set, and feeding those through
|
|
138
|
+
`derivePlacementPersonalizationTokens` + `resolveContent` renders
|
|
139
|
+
`{{trial_days_remaining}}` as `"3"` instead of leaving it literal. Includes
|
|
140
|
+
the positive control (trial + plan together — unchanged), the negative
|
|
141
|
+
control (no trial data at all — the token stays absent, never coerced to
|
|
142
|
+
`"0"`), and a sibling check confirming usage-only integrations were already
|
|
143
|
+
unaffected by the guard.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
50
147
|
## 0.10.4
|
|
51
148
|
|
|
52
149
|
### Every payload is a selection candidate, not just the first (BL-0122)
|
|
@@ -94,6 +191,8 @@ placement where payload 1 is not the payload a given user matches. Those users
|
|
|
94
191
|
now see the payload their chips select — which is the fix, and is a live
|
|
95
192
|
behaviour change for such configs. Single-payload placements are unaffected.
|
|
96
193
|
|
|
194
|
+
---
|
|
195
|
+
|
|
97
196
|
## 0.10.3
|
|
98
197
|
|
|
99
198
|
### The Rust port gains the decision surfaces Python already shipped (BL-0145)
|
|
@@ -124,6 +223,8 @@ and the crate could lack the capability entirely without a single fixture
|
|
|
124
223
|
going red. The runner now calls `revturbine::plans`, and the inline copies are
|
|
125
224
|
deleted; all 102 comparisons stay byte-identical.
|
|
126
225
|
|
|
226
|
+
---
|
|
227
|
+
|
|
127
228
|
## 0.10.2
|
|
128
229
|
|
|
129
230
|
### Local mode resolves placements by slot id (BL-0119)
|