Skip to content

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

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

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

Conversation

@mpretty-cyro

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

Copy link
Copy Markdown
Collaborator

Restores the Session Pro master gate removed in 97bdb22 (#729), off by default while the Pro release is delayed.

Toggle: Developer Settings → Session Pro → Enable Session Pro, or the launch environment variable sessionPro=true (what the Appium suite sets).

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

  • SessionProManager with Pro off starts only work about other users — polling the revocation list and re-rendering badges when their proofs lapse. None of this account's Pro tasks start (StoreKit, proof renewal, status fetches, user-expiry wakes), and clearing our own proof on revocation is gated. Gates remain only on entry points reachable from outside the manager: updateWithLatestFromUserConfig, refreshProState, currentUserHasProAccess (also covers the proof mock) and showSessionProCTAIfNeeded.
  • The mock observer always runs, so Developer Settings mocks and switching Pro on take effect at runtime (the remaining own-Pro tasks start on the next launch).
  • showSessionProCTAIfNeeded returns a new ProCTAOutcome.suppressedProDisabled, so callers take their non-upsell path.
  • The composer upsell badge and both pin-limit gates read state that is false when Pro is off, so they check the flag explicitly — otherwise the badge would show and the pin limit would be enforced.
  • Inbound truncation uses the Pro limit when off; canProfileAnimate returns true.
  • Settings drops the Pro row when off (Donate stays put), matching Android and Desktop.

Testing

  • New SessionProGateSpec (12 cases, each flag-off case has a flag-on control): access, character limit, own vs other user's profile features, animation, CTA outcome, expiring-CTA info completing initialisation.
  • xcodebuild test -scheme Session (serial) on the current dev base: 2249 passed, 0 failed.
  • 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 f1d42889fd against pre-gate 95bca7836a:

  • Gate-specific: a Pro-off device renders a Pro sender's badge. Per-device proof: the Pro settings row is present on the Pro-on device and absent on the Pro-off one across a 10s window. Pass.
  • Pro specs (17): no gate-only failures. 8 own-Pro failures reproduce without the gate (composer stays at 2000 after a real grant; Pro animated avatar; Pro pin limit; expired CTA). These are pre-existing on dev and out of scope here.
  • Non-Pro sweep (91, Pro off by default): 26 failures. All reproduce without the gate, or were a harness file-server misconfiguration. Media on the production file server: 13/14, and the one failure (Share to Session) also fails without the gate.
  • Not testable: a long Pro message to a Pro-off recipient, because the sender can't exceed 2000 on either build.

Verdict: no gate-caused regression.

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: #797 · session-foundation/session-android#2226 · session-foundation/session-desktop#2018

Brings back the sessionProEnabled feature (identifier and launch env var
"sessionPro", default off) removed in 97bdb22. 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.

- With Pro off SessionProManager starts only work about other users: polling
  the revocation list and re-rendering their badges when proofs lapse. The
  mock observer always runs, so mocks and switching Pro on apply at runtime.
  None of our own Pro tasks start, and our own proof is never cleared.
- The remaining gates sit on entry points reachable from outside the manager:
  projecting config into state, refreshProState, the access accessor (and its
  proof mock) and the CTA, which returns a new ProCTAOutcome.suppressedProDisabled.
- The composer upsell badge and both pin gates now read state that is false
  when Pro is off, so they need the flag explicitly.
- Settings drops the Pro row when off, matching Android and Desktop.
@mpretty-cyro
mpretty-cyro force-pushed the feature/restore-pro-gate branch from f1d4288 to b482697 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.

2 participants