Scope and levels
Where a ruleset sits in your organisation, from least to most specific.
Every ruleset has a scope: a list of {level, id} from the least to the most specific. An
organisation ruleset has one level. A project ruleset under it repeats that level and adds its own.
Level names are open; the recommended ones are enterprise, organization, businessUnit,
agency, project, application, module and feature.
Syntax
scope:
- { level: organization, id: learn }
- { level: project, id: shop }Example
org.ruleset.yaml is the organisation ruleset. The shop ruleset is one level narrower and extends
it, so the organisation's rule runs in the shop as well as the shop's own.
ruleCascade: 1.0.0
kind: RuleSet
metadata: { id: learn.shop, version: 1.0.0, title: "Shop rules" }
scope:
- { level: organization, id: learn }
- { level: project, id: shop }
extends:
- { ruleset: learn.org, version: "^1.0.0" }
rules:
- id: shop.email.required
kind: validation
target: { entity: Order, field: /email }
operations: [create]
assert: { op: exists, args: [{ var: data.email }] }
severity: error
finding: { code: LRN-SHP-001, message: shop.emailRequired }
messages:
en:
shop.emailRequired: "Give an e-mail address for the receipt."
tests:
- name: the organisation rule applies in the shop too
entity: Order
operation: create
given:
data: { quantity: 150, email: "ana@example.com" }
expect:
decision: deny
findings:
- { rule: org.quantity.max, code: LRN-ORG-001 }
- name: the shop adds its own rule
entity: Order
operation: create
given:
data: { quantity: 3 }
expect:
decision: deny
findings:
- { rule: shop.email.required }ruleCascade: 1.0.0
kind: RuleSet
metadata: { id: learn.org, version: 1.0.0, title: "Organisation rules" }
scope:
- { level: organization, id: learn }
entities:
Order:
schema: { $ref: "./learn.openapi.yaml#/components/schemas/Order" }
rules:
- id: org.quantity.max
kind: validation
target: { entity: Order, field: /quantity }
operations: [create]
assert: { op: lte, args: [{ var: data.quantity }, 100] }
severity: error
finding: { code: LRN-ORG-001, message: org.quantityMax }
messages:
en:
org.quantityMax: "No order may have more than 100 items."{
"entity": "Order",
"operation": "create",
"data": {
"quantity": 150,
"email": "ana@example.com"
}
}Result, from the engine
Decisiondeny1 finding, server channel
LRN-ORG-001errorblockingNo order may have more than 100 items./quantity
Common mistakes
- A child whose scope is not narrower than its parent's. The child must start with the parent's
scope and add at least one level. Here the shop forgot its own level, so it does not load:
SCOPE_NOT_NARROWER. Fix it by adding{ level: project, id: shop }.
ruleCascade: 1.0.0
kind: RuleSet
metadata: { id: learn.shop, version: 1.0.0, title: "Shop rules" }
scope:
- { level: organization, id: learn }
extends:
- { ruleset: learn.org, version: "^1.0.0" }
rules:
- id: shop.email.required
kind: validation
target: { entity: Order, field: /email }
operations: [create]
assert: { op: exists, args: [{ var: data.email }] }
severity: error
finding: { code: LRN-SHP-001, message: shop.emailRequired }
messages:
en:
shop.emailRequired: "Give an e-mail address for the receipt."
tests:
- name: the organisation rule applies in the shop too
entity: Order
operation: create
given:
data: { quantity: 150, email: "ana@example.com" }
expect:
decision: deny
findings:
- { rule: org.quantity.max, code: LRN-ORG-001 }
- name: the shop adds its own rule
entity: Order
operation: create
given:
data: { quantity: 3 }
expect:
decision: deny
findings:
- { rule: shop.email.required }ruleCascade: 1.0.0
kind: RuleSet
metadata: { id: learn.org, version: 1.0.0, title: "Organisation rules" }
scope:
- { level: organization, id: learn }
entities:
Order:
schema: { $ref: "./learn.openapi.yaml#/components/schemas/Order" }
rules:
- id: org.quantity.max
kind: validation
target: { entity: Order, field: /quantity }
operations: [create]
assert: { op: lte, args: [{ var: data.quantity }, 100] }
severity: error
finding: { code: LRN-ORG-001, message: org.quantityMax }
messages:
en:
org.quantityMax: "No order may have more than 100 items."{
"entity": "Order",
"operation": "create",
"data": {
"quantity": 150,
"email": "ana@example.com"
}
}Result, from the engine
does not loadThe engine refuses the ruleset before it evaluates anything.
SCOPE_NOT_NARROWERlearn.shop: scope must extend the scope of learn.org
Exercise
The checkout team owns a narrower ruleset. Add the level feature with the id checkout to the
shop ruleset's scope. The golden tests must still pass.
Hint
Add a third entry to scope; keep the first two as they are.
Show answer
ruleCascade: 1.0.0
kind: RuleSet
metadata: { id: learn.shop, version: 1.0.0, title: "Shop rules" }
scope:
- { level: organization, id: learn }
- { level: project, id: shop }
- { level: feature, id: checkout }
extends:
- { ruleset: learn.org, version: "^1.0.0" }
rules:
- id: shop.email.required
kind: validation
target: { entity: Order, field: /email }
operations: [create]
assert: { op: exists, args: [{ var: data.email }] }
severity: error
finding: { code: LRN-SHP-001, message: shop.emailRequired }
messages:
en:
shop.emailRequired: "Give an e-mail address for the receipt."
tests:
- name: the organisation rule applies in the shop too
entity: Order
operation: create
given:
data: { quantity: 150, email: "ana@example.com" }
expect:
decision: deny
findings:
- { rule: org.quantity.max, code: LRN-ORG-001 }
- name: the shop adds its own rule
entity: Order
operation: create
given:
data: { quantity: 3 }
expect:
decision: deny
findings:
- { rule: shop.email.required }ruleCascade: 1.0.0
kind: RuleSet
metadata: { id: learn.org, version: 1.0.0, title: "Organisation rules" }
scope:
- { level: organization, id: learn }
entities:
Order:
schema: { $ref: "./learn.openapi.yaml#/components/schemas/Order" }
rules:
- id: org.quantity.max
kind: validation
target: { entity: Order, field: /quantity }
operations: [create]
assert: { op: lte, args: [{ var: data.quantity }, 100] }
severity: error
finding: { code: LRN-ORG-001, message: org.quantityMax }
messages:
en:
org.quantityMax: "No order may have more than 100 items."{
"entity": "Order",
"operation": "create",
"data": {
"quantity": 150,
"email": "ana@example.com"
}
}Result, from the engine
Decisiondeny1 finding, server channel
LRN-ORG-001errorblockingNo order may have more than 100 items./quantity