A Plugin adds platform capability — a new channel adapter, a new RAG provider.
That is what separates it from a Solution, which adds
domain logic such as HR or recruitment.
The service provider
A Plugin is a Composer package whose service provider extends
Fapost\Foundation\Lifecycle\AbstractPluginServiceProvider:
onActivate() and onDeactivate() are available to hook enabling and disabling;
both are no-ops unless you override them.
The manifest
SolutionManifest is what makes a Plugin checkable at boot rather than at the
moment it breaks. requiresPlatform is a version constraint on Core;
requiresCapabilities names the platform capabilities the Plugin needs to be
present. Core validates the manifest during boot and through the platform update
lifecycle.
What you may register
Everything goes through CoreRegistrarInterface. This is the single registration
entry point.
An extension declares intent through the registrar. It must not call Route,
Schedule, or the migrator directly — the platform decides when and how those
are mounted.
Rules
Depend on public contracts, not Core internals. Everything a Plugin needs is
in fapost/foundation. A use App\… statement in a Plugin will break on a Core
refactor, and nothing in the stability promise covers it.
Do not inject Vue components into the running builder. The builder front end
is compiled before your Plugin is enabled. Make a node configurable by describing
it with a configuration schema — see Builder UI extensions.
Follow migration isolation. A Plugin migration is a DDL operation like any
other: no app(), no config(), no tenant-aware services, no reads of another
module’s tables. See Migration isolation.