Repository navigation
feat(licensing): check the license with Customer Center - #1112
Merged
Merged
Conversation
Coverage reportClick to see where and how coverage changed
This report was generated by python-coverage-comment-action |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2 of 6 tasks
aivong-openhands
approved these changes
Nov 2, 2026
Contributor
|
🚀 Released in 1.83.0. |
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
HUMAN:
AGENT:
Why
OHE needs to know whether its license key is good and what the account is entitled to. Customer Center now answers that with a signed payload (customer-center#66).
This adds the OHE side: a module that checks the key and that other code can call to enforce the license, plus a banner on the settings pages that shows the license state. Enforcement is off by default, so it can ship before rollout.
Summary
server/licensingchecksOPENHANDS_LICENSE_KEYwith Customer Center on startup and then everyLICENSE_CHECK_INTERVAL_SECONDS(30 minutes by default). It keeps the last trusted answer in memory.is_licensed(),has_feature()andwithin_limit(), or therequire_license/require_featuredependencies. WithLICENSE_ENFORCEMENT_ENABLEDoff, they all allow and no check is made.GET /api/license/statusfeeds a banner at the very top of the settings pages. It shows a missing or invalid key, an unverified license, the trial end date, or an overdue payment, and can't be dismissed.Issue Number
Part of PLTF-3962.
How to Test
LICENSE_SIGNING_KEY_ID=staging-1, andLICENSE_SIGNING_KEYfrom the stagingcustomer-center-appsecret in saas-deploy). Sign up to get a license key.LICENSE_ENFORCEMENT_ENABLED=true,OPENHANDS_LICENSE_KEY=<key>,LICENSE_SERVER_URL=<customer center>and a shortLICENSE_CHECK_INTERVAL_SECONDS(60 is the minimum)./settings. The banner shows the trial end date.trial_ends_atinto the past in Customer Center's database. After the next check, the banner says the trial has ended.Unit tests:
uv run pytest tests/unit/server/licensing tests/unit/server/routes/test_license.pyandnpm run test -- license-banner.Video/Screenshots
See Demo below.
Type
Notes
OHE trusts an answer only when the Ed25519 signature verifies,
key_sha256matches its own key, andexpires_atis in the future. If Customer Center is unreachable or sends something that doesn't verify, OHE keeps the last trusted answer until it expires.The payload models ignore unknown fields and keep
plan,stateandreasonas plain strings, so Customer Center can add values in v1 without breaking older installs.The public keys OHE trusts are baked into the code, in
TRUSTED_PUBLIC_KEYS(server/licensing/verification.py). No setting can add or replace one.LICENSE_SERVER_URLcan point anywhere, and a server there still can't sign answers OHE accepts. A new key, such as production's, ships in a release.The only trusted key so far is
staging-1, added to staging in OpenHands/saas-deploy#1872. Nothing calls the enforcement helpers yet.Demo
OHE checks a trial key with a local Customer Center (customer-center#66, signing with the staging key) and shows the trial end date on every settings page. The trial end is then moved into the past in Customer Center's database, and the next check turns the banner into "Your OpenHands Enterprise trial has ended."
PLTF-3962-license-enforcement.webm
Enterprise server image for this PR: