Skip to content

[6.x] Site keys and a simpler licensing flow - #15355

Draft
jackmcdade wants to merge 21 commits into
6.xfrom
feature/site-key
Draft

[6.x] Site keys and a simpler licensing flow#15355
jackmcdade wants to merge 21 commits into
6.xfrom
feature/site-key

Conversation

@jackmcdade

@jackmcdade jackmcdade commented Sep 2, 2026

Copy link
Copy Markdown
Member

Summary

This introduces a site key: a stable identity shared by a Statamic project’s local, staging, and production installs. It identifies the project; it is not a license.

New projects receive a key during installation. Customers can then connect the project to statamic.com from the Control Panel or CLI and buy, renew, or update licensing without manually creating a site record or copying a replacement key back into every environment.

Installs sharing the key resolve to the same site record and license state. This also lays the groundwork for better visibility of a project’s environments in the Control Panel and on statamic.com, though this PR does not yet build a complete automatic environment inventory.

What changes

  • Automatic identity: statamic:install writes a new-format STATAMIC_SITE_KEY to .env and .env.example without replacing an existing value.
  • A clear Control Panel flow: the Licensing utility presents one next action—generate a key, connect to statamic.com, buy or renew, or add a missing domain.
  • CLI connection: php please license uses a short URL and device code to connect the site to an account.
  • Site-aware checkout: the Control Panel summarizes the required Statamic Pro and addon licenses, then opens checkout for the correct site. Returning to the CP refreshes its status automatically.
  • Safer cloning and rotation: php please site:fresh-key separates a cloned project from its starter; php please site:rotate-key replaces a key while the old one remains valid during a grace period.
  • Clearer status: the interface distinguishes identified, connected, licensed, invalid-domain, shared-key, and renewal states.

Compatibility

Existing 16-character keys and STATAMIC_LICENSE_KEY continue to work without migration. Populated keys are not overwritten, and the interface consistently distinguishes having a site key from having a license.

This is the CMS half of the feature and requires the corresponding account, checkout, and licensing-service changes on statamic.com.

Test plan

  • A fresh install writes the same new site key to .env and .env.example; blank values are filled and populated values remain unchanged.
  • Existing STATAMIC_LICENSE_KEY and 16-character keys still work.
  • CP journey: Generate site keyConnect to Statamic.com → Buy, Renew, or Add domain as appropriate.
  • Returning from statamic.com refreshes the CP status automatically.
  • Checkout lists the correct Pro/addon products and is tied to the correct site.
  • php please license completes the device-code flow and skips it when already connected or licensed.
  • site:fresh-key and site:rotate-key update .env and .env.example; rotation preserves the previous key during its grace period.
  • statamic:pro:enable points to php please license when no existing key is supplied.

jackmcdade and others added 15 commits September 1, 2026 11:10
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Skip writing STATAMIC_SITE_KEY in CI, surface cloned-key collisions, and let sites rotate with a 90-day alias via please site:rotate-key.

Co-authored-by: Cursor <cursoragent@cursor.com>
Show one primary action based on whether the site is connected, pass APP_NAME into the handoff, and refresh after returning from statamic.com so licenses attach to the right site.

Co-authored-by: Cursor <cursoragent@cursor.com>
Ping first so a connected or licensed site gets a status and a site URL instead of another claim code.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread CHANGELOG.md

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Individual PRs shouldn't update the CHANGELOG.md

@duncanmcclean duncanmcclean changed the title Site keys and a simpler licensing flow [6.x] Site keys and a simpler licensing flow Sep 3, 2026
jackmcdade and others added 6 commits September 3, 2026 09:57
Co-authored-by: Cursor <cursoragent@cursor.com>

# Conflicts:
#	CHANGELOG.md
Prefer legacy license keys over site keys, stop remote rotation, host-gate
Outpost cache invalidation, and add a fresh-key recovery path when someone
else has already linked the public site key.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep Link to Account as the rightmost primary action for unlinked sites,
hide domain errors until the site is claimed, only offer a fresh key after
a failed claim, and stop minting from a claimed .env.example key.
So the claim page can show which domain is being linked even when the
site has no authorized domains yet.
getLicenseKey() intentionally prefers STATAMIC_LICENSE_KEY over
STATAMIC_SITE_KEY; the facade test was still asserting the opposite.
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