# @suaveplan/rules - Rule engine and validation system — async evaluator, fluent builder, 30 operators, schema/field/custom validators, serializer, optimizer; Zod boundaries, OTel surface, AbortSignal throughout ## Summary Universal rule engine + validation system. Comprehensive `RuleEngine` with async evaluation, depth limit, AbortSignal, plugin registration; fluent `RuleBuilder` + factory functions; 33-operator `OperatorRegistry`; three validator families (`SchemaValidator`, `FieldValidator`, `CustomValidator`); JSON serializer with function-placeholder strategy; AST optimiser (flatten / dedupe / simplify / sort); action subsystem with timeout + abort; typed event bus with priority hooks + bounded history. Zod boundaries at every public surface; OTel spans + histograms + counters from production paths; `RulesError` extends `SuaveplanError` with a 24-code registry. ## Documentation tree - [actions](./src/actions/actions.md) — _(no submodules)_ - [actions](./src/actions/actions.md) — _(no submodules)_ - [builder](./src/builder/builder.md) — _(no submodules)_ - [builder](./src/builder/builder.md) — _(no submodules)_ - [context](./src/context/context.md) — _(no submodules)_ - [context](./src/context/context.md) — _(no submodules)_ - [engine](./src/engine/engine.md) — _(no submodules)_ - operators-internal — `compareValues(actual, operato… - [engine](./src/engine/engine.md) — _(no submodules)_ - operators-internal — `compareValues(actual, operato… - [operators-internal](./src/engine/operators-internal.md) — `compareValues(actual, operator, expected)` is the built-in comparison dispatcher used by `RuleEngine` until the dedica… - [errors](./src/errors/rules-error.md) — _(no submodules)_ - [rules-error](./src/errors/rules-error.md) — _(no submodules)_ - [events](./src/events/event-bus.md) — _(no submodules)_ - [event-bus](./src/events/event-bus.md) — _(no submodules)_ - [operators](./src/operators/operators.md) — _(no submodules)_ - [operators](./src/operators/operators.md) — _(no submodules)_ - [optimizer](./src/optimizer/optimizer.md) — _(no submodules)_ - [optimizer](./src/optimizer/optimizer.md) — _(no submodules)_ - [otel](./src/otel/otel.md) — _(no submodules)_ - [otel](./src/otel/otel.md) — _(no submodules)_ - [serializer](./src/serializer/serializer.md) — _(no submodules)_ - [serializer](./src/serializer/serializer.md) — _(no submodules)_ - [custom](./src/validators/custom/custom.md) — _(no submodules)_ - [custom](./src/validators/custom/custom.md) — _(no submodules)_ - [field](./src/validators/field/field.md) — _(no submodules)_ - [field](./src/validators/field/field.md) — _(no submodules)_ - [schema](./src/validators/schema/schema.md) — _(no submodules)_ - [schema](./src/validators/schema/schema.md) — _(no submodules)_ - [constants](./src/constants.md) — This module exposes the package-level constants consumed across the rules engine, validators, action executor, and even… - [actions](./src/actions/actions.md) — _(no submodules)_- [builder](./src/builder/builder.md) — _(no submodules)_- [builder](./src/builder/builder.md) — _(no submodules)_- [context](./src/context/context.md) — _(no submodules)_- [context](./src/context/context.md) — _(no submodules)_- [engine](./src/engine/engine.md) — _(no submodules)_- operators-internal — `compareValues(actual, operato… - [engine](./src/engine/engine.md) — _(no submodules)_- operators-internal — `compareValues(actual, operato… - [operators-internal](./src/engine/operators-internal.md) — `compareValues(actual, operator, expected)` is the built-in comparison dispatcher used by `RuleEngine` until the dedica… - [errors](./src/errors/rules-error.md) — _(no submodules)_- [rules-error](./src/errors/rules-error.md) — _(no submodules)_- [events](./src/events/event-bus.md) — _(no submodules)_- [event-bus](./src/events/event-bus.md) — _(no submodules)_- [operators](./src/operators/operators.md) — _(no submodules)_- [operators](./src/operators/operators.md) — _(no submodules)_- [optimizer](./src/optimizer/optimizer.md) — _(no submodules)_- [optimizer](./src/optimizer/optimizer.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [serializer](./src/serializer/serializer.md) — _(no submodules)_- [serializer](./src/serializer/serializer.md) — _(no submodules)_- [custom](./src/validators/custom/custom.md) — _(no submodules)_- [custom](./src/validators/custom/custom.md) — _(no submodules)_- [field](./src/validators/field/field.md) — _(no submodules)_- [field](./src/validators/field/field.md) — _(no submodules)_- [schema](./src/validators/schema/schema.md) — _(no submodules)_- [schema](./src/validators/schema/schema.md) — _(no submodules)_- [constants](./src/constants.md) — This module exposes the package-level constants consumed across the rules engine, validators, action executor, and even… - [actions](./src/actions/actions.md) — _(no submodules)_- [builder](./src/builder/builder.md) — _(no submodules)_- [builder](./src/builder/builder.md) — _(no submodules)_- [context](./src/context/context.md) — _(no submodules)_- [context](./src/context/context.md) — _(no submodules)_- [engine](./src/engine/engine.md) — _(no submodules)_- operators-internal — `compareValues(actual, operato… - [engine](./src/engine/engine.md) — _(no submodules)_- operators-internal — `compareValues(actual, operato… - [operators-internal](./src/engine/operators-internal.md) — `compareValues(actual, operator, expected)` is the built-in comparison dispatcher used by `RuleEngine` until the dedica… - [errors](./src/errors/rules-error.md) — _(no submodules)_- [rules-error](./src/errors/rules-error.md) — _(no submodules)_- [events](./src/events/event-bus.md) — _(no submodules)_- [event-bus](./src/events/event-bus.md) — _(no submodules)_- [operators](./src/operators/operators.md) — _(no submodules)_- [operators](./src/operators/operators.md) — _(no submodules)_- [optimizer](./src/optimizer/optimizer.md) — _(no submodules)_- [optimizer](./src/optimizer/optimizer.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [serializer](./src/serializer/serializer.md) — _(no submodules)_- [serializer](./src/serializer/serializer.md) — _(no submodules)_- [custom](./src/validators/custom/custom.md) — _(no submodules)_- [custom](./src/validators/custom/custom.md) — _(no submodules)_- [field](./src/validators/field/field.md) — _(no submodules)_- [field](./src/validators/field/field.md) — _(no submodules)_- [schema](./src/validators/schema/schema.md) — _(no submodules)_- [schema](./src/validators/schema/schema.md) — _(no submodules)_- [constants](./src/constants.md) — This module exposes the package-level constants consumed across the rules engine, validators, action executor, and even… - [actions](./src/actions/actions.md) — _(no submodules)_- [builder](./src/builder/builder.md) — _(no submodules)_- [builder](./src/builder/builder.md) — _(no submodules)_- [context](./src/context/context.md) — _(no submodules)_- [context](./src/context/context.md) — _(no submodules)_- [engine](./src/engine/engine.md) — _(no submodules)_- operators-internal — `compareValues(actual, operato… - [engine](./src/engine/engine.md) — _(no submodules)_- operators-internal — `compareValues(actual, operato… - [operators-internal](./src/engine/operators-internal.md) — `compareValues(actual, operator, expected)` is the built-in comparison dispatcher used by `RuleEngine` until the dedica… - [errors](./src/errors/rules-error.md) — _(no submodules)_- [rules-error](./src/errors/rules-error.md) — _(no submodules)_- [events](./src/events/event-bus.md) — _(no submodules)_- [event-bus](./src/events/event-bus.md) — _(no submodules)_- [operators](./src/operators/operators.md) — _(no submodules)_- [operators](./src/operators/operators.md) — _(no submodules)_- [optimizer](./src/optimizer/optimizer.md) — _(no submodules)_- [optimizer](./src/optimizer/optimizer.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [serializer](./src/serializer/serializer.md) — _(no submodules)_- [serializer](./src/serializer/serializer.md) — _(no submodules)_- [custom](./src/validators/custom/custom.md) — _(no submodules)_- [custom](./src/validators/custom/custom.md) — _(no submodules)_- [field](./src/validators/field/field.md) — _(no submodules)_- [field](./src/validators/field/field.md) — _(no submodules)_- [schema](./src/validators/schema/schema.md) — _(no submodules)_- [schema](./src/validators/schema/schema.md) — _(no submodules)_- [constants](./src/constants.md) — This module exposes the package-level constants consumed across the rules engine, validators, action executor, and even… - [actions](./src/actions/actions.md) — _(no submodules)_- [builder](./src/builder/builder.md) — _(no submodules)_ - [builder](./src/builder/builder.md) — _(no submodules)_- [context](./src/context/context.md) — _(no submodules)_ - [context](./src/context/context.md) — _(no submodules)_- [engine](./src/engine/engine.md) — _(no submodules)_ - [engine](./src/engine/engine.md) — _(no submodules)_ - [operators-internal](./src/engine/operators-internal.md) — `compareValues(actual, operator, expected)` is the built-in comparison dispatcher used by `RuleEngine` until the dedica… - [errors](./src/errors/rules-error.md) — _(no submodules)_ - [rules-error](./src/errors/rules-error.md) — _(no submodules)_- [events](./src/events/event-bus.md) — _(no submodules)_ - [event-bus](./src/events/event-bus.md) — _(no submodules)_- [operators](./src/operators/operators.md) — _(no submodules)_ - [operators](./src/operators/operators.md) — _(no submodules)_- [optimizer](./src/optimizer/optimizer.md) — _(no submodules)_ - [optimizer](./src/optimizer/optimizer.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_ - [otel](./src/otel/otel.md) — _(no submodules)_- [serializer](./src/serializer/serializer.md) — _(no submodules)_ - [serializer](./src/serializer/serializer.md) — _(no submodules)_- [custom](./src/validators/custom/custom.md) — _(no submodules)_ - [custom](./src/validators/custom/custom.md) — _(no submodules)_- [field](./src/validators/field/field.md) — _(no submodules)_ - [field](./src/validators/field/field.md) — _(no submodules)_- [schema](./src/validators/schema/schema.md) — _(no submodules)_ - [schema](./src/validators/schema/schema.md) — _(no submodules)_- [constants](./src/constants.md) — This module exposes the package-level constants consumed across the rules engine, validators, action executor, and even… ## Install ```bash bun add @suaveplan/rules ``` ## Quick start ```ts import { context } from "@suaveplan/rules/context"; import { rule } from "@suaveplan/rules/builder"; import { RuleEngine } from "@suaveplan/rules/engine"; const policy = rule() .field("age").greaterThanOrEqual(18) .and() .field("region").in(["US", "CA"]) .build(); const engine = new RuleEngine(); const result = await engine.evaluate(policy, context({ age: 21, region: "US" })); // result.passed === true ``` ## Modules - [`context`](src/context/context.md) — `RuleContext` builder, dot-path / array-index field resolver, request-context derivation - [`builder`](src/builder/builder.md) — `RuleBuilder` + `FieldBuilder` fluent DSL + factory functions - [`engine`](src/engine/engine.md) — `RuleEngine` with evaluate / evaluateAll / evaluateRuleset / check + plugin registration - [`operators`](src/operators/operators.md) — `OperatorRegistry` + 33 built-in operator definitions - [`actions`](src/actions/actions.md) — `Action` / `ActionRegistry` / `ActionExecutor` + 4 built-in handlers - [`events`](src/events/event-bus.md) — `EventBus` + `HookManager` with priority hooks and `waitFor` - [`validators/schema`](src/validators/schema/schema.md) — recursive JSON-schema-like validator - [`validators/field`](src/validators/field/field.md) — chainable field validator with 12 presets - [`validators/custom`](src/validators/custom/custom.md) — named validators + registry + 11 built-ins + 5 parameterised factories - [`serializer`](src/serializer/serializer.md) — round-trip JSON with function-placeholder strategy - [`optimizer`](src/optimizer/optimizer.md) — AST optimiser (flatten / dedupe / simplify / sort) + analytics - [`errors`](src/errors/rules-error.md) — `RulesError` + 24-code registry - [`otel`](src/otel/otel.md) — lazy OTel instrument surface - Constants — [`constants.md`](src/constants.md) ## Internal references - [Engine internal compare dispatcher](src/engine/operators-internal.md) — bridges into the operator surface - [Type guards](src/types/) — `isConditionRule`, `isLogicalRule`, `isGroupRule`, `isCustomRule`, `isComputedRule` ## Conventions - Every public method validates input via Zod and raises `RulesError` with a typed code on rejection. - `AbortSignal` is threaded through every async path; pre-aborted signals short-circuit before work begins. - `Clock` / `Rng` / `LoggerLike` are injectable per CLAUDE.md "no module-scope `Date.now`/`Math.random`" rule. - 100% test coverage; sibling `.md` per implementation file ≥ 200 words. - Tests import runner primitives from `@suaveplan/testing/runner` exclusively (no direct `vitest` / `bun:test`). - No `export *` in feature barrels — every public symbol is named explicitly. ## See also - [`@suaveplan/rules-hono`](../rules-hono/README.md) — Hono middleware wrapping this package.