Rule Cascade
LearnThe process, end to end

Author a rule

Write a rule in YAML next to the schema of the data it checks, and try it before you commit anything.

A rule lives in a ruleset file, next to the schema of the data it checks. You write what must be true, how bad it is when it is not, and what the user reads. Start in the playground: it gives an answer in a second and needs nothing installed.

Hands-on

  1. Open the first rule of the course in the playground and change it until it says what you mean.

    Try it YourselfRuns in your browser with the TypeScript engine. Nothing to install.
  2. Create the project. Save the schema of the entity the rules talk about:

    orders.openapi.yaml
    openapi: 3.1.0
    info: { title: Shop orders, version: 1.0.0 }
    paths: {}
    components:
      schemas:
        Order:
          type: object
          properties:
            id: { type: string }
            quantity: { type: integer }
            country: { type: string }
            total: { type: number }
  3. Save the ruleset. It has a parameter for the limit, a validation rule that uses it, a message, and an action rule that announces a new order once it is saved:

    orders.ruleset.yaml
    ruleCascade: 1.0.0
    kind: RuleSet
    
    metadata:
      id: shop.orders
      version: 1.0.0
      title: Orders
      owner: shop-team
      status: active
    
    scope:
      - { level: organization, id: shop }
    
    entities:
      Order:
        schema: { $ref: "./orders.openapi.yaml#/components/schemas/Order" }
    
    params:
      maxQuantity:
        type: integer
        default: 10
        overridePolicy: tighten-only
        tightenDirection: lower
    
    rules:
      - id: order.quantity.max
        kind: validation
        title: An order has at most maxQuantity items
        target: { entity: Order, field: /quantity }
        operations: [create, update]
        triggers: [change, submit]
        when: { op: exists, args: [{ var: data.quantity }] }
        assert: { op: lte, args: [{ var: data.quantity }, { var: params.maxQuantity }] }
        severity: error
        finding:
          code: SHOP-ORD-001
          message: order.quantityTooHigh
          args: { max: { var: params.maxQuantity } }
    
      - id: order.placed
        kind: action
        title: Announce a new order once it is saved
        target: { entity: Order }
        operations: [create]
        enforcement: server
        commands:
          - name: order.placed
            type: event
            ref: OrderPlaced
            payload: { orderId: { var: data.id }, quantity: { var: data.quantity } }
            idempotencyKey: ["order.placed", { var: data.id }]
    
    messages:
      en:
        order.quantityTooHigh: "You can order at most {max} items."

Write the rule the way the authoring guidelines say: one check per rule, a stable finding code, a message key instead of a sentence, and a when that skips the rule when the field is absent.

Done when

  • The file has metadata.id, metadata.version and metadata.owner.
  • Every finding has a unique code and a message in the default locale.
  • The playground evaluates a request against it and shows the decision you expect.

Go deeper

Course overview

On this page