Notifications
When audit:verify --notify detects a chain integrity failure, AuditChain sends alerts through your configured channels. This ensures your security team is notified immediately, whether they monitor email, Slack, Microsoft Teams, or Discord.
Configuration
Configure notification channels in config/audit-chain.php:
'notifications' => [ 'channels' => ['mail', 'webhook'], 'mail_to' => [env('AUDIT_ALERT_EMAIL', '')], 'webhooks' => [ env('AUDIT_ALERT_WEBHOOK_1'), ], ],
| Key | Default | Description |
|---|---|---|
channels |
['mail'] |
Which channels to use: mail, webhook, or both |
mail_to |
[] |
Email addresses for mail alerts |
webhooks |
[] |
Webhook URLs for Slack, Teams, Discord, or custom endpoints |
Triggering Notifications
Notifications are only sent when you pass the --notify flag to the verify command:
php artisan audit:verify --notify
If the chain is valid, nothing is sent. Notifications fire only on failure.
Mail Notifications
AuditChain uses Laravel's notification system with the ChainCompromised notification class. The via() method is hardcoded to ['mail'] — webhooks are handled separately by the verify command. The email includes:
- The number of errors detected and logs checked
- A description of what the failure may indicate (tampering, unauthorized deletion, or database corruption)
- The first 10 error details with audit log IDs
- A call to action for immediate investigation
Setup
Add your alert email to .env:
AUDIT_ALERT_EMAIL=security@yourcompany.com
For multiple recipients, add them directly in the config:
'notifications' => [ 'channels' => ['mail'], 'mail_to' => [ 'security@yourcompany.com', 'cto@yourcompany.com', 'compliance@yourcompany.com', ], ],
Make sure your application's mail configuration is set up correctly — AuditChain uses the same mail transport as the rest of your Laravel application.
Webhook Notifications
Webhook payloads are designed for cross-platform compatibility. Each payload includes both text and content keys, covering the formats expected by Slack, Microsoft Teams, and Discord.
Payload Format
{ "text": "[MyApp] AUDIT CHAIN COMPROMISED\n\n3 error(s) detected out of 1500 log(s) checked.\n\n- [01jk...] Chain break: prev_hash does not match expected value.\n- [01jk...] Hash mismatch: stored hash does not match computed hash.\n- [01jk...] Hash mismatch: stored hash does not match computed hash.\n\nImmediate investigation required.", "content": "[MyApp] AUDIT CHAIN COMPROMISED\n\n3 error(s) detected out of 1500 log(s) checked.\n\n- [01jk...] Chain break: prev_hash does not match expected value.\n- [01jk...] Hash mismatch: stored hash does not match computed hash.\n- [01jk...] Hash mismatch: stored hash does not match computed hash.\n\nImmediate investigation required." }
The text key is used by Slack and Microsoft Teams. The content key is used by Discord. Both contain the same message. If there are more than 5 errors, the payload shows the first 5 and summarizes the rest.
Slack
Create an Incoming Webhook in your Slack workspace and add the URL to your .env:
AUDIT_ALERT_WEBHOOK_1=https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
Microsoft Teams
Create an Incoming Webhook connector in your Teams channel:
AUDIT_ALERT_WEBHOOK_1=https://outlook.office.com/webhook/...
Discord
Create a webhook in your Discord channel settings (Integrations > Webhooks). Append /slack to the URL to use Slack-compatible formatting:
AUDIT_ALERT_WEBHOOK_1=https://discord.com/api/webhooks/000000000000000000/XXXXXXXXXXXX/slack
Multiple Webhooks
You can send to multiple platforms simultaneously:
'notifications' => [ 'channels' => ['mail', 'webhook'], 'mail_to' => [env('AUDIT_ALERT_EMAIL', '')], 'webhooks' => [ env('AUDIT_ALERT_SLACK_WEBHOOK'), env('AUDIT_ALERT_TEAMS_WEBHOOK'), env('AUDIT_ALERT_DISCORD_WEBHOOK'), ], ],
Custom Endpoints
Any HTTP endpoint that accepts a JSON POST request works as a webhook target. The payload is sent as-is — parse the text field in your receiving application.
Security and Reliability
Webhook delivery includes several safety measures:
- SSRF protection: Webhook URLs must use HTTPS. Private and reserved IP ranges are blocked — the URL's hostname is resolved via
gethostbyname()and validated withFILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGEto prevent Server-Side Request Forgery. - Error handling: Webhook delivery is wrapped in a try-catch. If a webhook request fails (network error, timeout, non-2xx response), a warning is logged instead of crashing the verify command.
- HTTP timeout: All webhook requests use
Http::timeout(10)to avoid hanging indefinitely on unresponsive endpoints.
Automated Monitoring
For continuous monitoring, schedule verification with the --notify flag:
// routes/console.php Schedule::command('audit:verify --notify')->hourly();
See Scheduling for the full recommended cron setup.