fix(ios): stop hiding the store-update prompt behind a stale listing gate - #3114
Conversation
…gate IOS_APP_STORE_LISTING_LIVE was added on 2026-09-02 because the App Store URL 404'd, with the comment saying prompts stay hidden on iOS "until then". Then arrived and nobody flipped it: the listing has been serving `Peanut: Send Money & Card App` for a while, and the constant still said false, so every iOS install has been silently denied the update row and the store prompt. Removed rather than flipped. A `true` boolean named LISTING_LIVE tells the next reader nothing except that someone once expected it to be false, and the row condition reads as what it means now — an update the store has to deliver is offered on both platforms. This is not the rescue for installs already stuck behind a store update: the published App Store build is 1.5.0, so an iOS 1.5.0 binary is offered nothing newer, and a device running a bundle built before this change carries the old gate anyway. What it fixes is the population that CAN act — an iOS binary older than the published build now sees the prompt instead of nothing at all.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Code-analysis diffPainscore total: 8999.44 → 8999.31 (-0.13) 🆕 New findings (6)
✅ Resolved (6)
|
🧪 UI test report — ✅ all greenSuites
📊 Coverage (unit)
⏱ 10 slowest test cases
|
There was a problem hiding this comment.
Chip review — no blocking findings — this is not an approval
The stale iOS listing gate is removed cleanly: iOS now gets the existing store-update row and modal when the updater reports that a newer native binary is required.
Checked clean
- Confirmed the detached worktree is clean and pinned to the supplied head; its merge base matches the supplied dev base.
- Traced storeUpdateRequired from both staged-bundle inspection and the live Capgo check through the Profile row and store-only modal.
- Verified a staged OTA bundle still takes precedence over the store-update modal and each modal keeps the correct apply path.
- Confirmed the iOS App Store URL now resolves to the live Peanut listing.
- Exact-head unit, typecheck, format, lint, native-export, analysis, and aggregate CI checks passed; ds-shots was still running at review time.
- A local focused Jest invocation was unavailable because this detached worktree has no installed Jest binary; the exact-head unit gate passed instead.
Security review: did not run — this change has no security, privacy or money surface, so it was not asked. This review is one reviewer short.
Third opinion by claude-opus: 0 finding(s), marked with the model name. It answers only product truth, missing tests and the cross-repo contract, so treat its findings as advice.
Exact head: 78554f4c37f0 · Context: repo, web · Took 8m
🖼 Visual diff — 9 screens moved14 of 74 shots changed · 60 identical · baseline
job summary · before/after/diff images — artifact Fixture screenshots, no backend. Advisory — this check never blocks a merge. Posted from the default branch by ds-shots-comment.yml; the report it renders is untrusted data. |
Every iOS install has been silently denied the update row and the store prompt by a constant that went stale.
What happened
IOS_APP_STORE_LISTING_LIVEwas added on 2026-09-02 (e75d9eed9, "iOS store prompt gated") with this comment:"Until then" arrived and nobody flipped it:
Meanwhile, on both
devandmain:Which fed straight into the only thing that decides whether iOS sees an update at all:
falsethere means no row, no modal, nothing — the invisible failure mode, and it was one boolean rather than anything inherent.Removed, not flipped
A
trueboolean namedLISTING_LIVEtells the next reader nothing except that someone once expected it to be false. The row condition now reads as what it means: an update only the store can deliver is offered on both platforms. Two call sites, no tests referenced it, no docs mentioned it.What this does and does not fix
Does: an iOS binary older than the published App Store build now gets the prompt instead of silence, and can act on it.
Does not rescue installs already stuck behind a store update, for two independent reasons:
1.5.0binary is offered nothing newer, so the prompt would be a dead end for exactly that cohort.I want to be explicit because I got this wrong an hour ago and said flipping it would cancel the need for a new iOS build: it does not. Recovering the stuck iOS cohort still needs a newer iOS build in TestFlight or the App Store. This change is about the population that can act.
The gap it leaves
Nothing checks the store's actual version, so the prompt can point at a store with nothing newer — inherent to a client-side prompt, and true on Android too.
The cheap, honest improvement is available from work already in flight: #3111 computes the per-platform floor of the bundle being withheld, which is the version the user needs. The modal could name it — "Update to 1.7.0 in the App Store" rather than a vague "an update is needed" — which stays truthful even when the store hasn't caught up. That needs the floor plumbed through
OtaUpdateContext, so it belongs with #3111 rather than here.For a real store-version check there's the iTunes Lookup API on iOS (
itunes.apple.com/lookup?id=…returnsversion) and no official equivalent for Play. That's a third-party call from the app with CSP and privacy implications — worth a decision, not worth smuggling into a one-line PR.Verification
123 tests pass across the Profile suites and
migration.utils;tsc --noEmitclean;prettier --checkclean.