Solution looks messy and bloated to me.
Service Provider, Extension... Adding more and more components, abstractions... To achieve what?
What do we want from modules?
1. Easy to install
2. Easy to customize
1 — we in 2020 have class autoloading, composer and PSR-4. There is nothing more need to do to include some third-party code in you app. "composer install" - and you have your package ready to use in any place in app )
2 — This is easily done using patterns, and OOP capabilities, already existing in core language.
Change implementation? Use interface.
Hook to event? Use Publisher/Subscriber pattern, or some other suitable pattern
Configure object dependencies? Use dependency injection
All this "we need more classes to provide modularity" comes from lack of knowledge of basic stuff. You don't need to reinvent the wheel. Just use what you have, all you actually need is already there.
Maybe this "modules standard" way was useful 10 years ago... But today it is obsolete.
Moreover, this "standard" is actually limiting your possibilities.
If we use usual ways to extend and customize code, like interfaces, dependency injection, we have access to ANY bit of logic in module, that is made replaceable.
Once module was developed with SOLID in mind, it should provide maximum flexibility. You can replace anything... And subscribe to events )
But, what happens with "Service Providers"-way? When you build module, you have to make Factories, Providers, and define set of extensible points.
Defining this set of extensible points, you tell the user: "This is what I give you, you can customize here and there, ask for no more". This is limiting!
So. For making a good, reusable, customizable module, you need:
1. Good understanding of OOP, architecture patterns
2. Basic language, tooling, framework features (interfaces, autoloading, package manager, dependency injection)
3. SOLID code
4. Well written documentation
And nothing more...