Thoryn

Rules, programmable

Access rules. In JSON. Evaluated in a millisecond.

Policy Engine is a pure Kotlin library that evaluates JSON rule trees against a flat map of credential claims and returns ALLOW or DENY. No HTTP layer, no database, no dynamic code execution — any JVM app embeds it and calls it directly.

What Policy Engine does

Policy Engine is a library, not a service. You load a rule (JSON), parse it once into a PolicyRule object, then evaluate it against a flat claims map as many times as you like. Evaluation is deterministic, thread-safe, and fails closed. There is no expression language, no reflection, and no dynamic code execution — rules are pure data.

Flow

How an evaluation flows

  1. Step 1

    Your application loads a rule (JSON) from database, config, or REST.

  2. Step 2

    You parse it once: val rule = PolicyParser.parse(rulesJson).

  3. Step 3

    products.policyEngine.flow.s3

  4. Step 4

    You call PolicyEvaluator.evaluate(rule, facts) — thread-safe, allocation-light.

  5. Step 5

    You receive EvaluationResult(decision, reason) — ALLOW or DENY with a machine-readable reason.

Standards

What the engine supports

JSON rules (RFC 8259)

Rules are pure JSON. No expression language, no reflection. Store them anywhere JSON lives.

Operators

eq, neq, gt, gte, lt, lte, in, not_in, exists, not_exists — no regex, no wildcards.

Combinators

AND (all pass), OR (any passes), NOT (invert) — nest arbitrarily deep.

Facts map

products.policyEngine.standards.items.facts.description

Compliance

Fail-closed by default

A malformed rule, a missing fact, or an unknown operator never returns ALLOW. The engine is deterministic: same input, same decision, every time.

  • Fail-closed on malformed rules — unknown operators return DENY with a reason, not ALLOW
  • products.policyEngine.compliance.bullets.b2
  • No dynamic code execution — rules are data, never expressions
  • Thread-safe — parse once, evaluate in any thread without locks

Integration

Add the dependency. Call the function.

Import com.devnow:policy. Load your rule JSON, parse it once, build a facts map from the verified credential, call evaluate(). No Spring wiring, no HTTP client, no external process — it's a function call with deterministic output.

  • Single Maven artifact — no Spring Boot, no reflection, minimal footprint
  • Short-circuiting evaluation — AND stops on first DENY, OR stops on first ALLOW
  • Used in production inside TrustGate — same library you call is the one that runs at the door
See the rule syntax
Rule → evaluation → decision

FAQ

Frequently asked

Can I do regex or wildcard matching?
No. The engine supports exact equality, list membership, numeric comparisons, and existence checks — no regex, no wildcards. If you need regex, apply it before building the facts map. The rule engine only compares fixed values. This is deliberate: regex is a DoS surface and makes rules harder to reason about.
What if a fact is null or missing?
They behave differently. A missing key (not in the map) triggers field_missing on most operators. A null value (key present, value null) fails comparisons and triggers not_exists if checked. Be explicit in your rule: use exists or not_exists for presence; comparison operators for values.
Can I combine rules logically?
Yes. AND (all children must ALLOW), OR (at least one must ALLOW), NOT (invert one child). Rules nest arbitrarily — an AND can contain ORs, a NOT can wrap an AND. The engine short-circuits on the first failure in AND and the first success in OR.

Ready to turn policy into code?

Request access to see the library, the rule schema, and the evaluation fixtures.