What Rule Cascade is
One rule contract, compiled once and evaluated by the same pure function in the browser, the backend and any other language.
The problem it solves
A business rule such as "a retail transfer may not exceed 25,000 unless a risk officer accepts the risk" usually exists three times: in the form, in the API and in a batch job, each written by a different team in a different language. The copies drift. Rule Cascade keeps one copy, as data, and gives every place that must enforce it an engine that reads that data and returns the same answer.
How it works
- Write. A ruleset is a YAML or JSON document: where it sits in the organisation (
scope), what it inherits (extends), the rules, the messages users see, and golden tests. - Check. The compiler validates the document against the JSON Schema, resolves inheritance, checks every data path against your OpenAPI schema and runs the golden tests. It refuses anything that is wrong. This happens in CI.
- Seal. The result is a bundle: one immutable JSON file with a SHA-256 checksum. It holds a server manifest and a client manifest that contains only what a browser may see.
- Evaluate. An engine is a pure function,
(manifest, request) → decision, findings, effects, commands. It reads no clock, no network and no file. The browser evaluates the client manifest for immediate feedback; the server evaluates the server manifest for the decision.
A client evaluation is advice. The server decides, always.
The vocabulary
| Term | Meaning |
|---|---|
| Ruleset | The source document, YAML or JSON. Identified by metadata.id and metadata.version |
| Rule | One validation, state, compute or action rule, with a target (entity, page, screen, section, component, field, or data type) and the operations it applies to |
| Finding | What a failed validation rule produces: a stable code, a severity (info, warning, error), the field pointers, a message, whether it is blocking |
| Effect | A field state (visible, enabled, required, readOnly) or a computed value |
| Command | What an action rule asks the host to do after a successful save, with an idempotencyKey |
| Bundle | The compiled ruleset: server and client manifest, version and checksum |
| Channel | server (every rule) or client (rules with enforcement: client or both, no action rules) |
| Resolution | The user's answer to a finding: acknowledge a warning, or accept-risk on an error with a justification |
The engines
| Engine | Use it in | Page |
|---|---|---|
| TypeScript | Browsers, Node.js, React (hook), React Native | TypeScript |
| Java | Spring Boot and any JVM, Java 17+ | Java |
| Go | Go services; also the command and the WebAssembly module | Go |
| Python | Services and jobs; the reference implementation | Python |
Command rule-cascade | CI, and any language that can start a process | Command and WebAssembly |
WebAssembly rule-cascade.wasm | Any WASI preview 1 host | Command and WebAssembly |
| Rule server | Anything that speaks HTTP | Rule server |
What it guarantees
- No implicit conversion.
1is not"1";nullis notfalse. A wrong type is an evaluation error and the rule blocks. - Decimal arithmetic.
0.1 + 0.2is0.3in every engine. - Fails closed. A rule that cannot be evaluated produces a blocking
RULE-EVALUATION-ERRORfinding. It is never skipped. - Nothing ships unchecked. Unknown paths, operators and parameters, duplicate ids, illegal overrides, missing messages and failing golden tests stop the build.
- Server-only rules stay on the server. The client manifest carries no
enforcement: serverrule and no action rule.
The complete list, with the error code that enforces each item, is in the authoring guidelines; the exact semantics are in the specification.
Next
Run the quickstart: five minutes from an empty directory to an evaluated request.