Security Analytics - v1.0.0

Incident Response

IncidentResponder runs sequences of automated actions when an anomaly or rule matches. Each step is a pluggable action implementing ResponseActionInterface.

Shipped actions

Action What it does
BlockIpAction Add the IP to a blocklist (via cache / firewall)
BlockUserAction Set the user to "blocked" via your blocking trait
EnableEnhancedLoggingAction Bump logging verbosity for the affected user/IP
ForcePasswordResetAction Invalidate the user's password and email a reset link
LockAccountAction Lock the user account for the configured duration
LogEventAction Write an audit entry to a custom log channel
NotifyAdminAction Send notification to the admin team via alerting channels
RateLimitIpAction Apply a stricter rate limit to the IP
RequireTwoFactorAction Force the user to set up 2FA on next login
RevokeSessionsAction Revoke all of the user's active sessions
TerminateSessionAction Terminate just the offending session

Defining a playbook

A playbook is a sequence of action definitions. Store them in response_playbooks table or declare in config:

'incident_response' => [
    'enabled' => true,
    'playbooks' => [
        'brute_force_response' => [
            'trigger' => ['detector' => 'brute_force', 'severity' => 'high'],
            'actions' => [
                ['action' => 'block_ip', 'duration_minutes' => 60],
                ['action' => 'notify_admin', 'channel' => 'slack'],
                ['action' => 'lock_account', 'duration_minutes' => 30],
            ],
        ],
        'credential_stuffing_response' => [
            'trigger' => ['detector' => 'credential_stuffing'],
            'actions' => [
                ['action' => 'block_ip', 'duration_minutes' => 240],
                ['action' => 'enable_enhanced_logging'],
            ],
        ],
    ],
],

Or via the ResponsePlaybook model for DB-driven, runtime-editable playbooks:

ResponsePlaybook::create([
    'name'    => 'Critical anomaly auto-block',
    'trigger' => ['severity' => 'critical'],
    'actions' => [...],
    'enabled' => true,
]);

Triggering a playbook

IncidentResponder listens for AnomalyDetected events automatically (when incident_response.enabled = true). For manual triggering:

security_analytics()->responder()->runPlaybook(
    playbookSlug: 'brute_force_response',
    context: ['user' => $user, 'ip' => $ip],
);

Each action's result is captured in a SecurityIncident record so you have a full audit trail of what was done in response to what trigger.

Action results

Each ResponseActionInterface::execute(array $context): ActionResult returns:

$result->success;   // bool
$result->message;   // human-readable
$result->context;   // array — preserved for downstream actions in the same playbook

If an action returns success: false, the playbook can be configured to either continue or abort. Default is continue — partial response is usually better than no response.

Building a custom action

Implement ResponseActionInterface (execute, getName) and register your class. The package's AbstractAction base class handles common boilerplate (logging, error capture, context merging). See Custom actions.