Light-Rule Design
Light-Rule is the local YAML rule engine used by Light-Fabric services and workflows for deterministic business checks, transformations, authorization decisions, and workflow assertions.
It complements agentic workflow by keeping critical decisions explicit, repeatable, and auditable. Agents can propose or select rules, but the rule engine executes the deterministic logic.
Purpose
Light-Rule is designed for enterprise services that need fast local policy and transformation logic without a database call on every request.
Primary uses:
- fine-grained authorization
- request transformation
- response transformation
- response row and column filtering
- workflow assertions
- business validation
- permission and filter injection
- reusable rule templates selected from Light-Portal
The rule configuration is loaded locally by the target service. When permissions or rule mappings change, the controller can trigger a config reload so the service swaps to the latest rules.
Relationship To Agentic Workflow
Agentic Workflow orchestrates process steps. Light-Rule evaluates deterministic logic inside those steps.
Workflow uses Light-Rule in two main ways:
-
Rule call task A workflow task can call a named rule to validate or mutate workflow context.
-
Assert task extension Simple checks can be handled directly by
assert, while complex business checks can delegate to Light-Rule.
This separation keeps workflows readable. The workflow says when a check happens; Light-Rule defines the reusable business logic for the check.
Example workflow responsibilities:
- decide when authorization configuration is needed
- select or create a rule
- invoke a rule during live testing
- route failures to a human or agent
Example Light-Rule responsibilities:
- evaluate role, group, position, or attribute checks
- inject endpoint permissions into the context
- compute row or column filters
- execute transformation plugins
- return pass/fail for business assertions
See Agentic Workflow Design for the workflow orchestration model.
Relationship To LightAPI
LightAPI endpoint descriptions describe endpoint invocation and expected result behavior. Light-Rule can implement complex result checks that are too business-specific for simple schema assertions.
Recommended model:
- LightAPI describes endpoint result cases and expected behavior.
- Agentic Workflow invokes the endpoint and runs
asserttasks. asserthandles simple checks directly.- Light-Rule handles complex checks, authorization logic, row filters, column filters, and reusable business policies.
See LightAPI Description Design for endpoint capability descriptions.
Rule Specification
Rules are described by the rule specification in rule-specification/schema/rule.yaml.
The top-level configuration contains:
ruleBodies: named rule definitionsendpointRules: endpoint-to-rule mappings
Each rule can contain:
ruleIdruleDescruleTypeversionauthorupdatedAtconditionsconditionLanguageconditionSecurityProfileexpressionactions
Each endpoint mapping can contain:
req-tra: request transformation rulesres-tra: response transformation rulesreq-acc: request access rulesres-fil: response filter rulesaccess-control: legacy or compatibility access control rulespermission: permission values injected into contextx-*: extension rule phases
Rule Conditions
Conditions evaluate fields in the input context.
Light-Fabric supports CEL rule conditions only. A Light-Fabric rule uses
conditionLanguage: cel and a single boolean expression, with an optional
conditionSecurityProfile.
The native condition-row format with operand, operator, expected, and
joinCode is a legacy format from the Java yaml-rule implementation. It can be
documented for migration and compatibility, but it is not supported by
Light-Fabric rule execution. Keep the detailed CEL contract in
CEL Rule Conditions; this page documents how CEL fits into the
broader Light-Rule model.
Legacy Native Conditions
Supported operand forms:
- direct field:
role - dotted path:
user.role - JSON Pointer:
/user/role - JSONPath-like path:
$.user.roles[0]
Supported operators:
==
!=
>
<
>=
<=
eq
ne
contains
matches
startsWith
endsWith
exists
notExists
expected is typed and may be a string, number, boolean, array, object, or null.
Flat condition arrays are evaluated left-to-right. joinCode combines the current condition with the previous result.
A AND B OR C
is evaluated as:
(A AND B) OR C
If explicit grouping is required, split logic into multiple rules and combine them through endpoint mapping or workflow orchestration.
These native condition rows are included here only to document the legacy Java yaml-rule shape. New Light-Fabric rules must use CEL.
CEL Conditions
CEL rules use conditionLanguage: cel and store the predicate in expression.
The expression must evaluate to a boolean. If it evaluates to false, the rule
actions do not run.
ruleBodies:
allowOfferSearch:
ruleId: allowOfferSearch
ruleType: req-acc
conditionLanguage: cel
conditionSecurityProfile: strict
expression: >
auditInfo.subject_claims.ClaimsMap.role != null
&& toolArguments.category == "travel"
actions:
- actionClassName: com.networknt.rule.RoleBasedAccessControlAction
CEL expressions should be used for rule eligibility and business predicates.
Endpoint-specific role lists, row filters, column filters, and similar policy
values should still live under permission so API owners can change policy data
without editing the reusable rule body.
CEL must not be used as a general JSON mutation language. A CEL expression can
answer whether a rule applies, or whether a specific row should be kept when an
action provides a row-scoped CEL context. It should not directly rewrite
responseBody, add or remove fields, or execute side effects.
Rule Actions
Actions execute plugin logic after conditions pass.
An action contains:
actionIdactionClassNameactionValues
actionClassName identifies the registered plugin. actionValues carries plugin-specific configuration.
Typical action plugins:
- add values to request context
- inject permission attributes
- compute filters
- transform request body
- transform response body
- call a local business function
Actions are intentionally plugin-based so the schema remains stable while implementation logic can evolve.
For response filtering, standard actions remain the transformation boundary.
ResponseRowFilterAction and ResponseColumnFilterAction own row and column
mutation, shape-specific handling, failure behavior, and audit logging. If a use
case needs richer row predicates, add a CEL-aware action such as
ResponseCelRowFilterAction that evaluates a CEL predicate for each row. Do not
expose raw response-body mutation functions to CEL.
Response filtering should parse the response JSON once for the whole res-fil
phase, pass the mutable JSON value through the ordered action pipeline, and
serialize once at the end. Individual actions should not repeatedly parse and
serialize responseBody when multiple filters are configured on the same
endpoint.
Endpoint Rule Phases
Endpoint mappings define when rules run.
Request Transformation
req-tra rules run before the service handles the request. They can enrich or transform request context.
Response Transformation
res-tra rules run after the service produces a response. They can filter, redact, or reshape response data.
Request Access
req-acc rules validate whether a request is allowed before the target handler
or backend service runs. These rules normally run in parallel because they
should not mutate shared state.
access-control can be accepted as a compatibility phase by runtimes that need
to load older configuration, but new endpoint mappings should use req-acc.
Response Filtering
res-fil rules run after the target service produces a response and before the
caller receives it. They are used for row filters, column filters, response
masking, and other response-reduction policies that should not be implemented
inside the business API.
res-fil rules always execute as a sequential pipeline in the order listed on
the endpoint. accessRuleLogic applies only to req-acc; it does not change
response-filter execution semantics.
Permission Injection
permission values are injected into the evaluation context before rule execution. This lets API owners configure roles, groups, attributes, row filters, or column filters without editing the technical rule body.
Extension Phases
Custom phases must use the x-* prefix. This avoids silent typos in standard phase names while preserving controlled extensibility.
Execution Model
The Rust implementation lives in crates/light-rule.
Core components:
RuleConfig: top-level config modelRule: rule definitionRuleCondition: condition modelRuleAction: action modelRuleEngine: evaluates one ruleActionRegistry: maps action class names to pluginsMultiThreadRuleExecutor: executes rule lists and endpoint phase mappings
Sequential phases such as req-tra and res-tra should run with all semantics so transformations happen in order.
Access control can run in parallel because it should be a validation step rather than a mutation step.
Response filtering should run sequentially when multiple filters can depend on
the same fields. For example, a row filter that checks active == true must run
before a column filter that removes the active field from the final response.
Why Not Replace With Cedar Or Casbin
Cedar and Casbin are strong policy engines, but Light-Rule has a different role in this platform.
Light-Rule supports:
- local YAML configuration
- request and response transformation
- permission injection
- row and column filters
- endpoint-specific rule selection
- technical-team-authored reusable rules
- API-owner-selected rule parameters
- config reload through controller
Cedar is excellent for authorization policy, but it does not naturally cover transformation, row filter, and column filter use cases. Casbin is strong for policy enforcement, but it introduces a different policy storage and matching model.
Light-Rule should remain the built-in rule engine for Light-Fabric service configuration and workflow assertions. External policy engines can still be integrated as action plugins if needed.
Governance
Rule bodies should be authored and reviewed like code or controlled configuration.
Recommended governance metadata:
versionauthorupdatedAtruleDesc
Recommended operational controls:
- validate rule YAML against the schema before publishing
- reject endpoint phase typos
- keep
ruleIdequal to theruleBodiesmap key - audit rule publication and reload events
- test rules with representative input contexts
- use workflow live tests to verify rules in integrated environments
Workflow Live Testing
Light-Rule is useful in live tests because it can express business checks that are more specific than generic JSON assertions.
Example flow:
- Workflow invokes an endpoint using LightAPI description.
- Workflow captures the endpoint response.
assertverifies simple fields.- A rule task validates business-specific behavior.
- On failure, workflow creates a task for a human or agent to investigate.
This keeps live test orchestration in workflow while preserving reusable business rules in Light-Rule.
Design Rule
Use workflow for process control. Use LightAPI for endpoint capability. Use Light-Rule for deterministic business logic.
Agents may select, explain, or help author rules, but the rule engine should execute the final deterministic decision.