LearnIntroduction
Your first rule in 2 minutes
Write one validation rule, send one request, read the decision.
A ruleset is a YAML file. It names the data it checks and holds rules. A validation rule checks
one thing. When its assert is false, the engine reports a finding, and an error finding
denies the request.
Syntax
- id: <rule id>
kind: validation
target: { entity: <Entity>, field: /<field> }
operations: [create]
assert: <expression that must be true>
severity: error
finding: { code: <CODE>, message: <message key> }Example
This rule allows at most 10 items per order. The request orders 11.
ruleCascade: 1.0.0
kind: RuleSet
metadata: { id: learn.first-rule, version: 1.0.0, title: My first rule }
scope:
- { level: organization, id: learn }
entities:
Order:
schema: { $ref: "./learn.openapi.yaml#/components/schemas/Order" }
rules:
- id: order.quantity.max
kind: validation
target: { entity: Order, field: /quantity }
operations: [create]
assert: { op: lte, args: [{ var: data.quantity }, 10] }
severity: error
finding: { code: LRN-ORD-001, message: order.tooMany }
messages:
en:
order.tooMany: "You can order at most 10 items."
tests:
- name: eleven items are denied
entity: Order
operation: create
given:
data: { quantity: 11 }
expect:
decision: deny
findings:
- { rule: order.quantity.max, fields: [/quantity] }
- name: ten items are allowed
entity: Order
operation: create
given:
data: { quantity: 10 }
expect: { decision: allow, findings: [] }The entity schema, learn.openapi.yaml (the same for every lesson)
openapi: 3.1.0
info: { title: Learn Rule Cascade, version: 1.0.0 }
paths: {}
components:
schemas:
Order:
type: object
properties:
id: { type: string }
quantity: { type: integer }
price: { type: number }
total: { type: number }
discount: { type: number }
shipping: { type: number }
coupon: { type: string }
email: { type: string }
country: { type: string }
status: { type: string }
express: { type: boolean }
giftWrap: { type: boolean }
giftMessage: { type: string }
notes: { type: string }
reference: { type: string }
orderDate: { type: string }
deliveryDate: { type: string }
paymentMethod: { type: string }
cardNumber: { type: string }
currency: { type: string }
weight: { type: number }
priority: { type: integer }
approved: { type: boolean }
cancelReason: { type: string }
promoCodes: { type: array, items: { type: string } }
scores: { type: array, items: { type: number } }
tags: { type: array, items: { type: string } }
items:
type: array
items:
type: object
properties:
sku: { type: string }
qty: { type: integer }
price: { type: number }
Customer:
type: object
properties:
id: { type: string }
name: { type: string }
nickname: { type: string }
email: { type: string }
backupEmail: { type: string }
phone: { type: string }
country: { type: string }
dateOfBirth: { type: string }
vatId: { type: string }
company: { type: string }
accountType: { type: string }
newsletter: { type: boolean }
tier: { type: string }
age: { type: integer }
website: { type: string }
postcode: { type: string }
username: { type: string }
iban: { type: string }
bio: { type: string }
signupDate: { type: string }
lastLogin: { type: string }
creditLimit: { type: number }
balance: { type: number }
verified: { type: boolean }
roles: { type: array, items: { type: string } }
address:
type: object
properties:
street: { type: string }
city: { type: string }
postcode: { type: string }
country: { type: string }
contacts:
type: array
items:
type: object
properties:
name: { type: string }
email: { type: string }
phone: { type: string }
Ticket:
type: object
properties:
id: { type: string }
title: { type: string }
description: { type: string }
status: { type: string }
priority: { type: string }
assignee: { type: string }
reporter: { type: string }
dueDate: { type: string }
createdAt: { type: string }
closedAt: { type: string }
resolution: { type: string }
estimate: { type: number }
labels: { type: array, items: { type: string } }{
"entity": "Order",
"operation": "create",
"data": {
"quantity": 11
}
}Result, from the engine
Decisiondeny1 finding, server channel
LRN-ORD-001errorblockingYou can order at most 10 items./quantity
Try it YourselfOpens this ruleset and request in the playground. Nothing to install.
Exercise
Change the rule so that an order may have at most 5 items. Check it with a request of 6 items.
Hint
Change the number 10 in the assert and in the message. Then change the request.
Show answer
ruleCascade: 1.0.0
kind: RuleSet
metadata: { id: learn.first-rule, version: 1.0.0, title: My first rule }
scope:
- { level: organization, id: learn }
entities:
Order:
schema: { $ref: "./learn.openapi.yaml#/components/schemas/Order" }
rules:
- id: order.quantity.max
kind: validation
target: { entity: Order, field: /quantity }
operations: [create]
assert: { op: lte, args: [{ var: data.quantity }, 5] }
severity: error
finding: { code: LRN-ORD-001, message: order.tooMany }
messages:
en:
order.tooMany: "You can order at most 5 items."
tests:
- name: six items are denied
entity: Order
operation: create
given:
data: { quantity: 6 }
expect:
decision: deny
findings:
- { rule: order.quantity.max, message: You can order at most 5 items. }
- name: five items are allowed
entity: Order
operation: create
given:
data: { quantity: 5 }
expect: { decision: allow, findings: [] }{
"entity": "Order",
"operation": "create",
"data": {
"quantity": 6
}
}Result, from the engine
Decisiondeny1 finding, server channel
LRN-ORD-001errorblockingYou can order at most 5 items./quantity