Repository navigation
0.4.0
The rule engine moves from no-op stub to fully functional. Rules can
now compose triggers with When → If → Then semantics: a trigger
fires, the condition tree is evaluated, and a configurable list of
actions executes (with optional stop-on-failure).
Added
- [new] Nine built-in rule actions under
src/Actions/, all implementing
ActionInterface:send_outbound_webhook— fire an existing outbound webhook by handlecreate_entry/update_entry— Statamic entries viaStatamic\Facades\Entrycreate_form_submission—Statamic\Facades\Formsubmissiondispatch_event— generic Laravel event dispatch (FQCN or string)send_email—Mail::rawnotificationsend_slack_webhook—Http::postto Slack/Discord-compatible webhook URLsset_field_value— single-field entry update with literal or path-sourced valuewrite_log_note— structuredSystemLoggerentry
- [new]
RuleEngineis no longer a stub. LoadsRuleRepository::activeForTrigger,
evaluates each rule's condition tree viaConditionEvaluator, runs
the action chain viaActionExecutorand aggregates per-rule results
intoExecutionResults with structured action breakdowns. The engine
also exposesevaluateOne()so the CP "Test rule" path can run a
single rule against a synthetic context. - [new]
Domain\OutboundWebhook\Actions\DispatchOutboundWebhookAction— extracted
the snapshot+queue/sync logic that was private toTriggerDispatcher
so the newSendOutboundWebhookActionre-uses the same code path. - [new] Five domain actions for rule CRUD:
Create,Update,Delete,
Toggle,Test. - [new] Repository.
RuleRepository::paginate(int, ?string),find(),
findByUuid()to mirrorOutboundWebhookRepository/InboundEndpointRepository. - [new] CP CRUD.
Cp\RuleControllergrows from listing-only to full
CRUD (index/create/store/edit/update/destroy/toggle).
Cp\Actions\TestRuleControllerpowers the in-page Test panel. - [new] Routes.
routes/cp.phpadds the rules CRUD routes;
routes/actions.phpaddsactions.test-rule. - [new] i18n.
rule_*notices for CRUD success messages and
errors.rule_*for execution failures. - [new] Vue pages.
pages/rules/Index.vueis a real list view (search,
status badges, action count, order index).
Edit.vueships as a sectioned form (Identity / Trigger /
Conditions / Actions / Test) with a JSON editor for the condition
tree and the action list, plus a Test panel that runs a single
rule against a sample payload and shows the per-action outcome. - [new]
ActionRegistry::registerDefaults()— built-in actions are
resolved through the container so dependencies (repositories,
DispatchOutboundWebhookAction,SystemLogger) are wired
automatically. - [new] Tests.
tests/Unit/Rules/ConditionEvaluatorTest.php— leaf operators,
AND/OR groups, nested groups, in/not_in, contains/exists/empty,
numeric comparisons, regex, thesite/locale/trigger/replay
field shortcuts.tests/Unit/Rules/RuleEngineTest.php— disabled rules, failing
conditions, ordered action execution, unknown-handle failure,
stop-on-failure short-circuit.tests/Feature/RuleExecutesMultipleActionsTest.php— full
TriggerDispatcher → RuleEnginepath with thewrite_log_note
handler. Asserts ordering, trigger filtering, stop-on-failure,
andorder_indexordering.
Changed
Services\TriggerDispatcherno longer holds the snapshot+dispatch
logic itself — it delegates toDispatchOutboundWebhookAction.
Rules now evaluate before direct outbound resolution, so
rules can dispatch additional outbound webhooks via
send_outbound_webhookif needed. Direct-attached hooks are
unaffected (PRD §39 REVIEW: hooks remain a separate dispatch path
rather than a special-case rule).WebhookManagerServiceProvider::bootRegistries()now calls
ActionRegistry::registerDefaults().
Removed
messages.errors.rule_engine_not_implementedtranslation key — the
engine is implemented; specific error keys
(rule_unknown_action,rule_invalid_conditions) replace it.
TODO: REVIEW
- The condition / action editors are JSON-first (PRD §29 explicitly
allows this). A visual condition builder and a per-action form
generator remain v2 candidates. - Rule actions that touch Statamic facades (
create_entry,
update_entry,set_field_value,create_form_submission)
catch and surface throws but do not classify them. v2: feed into
the sameFailureClassifierthe delivery engine uses. SendEmailActionships text-only. Once the template module has a
rendering API on the public surface, accept a template handle
instead of pre-rendered body.