Rule Types¶
Prerequisites: Concepts.
This page explains the boundary between the public Rule authoring type and
the internal EngineRule representation. Condition syntax belongs to
Conditions, and engine-mode selection belongs to
Choosing an Engine.
Public Rule¶
Rule is the public type for authoring and serialization. Its condition_dsl
tree is the source of truth for boolean logic. Set persist=False in examples
and tests to avoid writing to the configured database.
from fluxrules import Rule
rule = Rule(
name="adult",
condition_dsl={"type": "condition", "field": "age", "op": ">=", "value": 18},
actions=("allow", "audit"),
persist=False,
)
assert rule.action == "allow" # compatibility view of actions[0]
assert rule.actions == ("allow", "audit")
See Concepts and the Pydantic Rule Guide for the complete field reference.
RuleBuilder¶
RuleBuilder is a fluent adapter for workflows that assemble a rule
incrementally. Its build() method returns the public Rule, so a built rule
needs no conversion before evaluation. Use build_engine_rule() when an
internal boundary needs the EngineRule shape instead.
from fluxrules import RuleBuilder
rule = (
RuleBuilder(rule_id=1)
.name("High Value Transaction")
.group("fraud_detection")
.priority(10)
.condition({"type": "condition", "field": "amount", "op": ">", "value": 10000})
.action("flag_for_review")
.build()
)
assert rule.condition_dsl["type"] == "condition"
assert rule.domain == "fraud_detection"
engine_rule = RuleBuilder(rule_id=2).name("internal").condition(
{"type": "condition", "field": "amount", "op": ">", "value": 1}
).action("flag").build_engine_rule()
assert engine_rule.condition_dsl["type"] == "condition"
Implementation: src/fluxrules/domain/rule_builder.py.
Internal EngineRule¶
EngineRule is immutable and is used by the reference evaluator, persistence
adapters, and internal services. Its authoritative logic is always the full
condition_dsl tree. Its .conditions member is a derived flat leaf view for
compatibility; it cannot preserve OR, NOT, or nesting and must not be used
to rebuild rule logic.
Convert explicitly at an internal integration boundary:
from fluxrules import Rule
rule = Rule(
name="adult",
condition_dsl={"type": "condition", "field": "age", "op": ">=", "value": 18},
action="allow",
persist=False,
)
engine_rule = rule.to_engine_rule()
round_tripped = Rule.from_engine_rule(engine_rule, persist=False)
assert round_tripped.condition_dsl == rule.condition_dsl
Implementation: src/fluxrules/domain/models.py; conversion methods:
src/fluxrules/domain/unified_rule.py.
Engine Input Contracts¶
| API | Accepted input | Output or behavior |
|---|---|---|
PhreakEngine.load_rules(rules) |
Public Rule objects or rule dictionaries |
Loads rules for stateless or streaming PHREAK evaluation |
ReferenceEvaluator.evaluate(ruleset, facts) |
A Ruleset containing EngineRule objects |
Returns EvaluationResult with fired_rules and ordered actions |
fluxrules.evaluate(rules, facts) |
A Rule, an iterable of rules, or a Ruleset |
Returns EvaluationResult with fired_rules and ordered actions |
Rule.to_engine_rule() |
One public Rule |
Produces the immutable internal representation |
Rule.from_engine_rule(engine_rule) |
One EngineRule |
Produces a public Rule; persistence is disabled by default |
For normal application code, create Rule objects and pass them to
PhreakEngine.load_rules(). Use EngineRule and ReferenceEvaluator at
internal adapter, persistence, or parity-test boundaries.