Repository navigation
Resolve licence decisions through the signed marketplace client - #726
Merged
Merged
Conversation
Core looked the marketplace client up under a container key nothing bound, so installed sites fell back to an unsigned request the marketplace rejects with 401. Core now depends on an ExtensionEntitlements contract with a Null default; the marketplace package binds the signed implementation. The signed client also sent no domain, which the marketplace requires, so it now sends the caller's domain or this site's host. A guard test fails on any container lookup of an unbound marketplace key.
howdu
enabled auto-merge (squash)
October 2, 2026 16:21
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.
Problem
Core resolved the marketplace client from the container under a key that nothing bound. On an installed site the lookup missed and licence decisions fell back to an unsigned request, which the marketplace rejects with 401 (it requires an instance signature). The same fallback gated on instance id and webhook secret being present in config, so a site connected only through the database never signed either. The signed client also dropped the
domainthe marketplace requires, so fixing the binding alone would have turned the 401 into a 422.Change
ExtensionEntitlementscontract (licenceDecision,verifyActivation) with aNullExtensionEntitlementsdefault, bound withbindIf.MarketplaceExtensionEntitlements, which uses the signed client and checks receipt shape before verifying the signature. The receipt-shape rules moved from Core into the marketplace implementation; the runtime gate keeps its catch-all so outcomes are unchanged.capell.marketplace.activation-verifierstring binding is removed.domain, using the caller's domain or this site's host when none is given (feedback has none).Tests
bound()of acapell.marketplace.string; shown to fail against the pre-change files.packages/marketplace/tests,packages/core/tests/Arch,packages/core/tests/Unit/PackageRegistry,packages/core/tests/Feature/Marketplace— 1017 passed. Pint, Rector, PHPStan clean on changed files. Not run: the full Core suite.Behaviour changes
With no credentials at all the error text changes from "Marketplace could not resolve this licence decision." to the client's "Marketplace instance is not registered…"; both are
RuntimeExceptions and the callers handle them as before.