Prerequisites
- .NET 9 SDK (the engine targets net9.0)
git- Optional: a DocumentForge instance (local
dfdb serveor hosted)
1. Clone and build
git clone https://github.com/tailwind-retailing/ruleforge.git
cd ruleforge
dotnet build
dotnet test # 126/126 green
2. Run a sample rule, in-process, against the bundled fixtures
The repo ships with versioned rule snapshots under fixtures/rules/ and matching scenarios under fixtures/scenarios/. The default binding points POST /v1/ancillary/bag-policy at rule-bag-policy@7.
dotnet run --project src/RuleForge.Cli -- run \
--endpoint /v1/ancillary/bag-policy \
--request '@fixtures/scenarios/s-bag-3pc-markup15.json' \
--debug
You'll see the rule's full per-node trace plus the assembled result:
{
"ruleId": "rule-bag-policy",
"ruleVersion": 7,
"decision": "apply",
"evaluatedAt": "2026-04-27T10:10:20.141Z",
"result": {
"code": "BAG", "weightKg": 23,
"currency": "AED", "fee": 517.5, "pieces": 3
},
"trace": [
{ "nodeId": "n5-bag", "outcome": "pass", "output": { /* base bag */ } },
{ "nodeId": "n6-pieces", "outcome": "pass", "output": { /* +pieces:3 */ } },
{ "nodeId": "n7-fee", "outcome": "pass", "output": { /* fee:450 */ } },
{ "nodeId": "n8-markup", "outcome": "pass", "output": { /* fee:517.5 */ } }
],
"durationMs": 47
}
3. Stand up the HTTP API
dotnet run --project src/RuleForge.Api
Boot output lists every endpoint that has an environment binding:
info: Bound POST /v1/ancillary/bag-policy → rule-bag-policy@7 info: Bound POST /v1/ancillary/tier-bonus → rule-tier-bonus@1 info: Now listening on: http://localhost:5050
curl -X POST http://localhost:5050/v1/ancillary/bag-policy \ -H 'content-type: application/json' \ --data @fixtures/scenarios/s-bag-3pc-markup15.json
4. Switch to DocumentForge
Swap the rule source by setting environment variables. The engine resolves endpoint + method → ruleId → version → snapshot on first call and caches each step.
# local DocumentForge (recommended for prod-like perf)
RULEFORGE_RULE_SOURCE=df \
RULEFORGE_DF_BASE_URL=http://localhost:5000 \
RULEFORGE_DF_API_KEY=your-key \
RULEFORGE_ENV=staging \
dotnet run --project src/RuleForge.Api
5. Add API auth
Set RULEFORGE_API_KEY and the engine starts rejecting requests that don't supply X-AERO-Key or Authorization: Bearer with the matching key. /health stays open for liveness probes.
RULEFORGE_API_KEY=secret dotnet run --project src/RuleForge.Api curl -X POST http://localhost:5050/v1/ancillary/bag-policy \ -H 'X-AERO-Key: secret' \ -H 'content-type: application/json' \ --data @fixtures/scenarios/s-bag-3pc-markup15.json
What's next
- Rule Schema — the JSON shape of a rule, node by node.
- Evaluators — every filter / logic / mutator / calc semantic, with edge cases.
- Sub-Rules — invoking another rule from a node.
- CLI Reference — every flag of
run,publish,mirror,bench. - Deployment — Docker, Render, env vars, co-located DF.