Constraints
Rules that policies enforce
Constraints
In guardrail-sim, constraints are implemented as policy rules using json-rules-engine. Each rule defines conditions that must be satisfied for a discount to be approved.
Default Constraints
The default policy includes these constraint rules:
Margin Floor
Ensures minimum margin is maintained after discount.
{
name: 'margin_floor',
conditions: {
all: [{
fact: 'calculated_margin',
operator: 'lessThan',
value: 0.15 // 15% minimum margin
}]
},
event: {
type: 'violation',
params: { message: 'Margin falls below 15% floor' }
}
}Maximum Discount
Caps the total discount percentage.
{
name: 'max_discount',
conditions: {
all: [{
fact: 'proposed_discount',
operator: 'greaterThan',
value: 0.25 // 25% maximum
}]
},
event: {
type: 'violation',
params: { message: 'Discount cannot exceed 25%' }
}
}Volume Tier
Requires minimum quantity for larger discounts.
{
name: 'volume_tier',
conditions: {
all: [
{ fact: 'quantity', operator: 'lessThan', value: 100 },
{ fact: 'proposed_discount', operator: 'greaterThan', value: 0.10 }
]
},
event: {
type: 'violation',
params: { message: 'Discount >10% requires quantity >= 100' }
}
}Creating Custom Constraints
Add new constraint rules to your policy:
import type { PolicyRule } from '@guardrail-sim/policy-engine';
// Customer segment constraint
const goldOnlyRule: PolicyRule = {
name: 'gold_tier_discount',
conditions: {
all: [
{ fact: 'proposed_discount', operator: 'greaterThan', value: 0.15 },
{ fact: 'customer_segment', operator: 'notEqual', value: 'gold' },
],
},
event: {
type: 'violation',
params: { message: 'Discounts over 15% require Gold tier' },
},
};Condition Logic
ALL Conditions (AND)
All conditions must be true for the rule to trigger:
const conditionConfig = {
conditions: {
all: [
{ fact: 'quantity', operator: 'lessThan', value: 50 },
{ fact: 'proposed_discount', operator: 'greaterThan', value: 0.2 },
],
},
};
// Triggers only if quantity < 50 AND discount > 20%ANY Conditions (OR)
At least one condition must be true:
const conditionConfig = {
conditions: {
any: [
{ fact: 'customer_segment', operator: 'equal', value: 'new' },
{ fact: 'quantity', operator: 'lessThan', value: 10 },
],
},
};
// Triggers if customer is new OR quantity < 10Nested Conditions
Combine ALL and ANY for complex logic:
const conditionConfig = {
conditions: {
all: [
{ fact: 'proposed_discount', operator: 'greaterThan', value: 0.2 },
{
any: [
{ fact: 'customer_segment', operator: 'notEqual', value: 'platinum' },
{ fact: 'order_value', operator: 'lessThan', value: 10000 },
],
},
],
},
};
// Discount > 20% AND (not platinum OR order < $10k)Available Operators
| Operator | Description | Example |
|---|---|---|
equal | Exact match | { fact: 'segment', operator: 'equal', value: 'gold' } |
notEqual | Not equal | { fact: 'segment', operator: 'notEqual', value: 'new' } |
lessThan | Less than | { fact: 'margin', operator: 'lessThan', value: 0.15 } |
lessThanInclusive | Less than or equal | { fact: 'discount', operator: 'lessThanInclusive', value: 0.25 } |
greaterThan | Greater than | { fact: 'quantity', operator: 'greaterThan', value: 100 } |
greaterThanInclusive | Greater than or equal | { fact: 'value', operator: 'greaterThanInclusive', value: 5000 } |
in | Value in array | { fact: 'segment', operator: 'in', value: ['gold', 'platinum'] } |
notIn | Value not in array | { fact: 'category', operator: 'notIn', value: ['clearance'] } |
contains | Array contains value | { fact: 'tags', operator: 'contains', value: 'vip' } |
Constraint Evaluation Order
Constraints are evaluated by rule priority (higher numbers first). Use priorities to:
- Fail fast: Check time/eligibility constraints first
- Layer logic: Apply volume tiers before final caps
- Ensure order: Run margin checks before stacking rules