Regulatory Engine
The regulatory module implements a visual, graph-based rules engine for evaluating building regulations. Rules are created in the admin panel using a ReactFlow node graph editor and evaluated on the backend.
Concepts
Rules
A RegulatoryRule represents a single regulation or by-law. Each rule contains:
- Parameters — Input variables required and output variables produced
- Graph — A ReactFlow node/edge graph that defines the computation logic
- Metadata — Authority, region, regulatory reference, tags
Variables
A RegulatoryVariable is a globally-registered input or output parameter:
site.area → number (sqm) [INPUT]
site.road_width → number (m) [INPUT]
result.max_far → number [OUTPUT]
result.max_height → number (m) [OUTPUT]
result.setback.front → number (m) [OUTPUT]
Graph Evaluation
The rule graph is a DAG (directed acyclic graph) of computation nodes:
┌───────────┐ ┌──────────────┐ ┌────────────┐
│ Input: │────▶│ Condition: │────▶│ Output: │
│ site.area │ │ area > 2000 │ │ max_far │
└───────────┘ │ ? 2.5 │ │ = result │
│ : 1.75 │ └────────────┘
└──────────────┘
Node types include:
- Input — Reads a variable value
- Constant — Fixed numeric/boolean/string value
- Comparison —
>,<,>=,<=,==,!= - Arithmetic —
+,-,*,/ - Conditional — If/then/else branching
- Output — Writes a result variable
- Math Functions —
min,max,round,ceil,floor
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /regulatory/rules | List all rules |
POST | /regulatory/rules | Create a new rule |
GET | /regulatory/rules/:id | Get rule details (including graph) |
PATCH | /regulatory/rules/:id | Update a rule |
DELETE | /regulatory/rules/:id | Delete a rule |
POST | /regulatory/rules/:id/evaluate | Evaluate a rule with given inputs |
GET | /regulatory/variables | List all registered variables |
POST | /regulatory/variables | Register a new variable |
DELETE | /regulatory/variables/:key | Delete a variable |
Evaluation
To evaluate a rule:
// POST /regulatory/rules/RUL-001/evaluate
{
"inputs": {
"site.area": 4000,
"site.road_width": 12,
"site.zone": "residential"
}
}
// Response
{
"outputs": {
"result.max_far": 2.5,
"result.max_height": 24,
"result.setback.front": 3,
"result.setback.rear": 2
}
}
The backend traverses the rule graph using math.js for expression evaluation, resolving node dependencies in topological order.