Rule Cascade
Usage by language

Go

Package rulecascade, standard library only. The same code also builds the rule-cascade command and the WebAssembly module.

The module github.com/YarlisAISolutions/rule-cascade/packages/go (package rulecascade) evaluates bundles and compiles source rulesets. The library uses the standard library only; the rule-cascade command built from the same module adds gopkg.in/yaml.v3 to read YAML. The command and the WebAssembly module have their own page.

Supported versions: Go 1.22 or later (go directive in go.mod). CI tests Go 1.24 on Linux, Windows and macOS. No maximum is declared.

Install from the repository

The module is not on a Go proxy yet. Point your module at a checkout with a replace directive:

git clone https://github.com/YarlisAISolutions/rule-cascade.git ../rule-cascade
go mod edit -require=github.com/YarlisAISolutions/rule-cascade/packages/go@v0.0.0 \
  -replace=github.com/YarlisAISolutions/rule-cascade/packages/go=../rule-cascade/packages/go
go mod tidy
import rulecascade "github.com/YarlisAISolutions/rule-cascade/packages/go"

Load

rules, err := rulecascade.FromBundle(bundle) // bundle: the parsed JSON of a *.bundle.json file
if err != nil {
	log.Fatal(err) // a *rulecascade.LoadError: do not start
}

rulecascade.ParseJSON reads a file's bytes into the values the library expects, keeping the order of object members; map[string]any from encoding/json works too. To compile source documents instead, call rulecascade.Load(document, registry, loader); a nil loader skips the checks that need the entity schemas.

Evaluate

result, err := rules.Evaluate(map[string]any{
	"entity":    "Transfer",
	"operation": "create",
	"data": map[string]any{
		"type": "international", "amount": 12000, "currency": "USD",
		"beneficiary": map[string]any{"name": "Ana", "country": "ES"},
	},
	"actor": map[string]any{"id": "u-1", "roles": []string{"teller"}},
}, "server", nil)
if err != nil {
	log.Fatal(err)
}

fmt.Println(result.Decision)
for _, f := range result.Findings {
	fmt.Println(f.Code, f.Severity, f.Fields, f.Message)
}
// deny
// ORG-TRF-003 warning [/memo] Adding a memo makes this transfer easier to reconcile.
// PAY-TRF-002 error [/beneficiary/swiftCode] A valid SWIFT/BIC code is required for international transfers.
// PAY-TRF-003 warning [/amount /beneficiary/name] This is a large transfer to Ana. Please confirm the details.

The third argument is a rulecascade.Operators map of custom operators, or nil. Evaluate is pure and a RuleSet is safe for concurrent use. result.Allowed() is the gate; Result, Finding, Effect and Command marshal to the JSON of the evaluation API with rulecascade.Marshal or encoding/json.

Errors

WhatHow it surfacesWhat to do
An unusable bundle*rulecascade.LoadError from FromBundle (BUNDLE_UNSUPPORTED, BUNDLE_INVALID)Do not start
A source ruleset that fails a check*rulecascade.LoadError from Load; Problems has Code, Rule and MessageDo not start; fix it in CI
A request of the wrong shape*rulecascade.RequestError from Evaluate, with MessageAnswer 400
A rule that cannot be evaluated, or a missing operatorNo error: a blocking RULE-EVALUATION-ERROR findingAlert on it
var malformed *rulecascade.RequestError
if errors.As(err, &malformed) {
	return 400, map[string]any{"title": malformed.Message}
}

More

The snippets come from the runnable examples in example_test.go, which CI runs. The full API, numbers and JSON values are in the package README.

Source: site/content/docs/usage/go.mdx

On this page