Skip to main content
← Back to list
01Issue
BugClosedSwamp ClubPublic
AssigneesNone

Relationships

#2606 A collective that cancels inside its 30-day trial window regains trial access to private extensions

Opened by skunk-ape · 9/28/2026

A collective that subscribes to a paid plan and then cancels while its creation-time trial clock (trigger collective_created) is still running falls back to trial entitlement for private extensions.

Where

collectiveEntitled in lib/app/billing/private-extension-entitlement.ts checks sub.grantsAccess() first. If that fails, it returns collective.trialStatus().state === "active" without reading everGrantedAccess.

Why it looks wrong

AGENTS.md: "Entitlement is remembered, not sampled: a collective that has ever held an entitling subscription can never start a trial." The trial-ended sweep (trial-ended-watch.ts) and the trial door both honour everGrantedAccess, but this entitlement fallback does not. A churned customer keeps private-extension access until day 30 of a trial they converted out of.

Separately, content/manual/reference/api-key-authentication.md says "The trial grants no entitlement". That contradicts this code path either way; whichever behaviour is intended, one of the two is wrong.

Steps

  1. Create a collective (trial starts, collective_created).
  2. Subscribe to Team, then cancel (status canceled, everGrantedAccess: true) within 30 days.
  3. collectiveCanUsePrivateExtensions returns true.

Expected

Decide whether a churned collective should fall back to its trial. If not, gate the fallback on !everGrantedAccess. Also fix the manual line.

Found while triaging #2541.

02Bog Flow
✓OPEN○TRIAGED○IN PROGRESS◉CLOSED

Closed

10/16/2026, 12:32:12 AM

No activity in this phase yet.

03Sludge Pulse
Editable. Press Enter to edit.

system commented 9/28/2026, 6:40:33 PM

Classified automatically when this issue was filed.

  • Source: Swamp Club

If you feel this classification is incorrect, add a ripple to tell us so.

skunk-ape commented 10/12/2026, 8:01:28 PM

Fixed as part of #1728 in https://github.com/swamp-club/swamp-club/pull/1323. The trial fallback now applies only to a collective that has never paid (everGrantedAccess), so a collective that cancels inside its trial window can no longer mark extensions private, and a former customer outside the window gets the paid-plan copy instead of 'trial ended'. The manual line 'The trial grants no entitlement' is corrected too: an active trial does allow private extensions, but only for a collective that never paid.

skunk-ape commented 10/16/2026, 12:32:03 AM

Verified fixed in production; closing. swamp-club PR 1323 (#1728) puts the former-customer check ahead of the trial: in collectiveStanding (lib/domain/billing/standing.ts), a collective whose subscription ever granted access reads as former-customer before its trial is looked at. That standing never entitles private extensions, so its verdict is paywalled. The server test 'gate: a cancelled subscription inside the trial window is the paywall, not the trial' (tests/app/mark_private_gate_test.ts) covers this issue's repro. Production runs this code: whoami serves privateExtensions, which that PR added. The manual line 'The trial grants no entitlement' was corrected in the same PR. swamp-club#3503 has since tightened standing further (a Personal License also ends the trial) without changing this rule. Not reproduced live: that would mean subscribing and then cancelling a collective.

Sign in to post a ripple.