brigada/guardian

Laravel project monitoring package — security audits, health checks, Discord notifications

Maintainers

Package info

github.com/Brigada-Group/guardian

Language:Blade

pkg:composer/brigada/guardian

Statistics

Installs: 9

Dependents: 0

Suggesters: 0

Stars: 4

Open Issues: 0

v1.1.2 2026-04-24 13:35 UTC

README

Private Laravel monitoring package. Runs security audits, health checks, and real-time event monitoring. Reports everything to Discord — with a built-in web dashboard.

Think of it as Nightwatch for Laravel — but self-hosted, Discord-native, and with a full monitoring dashboard.

Requirements

  • PHP ^8.2
  • Laravel ^11.0 or ^12.0
  • Discord webhook URL
  • Membership in the Brigada-Group GitHub organization

Team Access Setup

Before installing, each developer needs access to the private repository:

For org admins

  1. Go to Brigada-Group members
  2. Click Invite member and enter the developer's GitHub username or email
  3. Grant access to the guardian repository (at minimum Read role)

For developers

Once you've accepted the org invite, create a personal access token:

  1. Go to GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)
  2. Click Generate new token (classic)
  3. Name it something like composer-brigada
  4. Select the repo scope (required for private repos)
  5. Click Generate token and copy the ghp_... value immediately

Then configure Composer (one-time per machine):

composer config --global github-oauth.github.com ghp_YOUR_TOKEN

Note: Use --global so the token works across all projects on your machine. Never commit tokens to version control.

Installation

Add the private repository to your project's composer.json:

{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/Brigada-Group/guardian.git"
        }
    ]
}

Install the package:

composer require brigada/guardian
php artisan guardian:install

Add to your .env:

GUARDIAN_DISCORD_WEBHOOK=https://discord.com/api/webhooks/xxx/yyy
GUARDIAN_PROJECT_NAME="Your Project Name"
GUARDIAN_ENVIRONMENT=production

Verify it works:

php artisan guardian:test

What It Monitors

Cron-Based Health Checks (23 checks)

Schedule Checks
Every 5 min Failed job spikes, stale queue jobs, scheduler heartbeat
Hourly Disk space, memory, database/Redis connectivity, log error spikes, queue sizes, Horizon status, storage size
Daily Composer audit, npm audit, SSL certificate expiry, .env safety, file permissions, pending migrations, PHP/OS version EOL, config cache staleness, insecure packages, CSRF/CORS config
Weekly Full trend report comparing this week vs last week

Real-Time Event Monitoring (8 categories)

Category What It Captures Alerts On
Requests Every HTTP request (method, URI, duration, status) Slow requests (>5s), high error rates
Outgoing HTTP External API calls via Laravel HTTP client Slow responses, 5xx errors, connection failures
Database Queries Slow queries and N+1 patterns Queries exceeding threshold, N+1 detection
Mail Email send/fail events Delivery failures
Notifications All notification channel results Failed notifications on any channel
Cache Hit/miss ratios (aggregated per minute) Low hit rate (<50%)
Commands Artisan command execution and exit codes Failed commands (non-zero exit), slow commands
Scheduled Tasks Individual task completion, duration, failures Failed tasks, slow tasks

Exception Tracking

Every uncaught exception is sent to Discord in real-time with:

  • Exception class, message, and stack trace
  • URL, status code, user info, IP address
  • Deduplication (same exception only alerts once per 5 minutes)

Dashboard

Guardian includes a built-in monitoring dashboard accessible at /guardian (configurable). It provides a real-time view of all monitoring data with interactive charts and tables.

Pages

Page What It Shows
Overview Key metrics (requests, error rate, response time, cache hit rate), response time and error charts, recent alerts
Requests Response time histogram, slowest endpoints, filterable request log
Queries Slow queries, N+1 detections, query volume trends
Outgoing HTTP External API performance by host, failure rates
Jobs & Scheduler Command exit codes, scheduled task status, failures
Mail Sent vs failed chart, delivery failures
Notifications Channel breakdown, failure rates by channel
Cache Hit rate over time, per-store breakdown, read/write ratios
Exceptions Grouped by class, occurrence counts, trend chart, expandable details
Health Checks Status grid for all 23 checks, Run Now buttons

Stack

  • Blade + Alpine.js 3 + Chart.js 4 via CDN — zero build step required
  • 30-second polling with automatic pause when tab is hidden or idle
  • Dark/light mode toggle with localStorage persistence
  • Self-contained — no impact on your host app's middleware, routes, or assets

Enabling the Dashboard

The dashboard is enabled by default. Configure it in config/guardian.php:

'dashboard' => [
    'enabled' => true,
    'path' => 'guardian',           // URL prefix: /guardian
    'allowed_ips' => [],            // Empty = no IP restriction
    'poll_interval' => 30,          // Seconds between data refreshes
    'per_page' => 50,               // Rows per table page
],

Access Control

The dashboard requires both a Gate check and an optional IP whitelist.

1. Define the gate in your AuthServiceProvider or AppServiceProvider:

use Illuminate\Support\Facades\Gate;

Gate::define('viewGuardianDashboard', function ($user) {
    return $user->is_admin; // Your logic here
});

2. Optionally restrict by IP:

'dashboard' => [
    'allowed_ips' => ['127.0.0.1', '10.0.0.0/24'],
],

If allowed_ips is empty, only the gate check is enforced.

API Endpoints

Each dashboard page has a corresponding JSON API endpoint at /guardian/api/{section}. These are rate-limited (60 requests/minute per IP) and return Cache-Control: no-store headers. The dashboard's own requests are excluded from Guardian's request monitoring.

Security

Guardian includes several security features to protect sensitive data in monitoring logs and Discord alerts.

SQL Sanitization

Sensitive values in SQL queries are redacted before storage:

// Stored as: select * from users where email = '[REDACTED]' and id = ?
'security' => [
    'sanitize_sql' => true,     // Enabled by default
],

Stack Trace Sanitization

Exception messages and stack traces sent to Discord are automatically cleaned:

  • Base paths stripped from file references
  • Values after password=, token=, secret=, key=, authorization= are redacted
  • Bearer tokens are redacted

Header Filtering

Only safe headers are included in Discord exception alerts (whitelist approach):

'security' => [
    'safe_headers' => ['User-Agent', 'Referer', 'Accept', 'Content-Type'],
],

Headers like Authorization, Cookie, X-CSRF-Token, and X-API-Key are never sent to Discord.

IP Anonymization (GDPR)

Optionally anonymize IP addresses in request logs:

'security' => [
    'anonymize_ip' => false,    // Set to true to enable
],

When enabled, the last octet of IPv4 addresses is zeroed (192.168.1.42 becomes 192.168.1.0), and the last 80 bits of IPv6 addresses are zeroed.

Mail Recipient Hashing

Optionally hash email recipients before storage:

'security' => [
    'hash_mail_recipients' => false,    // Set to true to enable
],

When enabled, email addresses are stored as SHA-256 hashes, allowing unique recipient counting without storing PII.

Discord Webhook Validation

Guardian validates that the configured webhook URL points to a Discord domain (discord.com or discordapp.com). Non-Discord URLs trigger a warning log but are still allowed (for proxy setups).

Commands

php artisan guardian:install                     # One-liner setup (config + migrations)
php artisan guardian:test                        # Send test notification to Discord
php artisan guardian:run hourly                   # Run hourly checks
php artisan guardian:run daily                    # Run daily checks
php artisan guardian:run --check=DiskSpaceCheck   # Run a single check
php artisan guardian:status                       # View latest results locally
php artisan guardian:prune                        # Delete old monitoring data
php artisan guardian:prune --days=7               # Override retention period
php artisan guardian:prune --dry-run              # Preview what would be deleted

Configuration

Publish and edit config/guardian.php:

php artisan vendor:publish --tag=guardian-config

Disable checks

'disabled_checks' => [
    \Brigada\Guardian\Checks\HorizonStatusCheck::class,
    \Brigada\Guardian\Checks\NpmAuditCheck::class,
],

Adjust health check thresholds

'thresholds' => [
    'disk_percent' => ['warning' => 70, 'critical' => 85],
    'queue_size'   => ['warning' => 50, 'critical' => 200],
    'db_response_ms' => ['warning' => 50, 'critical' => 200],
],

Configure real-time monitoring

Each monitoring category can be individually enabled/disabled with its own thresholds:

'monitoring' => [
    'requests' => [
        'enabled' => true,
        'slow_threshold_ms' => 5000,
        'error_rate_threshold' => 50,
        'error_rate_window_minutes' => 5,
    ],
    'queries' => [
        'enabled' => true,
        'slow_threshold_ms' => 500,
        'n_plus_one_threshold' => 10,
    ],
    'outgoing_http' => [
        'enabled' => true,
        'slow_threshold_ms' => 10000,
    ],
    'cache' => [
        'enabled' => true,
        'low_hit_rate_threshold' => 50,
    ],
    'commands' => [
        'enabled' => true,
        'slow_threshold_ms' => 60000,
        'ignored' => ['some:noisy-command'],
    ],
    'scheduled_tasks' => [
        'enabled' => true,
        'slow_threshold_ms' => 300000,
    ],
],

Data retention

Control how long monitoring data is kept before guardian:prune cleans it up:

'retention' => [
    'results_days' => 30,
    'request_logs_days' => 7,
    'query_logs_days' => 7,
    'cache_logs_days' => 7,
    'mail_logs_days' => 30,
    'command_logs_days' => 30,
    'scheduled_task_logs_days' => 30,
],

Environment gating

'enabled_environments' => ['production', 'staging'],

Ignored exceptions

'exceptions' => [
    'enabled' => true,
    'dedup_minutes' => 5,
    'ignored_exceptions' => [
        \Symfony\Component\HttpKernel\Exception\NotFoundHttpException::class,
        \Illuminate\Auth\AuthenticationException::class,
    ],
],

Request Monitoring Middleware

The request monitoring middleware is available as Brigada\Guardian\Http\Middleware\RequestMonitor. Register it in your application's middleware stack to capture request metrics.

For Laravel 11+ (bootstrap/app.php):

->withMiddleware(function (Middleware $middleware) {
    $middleware->append(\Brigada\Guardian\Http\Middleware\RequestMonitor::class);
})

For Laravel 10 (app/Http/Kernel.php):

protected $middleware = [
    // ...
    \Brigada\Guardian\Http\Middleware\RequestMonitor::class,
];

Scheduling

Guardian auto-registers its cron checks via the service provider. Ensure the Laravel scheduler is running:

* * * * * cd /path-to-project && php artisan schedule:run >> /dev/null 2>&1

Schedule times are configurable:

'notifications' => [
    'daily_summary_time' => '06:00',
    'weekly_summary_day' => 'monday',
],

Discord Notifications

  • Color-coded embeds: red = critical, orange = warning, green = ok, blue = test
  • Duplicate alerts suppressed within configurable windows (default: 60 min for checks, 5 min for events)
  • Daily and weekly summary reports aggregate all check results
  • Rate limit handling with automatic retry on 429 responses

CI / Server Setup

For CI pipelines and production servers, use a token stored as a secret.

GitHub Actions

Add COMPOSER_GITHUB_TOKEN as a repository secret, then:

- run: composer config github-oauth.github.com ${{ secrets.COMPOSER_GITHUB_TOKEN }}
- run: composer install

Production Servers

composer config --global github-oauth.github.com ghp_YOUR_DEPLOY_TOKEN

Use a dedicated machine user or fine-grained token with read-only access to the guardian repo.

Database Tables

Guardian creates the following tables:

Table Purpose
guardian_results Health check results + deduplication
guardian_request_logs HTTP request metrics
guardian_outgoing_http_logs External API call tracking
guardian_query_logs Slow queries and N+1 patterns
guardian_mail_logs Email delivery tracking
guardian_notification_logs Notification channel results
guardian_cache_logs Cache hit/miss aggregations
guardian_command_logs Artisan command execution
guardian_scheduled_task_logs Scheduled task tracking