Rules
Rules are event-driven automation components that react to system events in Hantera. They enable you to validate state changes, enforce business logic, and trigger automated workflows.
What are Rules?
A rule is a component that executes when specific events occur in the system. Rules can:
- Validate operations before they complete (prevent invalid states)
- Automate workflows when entities change
- Enforce business logic across the platform
- Integrate with external systems via effects
Unlike Jobs which are time-triggered, rules are event-triggered - they run automatically when specific system events occur.
INFO
Current Focus: Available hooks currently focus on actor lifecycle events (order created, payment captured, etc.). The rule system is extensible and may support additional event types in the future, such as file operations, registry changes, and other resource events.
How Rules Work
Rules follow a three-step pattern:
- Hook Triggers: A system event occurs (e.g., order created)
- Component Evaluates: Rule component receives event data and evaluates conditions
- Effects Execute: Component returns effects to execute (commands, validations, integrations)
INFO
Rules use components with the rule runtime, which has more capabilities than the discount runtime but less than the reactor runtime. See Runtime Reference for details on what's available.
Simple Example: Order Confirmation Email
Here's a complete example that sends an email when an order is created:
Create the rule component:
filtrera//order-confirmation.hrule import 'resources' // 'input' is a special parameter and the designated type determines when/if the rule will evaluate: param input: OnOrderCreated let customerEmail = input.order.invoiceAddress.email from customerEmail match /@/ |> { effect = 'sendEmail' to = email subject = $'Order #{input.order.orderNumber} Confirmed' body = { html = $'<h1>Thank you for your order!</h1><p>Order number: {input.order.orderNumber}</p>' } category = 'order_confirmation' dynamic = { orderId = input.order.orderId } } ]Deploy via manifest:
yamluri: /resources/rules/order-confirmation spec: codeFile: order-confirmation.hruleApply the manifest:
bashh_ manage apply h_manifest.yaml
Now every time an order is created, the customer receives a confirmation email automatically.
Rule Hooks
Rules respond to actor lifecycle events called hooks. Hooks are categorized by timing and actor type:
Hook Timing
Before Hooks (OnXxxBeforeCreated, OnXxxBeforeDeleted):
- Execute before the operation completes
- Can prevent the operation with validation errors
- Changes aren't yet persisted
After Hooks (OnXxxCreated, OnXxxDeleted):
- Execute after the operation completes
- Changes are persisted
- Can trigger side effects and automation
Command Hooks (OnXxxCommands):
- Execute when commands are applied
- Can add additional commands
- Useful for cascading logic
Available Hooks
Currently available hooks focus on actor lifecycle events:
- Order: 6 hooks (BeforeCreated, Created, BeforeDeleted, Deleted, Commands, Journal)
- Payment: 7 hooks (BeforeCreated, Created, BeforeDeleted, Deleted, Commands, Capture, Journal)
- Ticket: 8 hooks (BeforeCreated, Created, BeforeDeleted, Deleted, Commands, Complete, Rejected)
- Sku: 5 hooks (BeforeCreated, Created, BeforeDeleted, Deleted, Commands)
- Asset: 5 hooks (BeforeCreated, Created, BeforeDeleted, Deleted, Commands)
Additional hooks for other resource types (files, registry, etc.) may be added in the future.
Rule Effects
Rules return effects - instructions for what should happen.
WARNING
Effect Availability: Not all effects work in all hooks. Before hooks typically support validation and commands, while after hooks support broader effects like messageActor and scheduleJob. Check individual hook documentation in the Runtime Reference to see which effects are supported in each context.
Effects include:
Actor Commands
Apply commands to actors:
orderCommand- Modify orderspaymentCommand- Modify paymentsticketCommand- Modify ticketsskuCommand- Modify SKUsassetCommand- Modify assets
System Operations
messageActor- Send messages to other actorsscheduleJob- Schedule background jobs
Validation
validationError- Prevent operation and return error
Common Use Cases
Validation Rules
Prevent invalid state changes:
import 'iterators'
param input: OnOrderBeforeCreated
let hasItems =
input.order.deliveries
select d => d.orderLines
flatten
count > 0
from hasItems match
false |> {
effect = 'validationError'
code = 'EMPTY_ORDER'
message = 'Orders must have at least one item'
}Automation Rules
Trigger workflows automatically:
param input: OnPaymentCapture
from input.paymentCapture.capturedAmount > 10000 match
true |> {
effect = 'messageActor'
actorType = 'ticket'
actorId = 'new'
messages = [{
type = 'create'
commands = [{
type = 'setDynamicFields',
fields = {
title = 'Large Payment Review'
description = $'Payment {input.payment.paymentNumber} for {input.paymentCapture.capturedAmount} needs review'
paymentId = input.payment.paymentId
}
}]
}]
}Integration Rules
Sync with external systems:
param input: OnOrderCreated
from [{
effect = 'scheduleJob'
definition = 'sync-to-erp'
at = datetime.now addMinutes 5
parameters = {
orderId = order.id
}
}]Multiple Effects
Rules can return multiple effects as an array:
param input: OnOrderCreated
from {
effect = 'orderCommand'
type = 'createComputedOrderDiscount'
componentId = 'free-shipping'
description = 'Free Shipping'
parameters = { threshold = '500' }
}
from {
effect = 'sendEmail'
to = order.customer.email
subject = 'Order Confirmed'
body = { html = '<h1>Thank you!</h1>' }
dynamic = {}
}All effects execute in the order specified.
Access Control
Managing rule resources requires standard permissions:
rules:read # View rule configurations
rules:write # Create, update, and delete rulesRules inherit the execution permissions of the system - they run with elevated privileges to enforce business logic across the platform.
Best Practices
1. Use Before Hooks for Validation
Prevent invalid operations with before hooks:
hook OnOrderBeforeCreated
from validateOrder(order) match
Error |> [{ effect = 'validationError', code = error.code, message = error.message }]
|> []2. Use After Hooks for Automation
Trigger workflows after successful operations:
hook OnOrderCreated
from [
{ effect = 'sendEmail', ... },
{ effect = 'scheduleJob', ... }
]3. Handle Missing Data Gracefully
Always handle optional data:
from input.order.invoiceAddress.email match
email |> { effect = 'sendEmail', to = email, ... }
// Default case returns nothingSee Also
- Components - Learn about components and runtimes
- Rule Hooks - Available lifecycle hooks
- Rule Effects - Available effects
- Common Patterns - Recipe-style examples
- Runtime Reference - Detailed runtime documentation