< Summary

Information
Class: Intentum.Core.Fraud.FraudRules
Assembly: Intentum.Core
File(s): /home/runner/work/Intentum/Intentum/src/Intentum.Core/Fraud/FraudRules.cs
Line coverage
95%
Covered lines: 60
Uncovered lines: 3
Coverable lines: 63
Total lines: 102
Line coverage: 95.2%
Branch coverage
80%
Covered branches: 21
Total branches: 26
Branch coverage: 80.7%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
AccountTakeover(...)100%1212100%
CredentialStuffing(...)50%4490.9%
PaymentFraud(...)75%8892.85%
AccountRecovery(...)50%2292.85%
AllRules()100%11100%

File(s)

/home/runner/work/Intentum/Intentum/src/Intentum.Core/Fraud/FraudRules.cs

#LineLine coverage
 1using Intentum.Core.Behavior;
 2using Intentum.Core.Models;
 3
 4namespace Intentum.Core.Fraud;
 5
 6/// <summary>
 7/// Pre-built fraud detection rules for common attack patterns.
 8/// Use with RuleBasedIntentModel or ChainedIntentModel.
 9/// </summary>
 10public static class FraudRules
 11{
 12    /// <summary>
 13    /// Detects account takeover attempts: multiple failed logins + password reset + IP/device change.
 14    /// </summary>
 15    public static Func<BehaviorSpace, RuleMatch?> AccountTakeover(
 16        int minFailedLogins = 3,
 417        double confidence = 0.9) => space =>
 318    {
 319        var failedLogins = space.Events.Count(e =>
 1220            e.Action.Contains("login.failed", StringComparison.OrdinalIgnoreCase) ||
 1221            e.Action.Contains("FailedLogin", StringComparison.OrdinalIgnoreCase));
 322        var hasIpChange = space.Events.Any(e =>
 1223            e.Action.Contains("ip.changed", StringComparison.OrdinalIgnoreCase) ||
 1224            e.Action.Contains("device.new", StringComparison.OrdinalIgnoreCase) ||
 1225            e.Action.Contains("NewDevice", StringComparison.OrdinalIgnoreCase));
 326        var hasPasswordReset = space.Events.Any(e =>
 1227            e.Action.Contains("password.reset", StringComparison.OrdinalIgnoreCase) ||
 1228            e.Action.Contains("PasswordReset", StringComparison.OrdinalIgnoreCase));
 429
 330        if (failedLogins >= minFailedLogins && (hasIpChange || hasPasswordReset))
 231            return new RuleMatch("AccountTakeover", confidence,
 232                $"Failed logins: {failedLogins}, IP change: {hasIpChange}, password reset: {hasPasswordReset}");
 133        return null;
 734    };
 35
 36    /// <summary>
 37    /// Detects credential stuffing: high-frequency login attempts from different actors.
 38    /// </summary>
 39    public static Func<BehaviorSpace, RuleMatch?> CredentialStuffing(
 40        int minAttempts = 5,
 241        double confidence = 0.85) => space =>
 142    {
 143        var loginAttempts = space.Events.Count(e =>
 644            e.Action.Contains("login", StringComparison.OrdinalIgnoreCase));
 645        var uniqueActors = space.Events.Select(e => e.Actor).Distinct().Count();
 246
 147        if (loginAttempts >= minAttempts && uniqueActors >= 3)
 148            return new RuleMatch("CredentialStuffing", confidence,
 149                $"Login attempts: {loginAttempts} from {uniqueActors} actors");
 050        return null;
 351    };
 52
 53    /// <summary>
 54    /// Detects payment fraud: rapid high-value transactions, card testing patterns.
 55    /// </summary>
 56    public static Func<BehaviorSpace, RuleMatch?> PaymentFraud(
 57        int minTransactions = 3,
 258        double confidence = 0.8) => space =>
 159    {
 160        var payments = space.Events.Count(e =>
 661            e.Action.Contains("payment", StringComparison.OrdinalIgnoreCase) ||
 662            e.Action.Contains("transaction", StringComparison.OrdinalIgnoreCase));
 163        var declines = space.Events.Count(e =>
 664            e.Action.Contains("declined", StringComparison.OrdinalIgnoreCase) ||
 665            e.Action.Contains("failed", StringComparison.OrdinalIgnoreCase));
 266
 167        if (payments >= minTransactions && declines >= 2)
 168            return new RuleMatch("PaymentFraud", confidence,
 169                $"Payments: {payments}, declines: {declines}");
 070        return null;
 371    };
 72
 73    /// <summary>
 74    /// Detects legitimate account recovery: failed login + password reset + successful login.
 75    /// </summary>
 76    public static Func<BehaviorSpace, RuleMatch?> AccountRecovery(
 277        double confidence = 0.85) => space =>
 178    {
 179        var hasFailed = space.Events.Any(e =>
 280            e.Action.Contains("login.failed", StringComparison.OrdinalIgnoreCase));
 181        var hasReset = space.Events.Any(e =>
 382            e.Action.Contains("password.reset", StringComparison.OrdinalIgnoreCase));
 183        var hasSuccess = space.Events.Any(e =>
 484            e.Action.Contains("login.success", StringComparison.OrdinalIgnoreCase));
 285
 186        if (hasFailed && hasReset && hasSuccess)
 187            return new RuleMatch("AccountRecovery", confidence,
 188                "Pattern: failed login -> password reset -> successful login");
 089        return null;
 390    };
 91
 92    /// <summary>
 93    /// Returns all standard fraud detection rules in recommended evaluation order.
 94    /// </summary>
 95    public static IReadOnlyList<Func<BehaviorSpace, RuleMatch?>> AllRules() =>
 196    [
 197        AccountTakeover(),
 198        CredentialStuffing(),
 199        PaymentFraud(),
 1100        AccountRecovery()
 1101    ];
 102}