Skip to content

Pro: restore the Session Pro gate, off by default - #2226

Open
mpretty-cyro wants to merge 1 commit into
devfrom
feature/restore-pro-gate
Open

mpretty-cyro wants to merge 1 commit into
devfrom
feature/restore-pro-gate

Conversation

@mpretty-cyro

@mpretty-cyro mpretty-cyro commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

Restores the Session Pro gate removed in 0b751f7 (#2150), off by default in every build while the Pro release is delayed (previously it defaulted on outside release builds).

Toggle: debug menu → Set app as post Pro launch, or the new QaLaunchConfig launch extra sessionPro=true (debug/QA builds only; same key as iOS).

What the gate does when off (the default)

  • This account: can neither use nor buy Pro, and nothing is restricted for lacking it — standard compose limit, no pinned-conversation limit, no upsell CTAs, no Pro settings row or badge of its own, and no Pro status or proof requests.
  • Other users: their Pro is still honoured — badges and message Pro features show, animated avatars animate, and inbound messages are only cut at the Pro limit.
  • Pro bought on another device: a proof or access expiry synced into config grants nothing on this device, and nothing on this device removes or rewrites it. Every writer of the user's own Pro config is on a gated path, or records a true fact about a newly set/removed avatar.
  • The Pro revocation list is still fetched, so other users' revoked proofs stop showing promptly. This account's own proof is never cleared by a Pro-off device, even if the list revokes it; that is left to its devices with Pro on.

Same rule on iOS, Android and Desktop. One commit per client so each reverts cleanly when Pro ships.

Implementation notes

  • All logged-in Pro loops in ProStatusManager share one gate; turning it off cancels the status and proof-generation workers. The revocation worker keeps polling, and clearing our own proof on revocation stays gated.
  • currentUserProProofForAccess() returns nothing when off, which covers the outgoing proof, declared message features and compose-limit enforcement. The Pro rotating-key signature is also withheld.
  • Recipients always get a Pro data context; only this account's own proof is skipped, so other people's badges still show.
  • The display plan no longer seeds from config when off, and proof renewal scheduling, the proof worker and onPurchaseInFlight are gated.
  • The conversation list's pref-event filter regains SET_FORCE_POST_PRO with the || the removed line was missing (without it the lambda only returned its last comparison).

Testing

  • New ProPreLaunchGateTest (6) and QaLaunchConfigSessionProTest (3); flag-off assertions have flag-on controls.
  • :app:testPlayDebugUnitTest on the current dev base: 370 tests, 0 failures.
  • Appium: see below.

Appium results (2026-09-29, overnight)

Method: every failure was re-run on a pre-gate build (this branch's parent, built separately). Each build was probed for a literal only the gate adds, alongside a control literal present in both. "Gate-caused" means it fails with the gate, passes without it, and holds under an alternating tie-break on fresh devices.

Tested 645c00e5bf against pre-gate 16782ae45f, on API 37 emulators (about 30% noise on both builds):

  • Gate-specific: a Pro-off device renders a Pro sender's badge, with the same per-device proof. Pass.
  • Pro specs (15): no gate-only failures. Badge-to-others was flaky on the gate build and passed on retry.
  • Sweep (150): 55 non-passes. 40 reproduce without the gate; the other 15 went through the tie-break. Pin and unpin fails identically on both builds.
  • The only gate-caused result is intended: "Check Settings page layout" (0/2 with the gate, 2/2 without). The visual diff is exactly this change — the "Upgrade Session" row is gone and the rows below move up. The screenshot baseline needs an update while the gate ships.

Verdict: no gate-caused regression; the Settings baseline diff is expected.

Since those runs: the revocation list is now also fetched while Pro is off (architect-approved), with clearing our own revoked proof still gated. Unit tests pass on the current head; a targeted Appium re-check of the revocation fetch and the badge is running.

Companion PRs

Same gate and rule on each client: session-foundation/session-ios#797 · #2226 · session-foundation/session-desktop#2018

Brings back the post-Pro-launch preference (pref_force_post_pro) removed in
0b751f7, now off by default in every build, with a `sessionPro` launch extra
(the iOS key) so QA harnesses can turn it on. Off, this account can neither use
nor buy Pro and nothing is restricted for lacking it; other people's Pro
(badges, message features) is still honoured. One commit so it reverts cleanly.

- Every self-facing guard 0b751f7 deleted, reapplied in the code's current
  shape. The logged-in Pro loops share one gate; turning it off cancels the
  status and proof workers, while the revocation list keeps polling for other
  people's proofs. Clearing our own revoked proof stays gated.
- Recipients always get a Pro data context; only our own proof is skipped, so a
  proof synced from another device grants nothing here and is left in config.
- Gates Pro code added since the removal: the display plan seeded from config,
  proof renewal scheduling and the proof worker, the access source (outgoing
  proof and declared features), the rotating-key signature, and the
  purchase-in-flight path.
- The conversation list's pref-event filter regains SET_FORCE_POST_PRO with the
  `||` it was missing, so the two force-Pro events are no longer ignored.
@mpretty-cyro
mpretty-cyro force-pushed the feature/restore-pro-gate branch from 645c00e to 580478f Compare September 28, 2026 21:02
@mpretty-cyro
mpretty-cyro marked this pull request as ready for review September 28, 2026 23:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant