Forward model_price_locked to the hero — a paywall was wearing poison's copy

Live induction on the deployed landing page caught this; markup review and the
unit suite both passed it. With the model leg stripped for anonymous visitors,
LiveHeroProp forwarded book/fair/model/ev/quarantine to PriceTriplet but NOT
model_price_locked, so deriveValueState fell through to the missing-model-price
branch and the card rendered "MODEL READ WITHHELD" — the quarantine state,
whose copy says we suppressed our own price because a leg is poisoned. Nothing
was poisoned. The real reason was the paywall, and the two must never share a
face: one says our data is untrustworthy, the other says you don't have this
tier.

Now forwarded, with a test asserting both the separation in deriveValueState
and the forwarding at the call site.

Tests 3559 passed / 291 suites, web build exit 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCNgGSt5qvcLxaeQqa7Zpj
This commit is contained in:
Kev
2026-07-20 19:56:21 -04:00
parent aaa41134d4
commit 4e2f488341
3 changed files with 31 additions and 1 deletions
+1 -1
View File
File diff suppressed because one or more lines are too long
+7
View File
@@ -39,6 +39,8 @@ type Hero = {
value?: boolean | null;
takeable?: boolean | null;
quarantine_reason?: string | null;
/** Free/anonymous: model leg stripped server-side (utils/snapshotGating). */
model_price_locked?: boolean;
};
const SPORT_LABEL: Record<string, string> = { nba: 'NBA', wnba: 'WNBA', mlb: 'MLB', soccer: 'Soccer' };
@@ -162,6 +164,11 @@ export default function LiveHeroProp() {
model_odds: data.model_odds,
ev_pct: data.ev_pct,
quarantine_reason: data.quarantine_reason,
// Session 67 — MUST be forwarded. Without it a GATED model leg
// falls through to the withheld/quarantine branch and the card
// says "we suppressed our price" when the truth is "you don't
// have this tier". A paywall must never wear poison's copy.
model_price_locked: data.model_price_locked,
}}
/>
</div>