SIGNALS Documentation
API Reference

Plugin Operation Registry

Contract for mapping declared plugin operation names onto invocable core action classes.

Overview

App\Sdk\Data\PluginOperationRegistry maps declared plugin operation names to invocable core action classes.

Core seeds a conservative set of low-risk actions that retain their own Gate checks. The Signals::operation() / PluginDataAccess::operation() facade never bypasses authorisation — operations run as the current authenticated user (or the ambient system/job context when no user is bound).

Manifest operations[] is a separate allow-list gate: a name must be both registered here and declared on the plugin manifest before the facade will invoke it.

Public surface

Method Purpose
register() Map one operation name to an action class string
has() Check whether an operation name is registered
get() Return the action class for a name or throw
all() Return the complete name => class-string map

Accepted registration shape

Identity is the operation name string in resource.action form (for example activities.complete).

$registry->register('activities.complete', CompleteActivity::class);

The value is a class-string for an invocable action. The registry stores the string without instantiating or runtime-checking the class; the container resolves it when PluginDataAccess invokes the operation.

register() assigns directly into an associative map. Registering another class for the same name replaces the earlier mapping; duplicate names are not rejected.

Seeded operations

The constructor currently seeds:

Operation Action class
activities.create App\Actions\Activities\CreateActivity
activities.complete App\Actions\Activities\CompleteActivity
favourites.toggle App\Actions\Favourites\ToggleFavourite

Lookup and facade gating

  • has($name) is the optional guard
  • get($name) throws App\Sdk\Data\PluginDataException with Operation [{name}] is not registered in the plugin operation registry. when missing
  • all() returns the current map in registration / replacement order

PluginDataAccess::operation($package, $action, ...$args) enforces two gates before resolution:

  1. $action must appear in the plugin's stored manifest operations[]
  2. $action must pass has() / get() on this registry

Only then does the facade resolve the action class from the container and invoke it with the supplied arguments. Authorisation remains inside the action.

Worked example

This is the current seeded lookup and invocation path:

$registry->has('activities.complete'); // true
$registry->get('activities.complete'); // CompleteActivity::class

$actionClass = $registry->get('activities.complete');
app($actionClass)($activity);

A name that is registered here but omitted from the calling plugin's manifest operations[] is still denied by the facade before get() runs for the happy path; an undeclared unknown name fails the manifest gate, while a declared but unregistered name fails with PluginDataException from get().