Skip to main content

6.1 Naming Conventions

Rules:
  • Use PascalCase or PascalCase_With_Underscores.
  • Name should describe the fraud pattern, not the implementation detail.
  • Good: HighFrequencyDestination, DormantAccountActivity
  • Bad: CheckAmount, Rule_v2_final
Variables:
  • Use $snake_case.
  • Good: $sanctioned_countries, $high_risk_bins
  • Bad: $myList, $SC

6.2 One Rule, One Purpose

Each .ws file should contain a single rule that detects a single, specific fraud pattern. This provides:
  • Clear audit trails: When a transaction is blocked, you know exactly which pattern triggered it.
  • Independent tuning: You can adjust the score of one rule without affecting others.
  • Clean version history: Git diffs show exactly what changed and why.
Don’t do this:
Do this instead: Write three separate rules, each with its own score, reason, and description.

6.3 Writing Clear Descriptions

Your description should answer three questions:
  1. What does this rule detect?
  2. Why is this pattern suspicious?
  3. What is the expected action?

6.4 Performance Considerations

Order your and conditions wisely. Place cheap checks before expensive checks. The interpreter uses short-circuit evaluation, so if the first condition fails, the expensive ones are never executed.
Keep time windows as small as possible. "PT1H" is much faster to query than "P30D". Use the smallest window that effectively catches the pattern. Avoid overly complex regex. Catastrophic backtracking in regex can cause severe performance degradation. Keep patterns simple and specific. Avoid nested quantifiers like (.+)+.

6.5 Scoring Strategy

Adopt a consistent scoring philosophy across your entire rule set: The risk consolidator aggregates scores. If multiple rules fire with 0.3 scores, the combined risk may still escalate the transaction to a block. Design your scores with this aggregation in mind.

6.6 Common Pitfalls