Repository navigation
Bind unclaimed paid Cloud licences within minutes, not hourly - #1542
Merged
Merged
Conversation
A buyer who paid from an email link and whose browser did not come back to the activation page waited up to 75 minutes for the plan: the binder ran only from the hourly onboarding cron, and the licence site held each licence back for 15 minutes. LicenseService now runs the binder every minute on the Cloud, binds a licence two minutes after the sale, never runs two bindings at once, and logs a minute run only when it binds or fails a licence.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A Cloud customer paid at 18:29 UTC on 5 Nov 2026 from the "blocked calls" email. That checkout goes through the public pricing page, so it does not name the workspace. His browser did not come back to
/settings/license/activate, so the licence stayed unbound. The fallback (bindUnclaimedPaidLicences, from #1451) runs only from the hourly onboarding cron. The licence site also holds every licence back for 15 minutes. Together that means a paying customer can stay locked out for up to 75 minutes. In this case it was about 50 minutes.Changes
LicenseServiceruns the binder every minute on the Cloud (UNCLAIMED_SWEEP_MS). The timer is unref'd and cleared on shutdown. Self-hosted is unchanged: no timer.UNCLAIMED_SETTLE_MS, read from thecreatedAtthe site already sends). The browser's own activation still goes first: Stripe sends it back within seconds, and it knows the workspace for certain. The site applies the same delay (HelpCode-ai/anythingmcp-website PR, 15 → 2 minutes). The Cloud keeps the delay too, in case the site does not.licensesBound=in the drip line) never bind the same key twice. The files worker does not loadLicenseModule, so only the backend process runs the timer.already_paid/bound_elsewherewarnings and "site unreachable" warnings stay at debug.no_accountlicences do not add 1,440 lines a day.No schema change, no migration, no new endpoint.
Cloud: paid licences without a returning browser are bound about 2–3 minutes after the payment instead of up to 75. Self-hosted: no change (the binder and the timer are Cloud only).
Type
Testing
In
packages/backend:npx jest src/license/license-unclaimed.spec.ts: 18 passed. New tests cover:npx jest src/license src/ee/cloud: 21 suites, 392 tests passed.npx eslinton the 3 changed files: clean.npx tsc --noEmit: no errors in the changed files. The errors left are the known local baseline:picomatch,@aws-sdk/client-s3,basic-ftp,ssh2and@smithytypes missing from this machine'snode_modules. CI runs the full suite.Checklist