Node.js example (node:http)
The payments API of backend-spring-boot, on plain node:http with the TypeScript runtime and no other dependency. It enforces payments-transfer.ruleset.yaml from its compiled bundle.
The payments API of backend-spring-boot, on plain node:http with the
TypeScript runtime and no other dependency. It enforces
payments-transfer.ruleset.yaml (examples/contracts/payments-transfer.ruleset.yaml) from its compiled bundle.
| File | What it shows |
|---|---|
src/app.mjs | The four steps on every operation: evaluate, refuse on deny with 422 problem details, persist, run commands once per idempotency key. Read rules that hide fields. The client manifest with an ETag |
src/main.mjs | Load the bundle once at startup; a bundle that cannot be read stops the process |
test/app.test.mjs | The behaviour above through real HTTP requests (node:test) |
Run it
From the repository root:
npm ci && npm run build # builds the runtime this example imports
npm test -w rule-cascade-example-backend-node
npm start -w rule-cascade-example-backend-node # listens on :8080# Allowed, with a non-blocking warning about the missing memo
curl -s localhost:8080/transfers -H 'Content-Type: application/json' -d '{
"transfer": {"type": "domestic", "amount": 120.50, "currency": "USD",
"beneficiary": {"name": "Jo Lee", "country": "US"}}}'
# Denied: 422 application/problem+json with the evaluation attached
curl -s localhost:8080/transfers -H 'Content-Type: application/json' -d '{
"transfer": {"type": "international", "amount": 500, "currency": "USD", "memo": "gift",
"beneficiary": {"name": "X", "country": "KP", "swiftCode": "ABCDKPPY"}}}'
# What a browser fetches; send the ETag back as If-None-Match to get 304
curl -si localhost:8080/rulesets/acme.payments.transfer/manifest | head -5RULES_BUNDLE points at another bundle and PORT changes the port.
Bundle or source
The service reads conformance/bundles/acme.payments.transfer.bundle.json, the compiled form of the
example contract, so it needs no YAML parser and repeats no load-time check. Compile your own with any
runtime's command, for example
rule-cascade compile examples/contracts/payments-transfer.ruleset.yaml -o transfer.bundle.json.
To compile from YAML at startup instead, use loadRuleSet with createSchemaValidator() as shown in
packages/typescript.
A bundle contains server-only rules. Serve browsers rules.manifest('client'), never the bundle.
The actor
The actor comes from the X-Actor-Id and X-Actor-Roles headers to keep the example short. A real
service takes it from its authentication layer and never trusts a role a caller claims for itself.
Go example (net/http)
The payments API of backend-spring-boot, on the standard library's net/http with the Go runtime. It enforces payments-transfer.ruleset.yaml from its compiled bundle.
Spring Boot example
A small payments API that enforces examples/contracts/payments-transfer.ruleset.yaml with the Java runtime.