Rule Cascade
Usage by language

Rule server (HTTP)

@yarlisaisolutions/rule-cascade-server: a stateless HTTP service that serves manifests and bundles and evaluates operations.

The rule server implements the evaluation API of spec/v1/rule-evaluation.openapi.yaml. Use it for callers that cannot embed a runtime. It keeps nothing between requests, so any number of replicas can run behind a load balancer.

Supported versions: Node.js 20 or later (engines), the same as the TypeScript runtime it is built on. The container image is node:22-alpine; CI builds it and smoke-tests it.

Install from the repository

git clone https://github.com/YarlisAISolutions/rule-cascade.git && cd rule-cascade
npm ci && npm run build
RULE_SERVER_TOKEN=$(openssl rand -hex 32) RULES_DIR=examples/contracts node packages/server/dist/main.js
VariableMeaningDefault
RULES_DIRDirectory with *.ruleset.yaml / .yml / .json sources (compiled at start-up) and *.bundle.json bundles./rules
PORTListen port8080
RULE_SERVER_TOKENBearer token for evaluations, the server manifest, bundles and server-only rule detailssee below
DRAIN_SECONDSTime between "not ready" and shutdown on SIGTERM5

Always set RULE_SERVER_TOKEN

POST /evaluations evaluates whatever actor the caller sends, and the server manifest and the bundle reveal server-only rules. The token is required: the server exits with status 1 at start-up without RULE_SERVER_TOKEN, unless RULE_SERVER_ALLOW_OPEN=1 is set explicitly for development on a private network. The client manifest, the ruleset list and the health probes stay public. The package README always describes the behaviour of the code it ships with.

Endpoints

Method and pathPurposeNeeds the token
GET /healthzLivenessno
GET /readyzReadiness; 503 while drainingno
GET /rulesets?scope=List rulesetsno
GET /rulesets/{id}/manifest?channel=clientClient-safe manifest, with ETagno
GET /rulesets/{id}/manifest?channel=serverFull manifest for backend runtimesyes
GET /rulesets/{id}/bundleThe compiled bundle, with ETagyes
GET /rulesets/{id}/rules/{ruleId}One resolved ruleserver-only rules: yes
POST /evaluationsEvaluate an operationyes

Evaluate

The body is the evaluation request plus ruleset, and optionally version and channel:

curl -s localhost:8080/evaluations -H "Authorization: Bearer $RULE_SERVER_TOKEN" \
  -H 'Content-Type: application/json' -d '{
  "ruleset": "acme.payments.transfer", "entity": "Transfer", "operation": "create",
  "data": {"type": "international", "amount": 500, "currency": "USD", "memo": "gift",
           "beneficiary": {"name": "X", "country": "KP", "swiftCode": "ABCDKPPY"}}}'
# {"decision":"deny","findings":[{"code":"ORG-TRF-001","message":"Transfers to KP are not permitted.", ...}], ...}

The answer is the evaluation result, with HTTP 200 whatever the decision: the caller acts on decision.

Errors

StatusWhen
400A body that is not an evaluation request; the problem document's title says what is wrong, for example 'view' must be an object
401A protected endpoint without Authorization: Bearer <token>
404An unknown ruleset or version
503 on /readyzDraining after SIGTERM
Process exits before it listensA ruleset fails a load check or a bundle is unusable

SIGHUP reloads RULES_DIR; if the new rules fail to load, the server logs the reason and keeps serving the previous ones. A ruleset that uses a custom operator is served, a warning names the missing operators, and those rules fail closed. To supply operators, embed the server with createRuleServer(store, { token, operators }).

More

The package README has the full behaviour; production deployment is the Kubernetes playbook.

Source: site/content/docs/usage/rule-server.mdx

On this page