Skip to content

Add symbolic value type, resolver registry, and the in operator to the rule management component#8198

Open
kaviska wants to merge 5 commits into
wso2:masterfrom
kaviska:rule-mgt
Open

Add symbolic value type, resolver registry, and the in operator to the rule management component#8198
kaviska wants to merge 5 commits into
wso2:masterfrom
kaviska:rule-mgt

Conversation

@kaviska

@kaviska kaviska commented Jul 9, 2026

Copy link
Copy Markdown

Proposed changes in this pull request

This PR introduces a new symbolic value type (SYMBOLIC) and the in operator to the Rule Management
component (rule-mgt), together with the runtime resolver mechanism that turns a symbolic value into a
concrete value at evaluation time.

Symbolic value type

  • Add SYMBOLIC to the metadata and management value type enums, and add the DEVICE_POLICY flow type.
  • RuleBuilder resolves a symbolic field's value to the SYMBOLIC type at save time (rather than storing it
    as a plain string/number), so it can be resolved later at evaluation time.
  • FieldExtractor maps a symbolic field to a numeric evaluation type, because the live value supplied by
    the data provider is concrete (numeric) — only the stored rule value is symbolic.

Symbolic value resolver

  • Add a SymbolicValueResolver contract: Value resolve(String symbolicValue) — given a placeholder, return
    its resolved concrete value (a single NUMBER, or a LIST for comma-separated multi-values).
  • Add a singleton SymbolicValueResolverRegistry keyed by field name (register / deregister /
    getResolver), so consuming components register their resolver at bundle activation and remove it at
    deactivation. This keeps rule-mgt fully decoupled — it ships no resolvers and depends on no consuming
    component.
  • RuleEvaluator.evaluateSymbolicExpression looks up the resolver for the field, resolves the stored
    placeholder, and compares the result against the runtime value. If no resolver is registered for the field,
    it fails with a clear error instead of throwing an unchecked exception.

in operator

  • Add the in operator, which represents a multi-value (comma-separated) membership check
    (for example androidOsVersion in LATEST_ANDROID,SECOND_LATEST_ANDROID).
  • An in value is stored as a LIST, and RuleBuilder validates each token of the list against the
    field's allowed options at save time, so an invalid token is rejected early with a clear message rather than
    failing at evaluation.
  • At evaluation, numeric in checks membership against the comma-separated numbers; for symbolic fields, each
    token is resolved first and then membership is checked.

Unit tests

  • Add tests covering both the symbolic value flow and the in operator, for happy and failure paths.

Rule metadata configuration (JSON) changes

The rule metadata catalog shipped by the rule management server feature
(features/rule-mgt/.../resources/identity/rulemeta) is updated so the new type and operator are available at
runtime:

  • operators.json — add the in and greaterThanOrEquals operators.
  • flows.json — add the devicePolicy flow, listing the OS version fields
    (androidOsVersion, iosOsVersion, macosOsVersion, windowsOsVersion).
  • fields.json — add the symbolic OS version field definitions. Each field is declared with
    valueType: symbolic and an options list that contains the symbolic placeholders (for example
    LATEST_ANDROID, SECOND_LATEST_ANDROID) alongside concrete versions.

These are additive configuration changes; existing flows and fields are unaffected.

When should this PR be merged

No preconditions. The change is self-contained within rule-mgt.

Follow up actions

N/A

kaviska added 2 commits July 9, 2026 08:24
Introduce a new SYMBOLIC value type across the rule metadata, management and
evaluation modules, allowing a rule to store a placeholder value (e.g.
LATEST_ANDROID) that is resolved to a concrete value at evaluation time.

- metadata/management: add SYMBOLIC to the value type enums and the
  DEVICE_POLICY flow type; RuleBuilder resolves symbolic values and validates
  option membership per token for the 'in' operator
- evaluation: add SymbolicValueResolver contract and registry plus an
  evaluateSymbolicExpression path; FieldExtractor maps symbolic fields to a
  numeric evaluation type
- add unit tests covering symbolic and 'in' operator happy and failure paths
Add the device policy flow metadata that backs the symbolic value support in
the rule management server feature:

- operators.json: add the 'in' and 'greaterThanOrEquals' operators
- flows.json: add the devicePolicy flow (android/ios/macos/windows OS version)
- fields.json: add the symbolic OS version field definitions
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: ceda3060-ac5b-45fd-93e7-4bf138add336

📥 Commits

Reviewing files that changed from the base of the PR and between 7a2ef2f and bf08b62.

📒 Files selected for processing (1)
  • components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/api/util/RuleBuilder.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/api/util/RuleBuilder.java

📝 Walkthrough

Walkthrough

Adds DEVICE_POLICY flow types, SYMBOLIC and LIST value types, symbolic value resolver infrastructure, evaluator and RuleBuilder support for symbolic values and new operators, plus device policy metadata, flows, and tests.

Changes

Device Policy Rule Feature

Layer / File(s) Summary
DEVICE_POLICY flow type addition
.../rule.evaluation/.../FlowType.java, .../rule.management/.../FlowType.java, .../rule.metadata/.../FlowType.java
Adds DEVICE_POLICY enum constants to FlowType in evaluation, management, and metadata modules.
LIST and SYMBOLIC value type additions
.../rule.management/.../Value.java, .../rule.metadata/.../Value.java
Extends value type enums with LIST and SYMBOLIC members.
Symbolic value resolver contract and registry
.../resolver/SymbolicValueResolver.java, .../resolver/SymbolicValueResolverRegistry.java, .../SymbolicValueResolverRegistryTest.java
Adds the resolver interface, singleton registry, and registry tests for register, deregister, and lookup behavior.
Evaluator support for symbolic and in operators
FieldExtractor.java, OperatorRegistry.java, RuleEvaluationResult.java, RuleEvaluationServiceImpl.java, RuleEvaluator.java, RuleEvaluatorSymbolicTest.java, testng.xml
Adds failed-field tracking, symbolic resolution, greaterThanOrEquals and in operator handling, and evaluator tests wired into TestNG.
RuleBuilder validation for symbolic and list values
RuleBuilder.java, RuleBuilderTest.java, valid-operators.json
Raises the AND-expression limit, adds symbolic/list-aware value resolution and options validation, adds an in operator entry, and updates RuleBuilder tests.
Device policy metadata, fields, and flows configuration
rulemeta/fields.json, rulemeta/flows.json, rulemeta/operators.json
Adds device platform, security, and integrity field definitions, a devicePolicy flow field list, and operator metadata entries for greaterThanOrEquals and in.
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the feature changes, but it misses most required template sections like Purpose, Goals, Approach, tests, and security checks. Rewrite it using the repository template and fill in the missing sections, especially Purpose, Goals, Approach, User stories, Release note, Automation tests, Security checks, and Documentation.
Docstring Coverage ⚠️ Warning Docstring coverage is 4.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: symbolic values, resolver registry, and the new in operator in rule management.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@components/rule-mgt/org.wso2.carbon.identity.rule.evaluation/src/main/java/org/wso2/carbon/identity/rule/evaluation/internal/service/impl/OperatorRegistry.java`:
- Around line 48-49: The `in` operator in `OperatorRegistry` is inconsistent
with `evaluateInForNumber` because it compares raw comma-separated tokens
without trimming whitespace. Update the `supportedOperators.put("in", ...)`
predicate to trim each split value before checking containment, so
STRING/REFERENCE fields handle inputs like “Android, iOS” consistently. Use the
existing `stringPredicate` setup and keep the behavior aligned with the number
path’s token normalization.

In
`@components/rule-mgt/org.wso2.carbon.identity.rule.evaluation/src/main/java/org/wso2/carbon/identity/rule/evaluation/internal/service/impl/RuleEvaluator.java`:
- Around line 149-155: Handle parsing failures in evaluateInForNumber by
validating the commaSeparated input before splitting and by catching
NumberFormatException from Double.parseDouble, then convert those failures into
a RuleEvaluationException instead of letting them escape. Update the
evaluateInForNumber path in RuleEvaluator, and ensure callers such as
evaluateSymbolicExpression receive a handled rule-evaluation error when resolver
output is null or non-numeric.
- Around line 157-174: Validate operator and resolved-type compatibility in
evaluateSymbolicExpression before routing evaluation. In RuleEvaluator, the
current logic only branches on SymbolicValueResolver result type, which lets
NUMBER values fall through to operator.apply and LIST values always use
evaluateInForNumber regardless of the Operator. Update the method to explicitly
handle only the supported operator/type combinations (for example, use
membership logic only for in with LIST, and equality/other numeric operators
only for NUMBER), and throw RuleEvaluationException for unsupported combinations
so wrong results are not silently returned.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 5036743e-2e95-4534-a730-1f5211e3b9ed

📥 Commits

Reviewing files that changed from the base of the PR and between 40a5c43 and 5de1bc5.

📒 Files selected for processing (18)
  • components/rule-mgt/org.wso2.carbon.identity.rule.evaluation/src/main/java/org/wso2/carbon/identity/rule/evaluation/api/model/FlowType.java
  • components/rule-mgt/org.wso2.carbon.identity.rule.evaluation/src/main/java/org/wso2/carbon/identity/rule/evaluation/api/model/RuleEvaluationResult.java
  • components/rule-mgt/org.wso2.carbon.identity.rule.evaluation/src/main/java/org/wso2/carbon/identity/rule/evaluation/api/resolver/SymbolicValueResolver.java
  • components/rule-mgt/org.wso2.carbon.identity.rule.evaluation/src/main/java/org/wso2/carbon/identity/rule/evaluation/api/resolver/SymbolicValueResolverRegistry.java
  • components/rule-mgt/org.wso2.carbon.identity.rule.evaluation/src/main/java/org/wso2/carbon/identity/rule/evaluation/internal/service/impl/FieldExtractor.java
  • components/rule-mgt/org.wso2.carbon.identity.rule.evaluation/src/main/java/org/wso2/carbon/identity/rule/evaluation/internal/service/impl/OperatorRegistry.java
  • components/rule-mgt/org.wso2.carbon.identity.rule.evaluation/src/main/java/org/wso2/carbon/identity/rule/evaluation/internal/service/impl/RuleEvaluationServiceImpl.java
  • components/rule-mgt/org.wso2.carbon.identity.rule.evaluation/src/main/java/org/wso2/carbon/identity/rule/evaluation/internal/service/impl/RuleEvaluator.java
  • components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/api/model/FlowType.java
  • components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/api/model/Value.java
  • components/rule-mgt/org.wso2.carbon.identity.rule.management/src/main/java/org/wso2/carbon/identity/rule/management/api/util/RuleBuilder.java
  • components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/java/org/wso2/carbon/identity/rule/management/util/RuleBuilderTest.java
  • components/rule-mgt/org.wso2.carbon.identity.rule.management/src/test/resources/configs/valid-operators.json
  • components/rule-mgt/org.wso2.carbon.identity.rule.metadata/src/main/java/org/wso2/carbon/identity/rule/metadata/api/model/FlowType.java
  • components/rule-mgt/org.wso2.carbon.identity.rule.metadata/src/main/java/org/wso2/carbon/identity/rule/metadata/api/model/Value.java
  • features/rule-mgt/org.wso2.carbon.identity.rule.management.server.feature/resources/identity/rulemeta/fields.json
  • features/rule-mgt/org.wso2.carbon.identity.rule.management.server.feature/resources/identity/rulemeta/flows.json
  • features/rule-mgt/org.wso2.carbon.identity.rule.management.server.feature/resources/identity/rulemeta/operators.json

@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.50000% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 52.85%. Comparing base (40a5c43) to head (bf08b62).

Files with missing lines Patch % Lines
...valuation/internal/service/impl/RuleEvaluator.java 90.00% 2 Missing and 1 partial ⚠️
...ule/evaluation/api/model/RuleEvaluationResult.java 60.00% 1 Missing and 1 partial ⚠️
...uation/internal/service/impl/OperatorRegistry.java 33.33% 2 Missing ⚠️
...identity/rule/management/api/util/RuleBuilder.java 90.90% 1 Missing and 1 partial ⚠️
...aluation/internal/service/impl/FieldExtractor.java 0.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #8198      +/-   ##
============================================
+ Coverage     52.82%   52.85%   +0.02%     
+ Complexity    21345    21255      -90     
============================================
  Files          2197     2198       +1     
  Lines        131721   131828     +107     
  Branches      19936    19959      +23     
============================================
+ Hits          69587    69672      +85     
- Misses        53596    53609      +13     
- Partials       8538     8547       +9     
Flag Coverage Δ
unit 38.30% <87.50%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

kaviska added 3 commits July 9, 2026 10:07
- OperatorRegistry: trim comma-separated tokens in the 'in' operator, for
  parity with evaluateInForNumber and the save-time option validation
- RuleEvaluator: wrap numeric parsing in the 'in' evaluation so a non-numeric
  value throws a handled RuleEvaluationException instead of an uncaught
  NumberFormatException
- RuleEvaluator: route symbolic expressions by the operator (in vs equals)
  instead of the resolved value shape, fixing incorrect results for 'in' with
  a single value and 'equals' with a multi-value
- add unit tests covering the symbolic evaluation paths and the symbolic value
  resolver registry
The rule engine is generic infrastructure, so rename the 'deviceValue'
parameter of evaluateInForNumber to 'numericValue' to avoid a device-specific
name in the shared component.
…y ValueType import

- Remove the unused 2-arg resolveValue overload (dead code; the single call site
  always passes the originalValue argument to the 3-arg version)
- Import Value.ValueType and use the short name instead of the fully qualified
  name inline
@sonarqubecloud

sonarqubecloud Bot commented Jul 9, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant