refactor(backend): remove BetaUserCredit monthly credit refill (hotfix) - #12969
Conversation
The BetaUserCredit class auto-granted beta-cohort users $15 of credits per
calendar month via a MONTHLY-CREDIT-TOP-UP-{date} GRANT transaction. The
class's own docstring marked it for removal as a temporary feature; the
free-credit perk is being retired.
This PR is intentionally surgical:
- Deletes `BetaUserCredit` and the two now-unused settings fields it
consumed (`enable_beta_monthly_credit`, `num_user_credits_refill`).
- Simplifies `get_user_credit_model()` to always return `UserCredit` (or
`DisabledUserCredit` when credits are disabled).
- Drops the dead refill-trigger setup in test fixtures and deletes the
two tests that exercised monthly-refill behavior specifically; swaps
remaining `BetaUserCredit(...)` instantiations for `UserCredit()` in
test files where the class choice was incidental.
- Adds an integration test that asserts the factory's exact return class
to catch any future re-introduction of beta-cohort branching.
`Flag.ENABLE_PLATFORM_PAYMENT` and its three other downstream consumers
(`rate_limit.py`, `v1.py` subscription routing, frontend `PaywallGate`,
frontend onboarding) are intentionally untouched — the soft-brick risk
for flag-off users without payment configured is being handled by other
moving parts in flight. A follow-up PR can clean up the flag and its
gates once that work lands.
Existing `MONTHLY-CREDIT-TOP-UP-*` ledger rows in the DB are unaffected;
they remain valid historical GRANT entries.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughThis PR removes the Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #12969 +/- ##
==========================================
+ Coverage 69.57% 69.58% +0.01%
==========================================
Files 2114 2114
Lines 157419 157368 -51
Branches 16220 16219 -1
==========================================
- Hits 109524 109505 -19
+ Misses 44684 44652 -32
Partials 3211 3211
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
…monthly-credit-refill
Why / What / How
Why
Beta-cohort users have been receiving $15 of free credits at the start of every calendar month via a
MONTHLY-CREDIT-TOP-UP-{date}GRANTtransaction. TheBetaUserCreditclass that implemented this perk was always documented as temporary — its own docstring atcredit.py:1157-1161(master) reads:The free-credit perk is being retired. Removing it also removes a quiet bifurcation in the credit system that has accumulated downstream branches (paywall, onboarding, rate-limits) — the cleanest path forward is to close out the beta cohort.
What
This PR is intentionally surgical — it removes the monthly-refill mechanism only:
BetaUserCredit(mastercredit.py:1157-1187).get_user_credit_model()(mastercredit.py:1223-1248) to always returnUserCredit(orDisabledUserCreditwhen credits are disabled).enable_beta_monthly_credit(never read in production code, only by two test monkeypatches) andnum_user_credits_refill(only consumed by the deleted class's__init__).is_feature_enabledfromcredit.py.test_block_credit_resetandtest_credit_refillincredit_test.py).updatedAt = 35-days-agosetup fromdisable_test_user_transactions()(it was specifically there to trigger the now-gone monthly check).BetaUserCredit(1000)→UserCredit()incredit_test.py,credit_integration_test.py(4 sites), andcredit_metadata_test.py(2 sites). All swapped tests exercise behavior that lived on the parent class — class choice was incidental.enable_beta_monthly_credit/num_user_credits_refillmonkeypatches fromcredit_integration_test.py.credit_concurrency_test.py.test_get_user_credit_model_returns_usercredit_unconditionally— a regression guard that asserts the factory returns exactlyUserCredit(using__class__ is UserCredit, notisinstance, so any futureclass BetaFoo(UserCredit)resurrection trips the test instead of silently passing).How
Flag.ENABLE_PLATFORM_PAYMENTand its three remaining downstream consumers (backend/copilot/rate_limit.py,backend/api/features/v1.py,frontend/src/app/(platform)/PaywallGate/PaywallGate.tsx,frontend/src/app/(no-navbar)/onboarding/useOnboardingPage.ts) are deliberately left in place. A user who currently has the flag off will, post-merge, getUserCreditfrom the factory but no longer see the paywall engage onNO_TIER(becauserate_limit.pystill falls back toBASICmultipliers when the flag is off, andPaywallGateskips when the flag is off). The soft-brick risk this creates for flag-off users without payment configured is being addressed by other moving parts in flight — out of scope for this PR by design.A follow-up PR can clean up the flag and its gates once that parallel work lands.
Existing data:
MONTHLY-CREDIT-TOP-UP-*GRANTrows already in the database are unaffected. They remain valid historical ledger entries; nothing depends on them and nothing cleans them up. No migration needed.Rollback: pure code change.
git revertof the squash commit fully restores prior behavior.Notes for review
d8c18f119), cherry-picked ontomaster. The cherry-pick was clean — no manual conflict resolution.masteranddevdiffer around this code (dev has unrelatedInvoiceListItem,grant_credits,list_invoices,admin_export_user_historyadditions incredit.pyandmax_workspace_storage_mbinsettings.py), but the exact regions this PR deletes are byte-identical between master and dev. The four test files are 100% identical between master and dev.master, the standard master → dev backmerge will carry the change todevautomatically.Changes 🏗️
autogpt_platform/backend/backend/data/credit.pyBetaUserCreditclass.get_user_credit_model()toUserCredit/DisabledUserCreditonly.is_feature_enabledimport.autogpt_platform/backend/backend/util/settings.pyenable_beta_monthly_creditandnum_user_credits_refillfields.autogpt_platform/backend/backend/data/credit_test.pyBetaUserCredit(REFILL_VALUE)→UserCredit(). DropREFILL_VALUEconstant. Clean deadupdatedAtreset indisable_test_user_transactions.test_block_credit_reset(monthly-refill behavioral test).test_credit_refill(asserted post-reset balance equals refill value).datetime/timedelta/timezoneimports.autogpt_platform/backend/backend/data/credit_integration_test.pyBetaUserCredit(1000)→UserCredit().enable_beta_monthly_credit/num_user_credits_refill.test_get_user_credit_model_returns_usercredit_unconditionallyregression test.autogpt_platform/backend/backend/data/credit_metadata_test.pyBetaUserCredit(1000)→UserCredit().autogpt_platform/backend/backend/data/credit_concurrency_test.pyBetaUserCredit.Net: −149 LoC across 6 files.
Checklist 📋
For code changes:
poetry run pytest backend/data/credit_test.py backend/data/credit_integration_test.py backend/data/credit_metadata_test.py backend/data/credit_concurrency_test.py -vpoetry run pytest backend/data/credit_integration_test.py::test_get_user_credit_model_returns_usercredit_unconditionally -v(new regression test)MONTHLY-CREDIT-TOP-UP-*rows on the 1st of next monthgrep -rn "BetaUserCredit\|num_user_credits_refill\|enable_beta_monthly_credit" autogpt_platform/backend/returns zero hitsFor configuration changes:
.env.defaultis updated or already compatible with my changes — neither removed setting was in.env.default(they were Pydantic defaults only)docker-compose.ymlis updated or already compatible — no referencesenable_beta_monthly_creditandnum_user_credits_refillremoved fromSettingsNote on local test execution
The reporter's local Windows env has a
poetry installblocker on thestagehandwheel ([Errno 22]extracting from poetry's artifact cache) that is unrelated to this branch and reproduces onmasterHEAD. All 6 edited files passpython -m astparse, andgrepconfirms zero residual references toBetaUserCredit,num_user_credits_refill,enable_beta_monthly_credit,MONTHLY-CREDIT-TOP-UP, orREFILL_VALUEanywhere inautogpt_platform/backend/. CI is the source of truth for the test runs.Out of scope (deliberate)
Flag.ENABLE_PLATFORM_PAYMENTand its 3 downstream consumers — soft-brick risk handled separately.MONTHLY-CREDIT-TOP-UP-*ledger rows.