[3.0] Lets mods declare the services they use, and admins withdraw them - #9701
Open
albertlast wants to merge 1 commit into
Open
albertlast wants to merge 1 commit into
albertlast wants to merge 1 commit into
Conversation
A package says in its package-info.xml which services it provides and which it wants to use. The package manager shows those declarations among the install actions and records them when the package is installed, so Package Manager > Service Access can list what every installed mod does with services and take that access away again without uninstalling anything. Each package's factories are handed an accessor limited to what the package declared, so asking for anything else fails where it happens and says which package asked. Which container does the work stays inside SMF\Infrastructure: everything else is given has() and get(). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Mathias Albert <mathiaspapealbert@hotmail.com>
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.
Description
An alternative to #9695, weighted towards the administrator rather than towards how the code reads. Same goals — mods can register services, the container stays an implementation detail — but arrived at from the other end: what does the person running the forum see, and what can they do about it?
The difference in one line: a mod declares its services in
package-info.xmlinstead of registering them through a runtime hook. Everything admin-facing follows from that, because SMF then knows which package every service belongs to, which a hook can never tell it.What that gives the admin:
How it works
SMF\Infrastructure\Servicesis the whole API a package sees:has()andget(). It holds the grants for one consumer, and League's exceptions are translated into SMF's own on the way out, so nothing outsideSMF\Infrastructurelearns which container is in use.SMF\Infrastructure\ServiceRegistrybuilds the container: SMF's own services fromServicesList.php, then each granted package's. Later registrations of an ID that is taken are refused and logged, rather than a package quietly replacing a service other code is already using.SMF\Infrastructure\PackageServiceskeeps what each package declared, written by the package manager at install and removed at uninstall.$this. A mod can then write its factory as any callable, including a static one, whichClosure::bind()cannot do.What this does not do
It is a declaration, not a sandbox, and the admin page says so. A mod that runs in the same PHP process can still call
Db::$dbdirectly or readSettings.php. What this gives an honest mod is a way to state what it works with, and the admin a way to see and withdraw it. Claiming more than that would be misleading, which is why the wording on the page is "This describes what a modification asks for; it does not stop a badly behaved one from reaching the forum in other ways."Nothing in core consumes services yet.
ErrorHandlerServiceis still reached the old way. The consumption path — injecting services into actions — is what #9695 is designing, and it fits on top of this: resolve throughServiceRegistry::services()instead of a bare container. The gate is worth landing before the way in, rather than after mods depend on ungated access.Testing
Unit tests cover the access model: a granted service is handed over, an ungranted one is refused with the package named, an ungranted service reports as absent rather than as present-but-refused (so a package cannot probe for what else is installed), SMF's own accessor reaches everything, and a missing service throws SMF's exception rather than League's. Plus the manifest reading, including a mangled setting leaving everything without access.
Verified in the Docker environment with a real package built for the purpose, installed and uninstalled through the Package Manager over HTTP:
log_errors.Issues References (Fixes|Related|Closes)
Related: #9695
🤖 Generated with Claude Code