Plugins
Build manifest-driven provider plugins and deterministic hooks.
Plugin structure
Each plugin is one direct child of plugins/ with a bounded plugin.json and entry class. Discovery rejects traversal, symlinks escaping the plugin root, malformed manifests, duplicate slugs, and entry classes loaded from another directory.
{
"slug": "example-provider",
"name": "Example Provider",
"version": "1.0.0",
"entry": "ExampleProviderPlugin.php"
}
Interface and hooks
final class ExampleProviderPlugin implements PluginInterface
{
public function register(HookRegistry $hooks): void
{
$hooks->after('video.resolved', [$this, 'decorate']);
}
}
Hooks use namespaced names, deterministic priority/insertion order, before/after semantics, and isolated failures. The registry never logs hook payloads or sensitive exception context.
Activation
Administrators rescan and activate plugins in /admin/plugins. Activation fails closed if manifest, class origin, interface, or boot checks fail. Review third-party PHP as trusted server code before activation.